1 /* $OpenBSD: uark.c,v 1.1 2006/08/14 08:30:22 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $FreeBSD$ 19 */ 20 21 /* 22 * NOTE: all function names beginning like "uark_cfg_" can only 23 * be called from within the config thread function ! 24 */ 25 26 #include "usbdevs.h" 27 #include <dev/usb/usb.h> 28 #include <dev/usb/usb_mfunc.h> 29 #include <dev/usb/usb_error.h> 30 #include <dev/usb/usb_cdc.h> 31 32 #define USB_DEBUG_VAR usb2_debug 33 34 #include <dev/usb/usb_core.h> 35 #include <dev/usb/usb_debug.h> 36 #include <dev/usb/usb_process.h> 37 #include <dev/usb/usb_request.h> 38 #include <dev/usb/usb_lookup.h> 39 #include <dev/usb/usb_util.h> 40 41 #include <dev/usb/serial/usb_serial.h> 42 43 #define UARK_BUF_SIZE 1024 /* bytes */ 44 45 #define UARK_SET_DATA_BITS(x) ((x) - 5) 46 47 #define UARK_PARITY_NONE 0x00 48 #define UARK_PARITY_ODD 0x08 49 #define UARK_PARITY_EVEN 0x18 50 51 #define UARK_STOP_BITS_1 0x00 52 #define UARK_STOP_BITS_2 0x04 53 54 #define UARK_BAUD_REF 3000000 55 56 #define UARK_WRITE 0x40 57 #define UARK_READ 0xc0 58 59 #define UARK_REQUEST 0xfe 60 61 #define UARK_CONFIG_INDEX 0 62 #define UARK_IFACE_INDEX 0 63 64 enum { 65 UARK_BULK_DT_WR, 66 UARK_BULK_DT_RD, 67 UARK_N_TRANSFER, 68 }; 69 70 struct uark_softc { 71 struct usb2_com_super_softc sc_super_ucom; 72 struct usb2_com_softc sc_ucom; 73 74 struct usb2_xfer *sc_xfer[UARK_N_TRANSFER]; 75 struct usb2_device *sc_udev; 76 77 uint8_t sc_msr; 78 uint8_t sc_lsr; 79 }; 80 81 /* prototypes */ 82 83 static device_probe_t uark_probe; 84 static device_attach_t uark_attach; 85 static device_detach_t uark_detach; 86 87 static usb2_callback_t uark_bulk_write_callback; 88 static usb2_callback_t uark_bulk_read_callback; 89 90 static void uark_start_read(struct usb2_com_softc *); 91 static void uark_stop_read(struct usb2_com_softc *); 92 static void uark_start_write(struct usb2_com_softc *); 93 static void uark_stop_write(struct usb2_com_softc *); 94 static int uark_pre_param(struct usb2_com_softc *, struct termios *); 95 static void uark_cfg_param(struct usb2_com_softc *, struct termios *); 96 static void uark_cfg_get_status(struct usb2_com_softc *, uint8_t *, 97 uint8_t *); 98 static void uark_cfg_set_break(struct usb2_com_softc *, uint8_t); 99 static void uark_cfg_write(struct uark_softc *, uint16_t, uint16_t); 100 101 static const struct usb2_config 102 uark_xfer_config[UARK_N_TRANSFER] = { 103 104 [UARK_BULK_DT_WR] = { 105 .type = UE_BULK, 106 .endpoint = UE_ADDR_ANY, 107 .direction = UE_DIR_OUT, 108 .mh.bufsize = UARK_BUF_SIZE, 109 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 110 .mh.callback = &uark_bulk_write_callback, 111 }, 112 113 [UARK_BULK_DT_RD] = { 114 .type = UE_BULK, 115 .endpoint = UE_ADDR_ANY, 116 .direction = UE_DIR_IN, 117 .mh.bufsize = UARK_BUF_SIZE, 118 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 119 .mh.callback = &uark_bulk_read_callback, 120 }, 121 }; 122 123 static const struct usb2_com_callback uark_callback = { 124 .usb2_com_cfg_get_status = &uark_cfg_get_status, 125 .usb2_com_cfg_set_break = &uark_cfg_set_break, 126 .usb2_com_cfg_param = &uark_cfg_param, 127 .usb2_com_pre_param = &uark_pre_param, 128 .usb2_com_start_read = &uark_start_read, 129 .usb2_com_stop_read = &uark_stop_read, 130 .usb2_com_start_write = &uark_start_write, 131 .usb2_com_stop_write = &uark_stop_write, 132 }; 133 134 static device_method_t uark_methods[] = { 135 /* Device methods */ 136 DEVMETHOD(device_probe, uark_probe), 137 DEVMETHOD(device_attach, uark_attach), 138 DEVMETHOD(device_detach, uark_detach), 139 {0, 0} 140 }; 141 142 static devclass_t uark_devclass; 143 144 static driver_t uark_driver = { 145 .name = "uark", 146 .methods = uark_methods, 147 .size = sizeof(struct uark_softc), 148 }; 149 150 DRIVER_MODULE(uark, ushub, uark_driver, uark_devclass, NULL, 0); 151 MODULE_DEPEND(uark, ucom, 1, 1, 1); 152 MODULE_DEPEND(uark, usb, 1, 1, 1); 153 154 static const struct usb2_device_id uark_devs[] = { 155 {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)}, 156 }; 157 158 static int 159 uark_probe(device_t dev) 160 { 161 struct usb2_attach_arg *uaa = device_get_ivars(dev); 162 163 if (uaa->usb2_mode != USB_MODE_HOST) { 164 return (ENXIO); 165 } 166 if (uaa->info.bConfigIndex != 0) { 167 return (ENXIO); 168 } 169 if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) { 170 return (ENXIO); 171 } 172 return (usb2_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa)); 173 } 174 175 static int 176 uark_attach(device_t dev) 177 { 178 struct usb2_attach_arg *uaa = device_get_ivars(dev); 179 struct uark_softc *sc = device_get_softc(dev); 180 int32_t error; 181 uint8_t iface_index; 182 183 device_set_usb2_desc(dev); 184 185 sc->sc_udev = uaa->device; 186 187 iface_index = UARK_IFACE_INDEX; 188 error = usb2_transfer_setup 189 (uaa->device, &iface_index, sc->sc_xfer, 190 uark_xfer_config, UARK_N_TRANSFER, sc, &Giant); 191 192 if (error) { 193 device_printf(dev, "allocating control USB " 194 "transfers failed!\n"); 195 goto detach; 196 } 197 /* clear stall at first run */ 198 usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_WR]); 199 usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]); 200 201 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, 202 &uark_callback, &Giant); 203 if (error) { 204 DPRINTF("usb2_com_attach failed\n"); 205 goto detach; 206 } 207 return (0); /* success */ 208 209 detach: 210 uark_detach(dev); 211 return (ENXIO); /* failure */ 212 } 213 214 static int 215 uark_detach(device_t dev) 216 { 217 struct uark_softc *sc = device_get_softc(dev); 218 219 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1); 220 221 usb2_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER); 222 223 return (0); 224 } 225 226 static void 227 uark_bulk_write_callback(struct usb2_xfer *xfer) 228 { 229 struct uark_softc *sc = xfer->priv_sc; 230 uint32_t actlen; 231 232 switch (USB_GET_STATE(xfer)) { 233 case USB_ST_SETUP: 234 case USB_ST_TRANSFERRED: 235 tr_setup: 236 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0, 237 UARK_BUF_SIZE, &actlen)) { 238 xfer->frlengths[0] = actlen; 239 usb2_start_hardware(xfer); 240 } 241 return; 242 243 default: /* Error */ 244 if (xfer->error != USB_ERR_CANCELLED) { 245 /* try to clear stall first */ 246 xfer->flags.stall_pipe = 1; 247 goto tr_setup; 248 } 249 return; 250 251 } 252 } 253 254 static void 255 uark_bulk_read_callback(struct usb2_xfer *xfer) 256 { 257 struct uark_softc *sc = xfer->priv_sc; 258 259 switch (USB_GET_STATE(xfer)) { 260 case USB_ST_TRANSFERRED: 261 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, 262 xfer->actlen); 263 264 case USB_ST_SETUP: 265 tr_setup: 266 xfer->frlengths[0] = xfer->max_data_length; 267 usb2_start_hardware(xfer); 268 return; 269 270 default: /* Error */ 271 if (xfer->error != USB_ERR_CANCELLED) { 272 /* try to clear stall first */ 273 xfer->flags.stall_pipe = 1; 274 goto tr_setup; 275 } 276 return; 277 } 278 } 279 280 static void 281 uark_start_read(struct usb2_com_softc *ucom) 282 { 283 struct uark_softc *sc = ucom->sc_parent; 284 285 usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_RD]); 286 } 287 288 static void 289 uark_stop_read(struct usb2_com_softc *ucom) 290 { 291 struct uark_softc *sc = ucom->sc_parent; 292 293 usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_RD]); 294 } 295 296 static void 297 uark_start_write(struct usb2_com_softc *ucom) 298 { 299 struct uark_softc *sc = ucom->sc_parent; 300 301 usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_WR]); 302 } 303 304 static void 305 uark_stop_write(struct usb2_com_softc *ucom) 306 { 307 struct uark_softc *sc = ucom->sc_parent; 308 309 usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_WR]); 310 } 311 312 static int 313 uark_pre_param(struct usb2_com_softc *ucom, struct termios *t) 314 { 315 if ((t->c_ospeed < 300) || (t->c_ospeed > 115200)) 316 return (EINVAL); 317 return (0); 318 } 319 320 static void 321 uark_cfg_param(struct usb2_com_softc *ucom, struct termios *t) 322 { 323 struct uark_softc *sc = ucom->sc_parent; 324 uint32_t speed = t->c_ospeed; 325 uint16_t data; 326 327 /* 328 * NOTE: When reverse computing the baud rate from the "data" all 329 * allowed baud rates are within 3% of the initial baud rate. 330 */ 331 data = (UARK_BAUD_REF + (speed / 2)) / speed; 332 333 uark_cfg_write(sc, 3, 0x83); 334 uark_cfg_write(sc, 0, data & 0xFF); 335 uark_cfg_write(sc, 1, data >> 8); 336 uark_cfg_write(sc, 3, 0x03); 337 338 if (t->c_cflag & CSTOPB) 339 data = UARK_STOP_BITS_2; 340 else 341 data = UARK_STOP_BITS_1; 342 343 if (t->c_cflag & PARENB) { 344 if (t->c_cflag & PARODD) 345 data |= UARK_PARITY_ODD; 346 else 347 data |= UARK_PARITY_EVEN; 348 } else 349 data |= UARK_PARITY_NONE; 350 351 switch (t->c_cflag & CSIZE) { 352 case CS5: 353 data |= UARK_SET_DATA_BITS(5); 354 break; 355 case CS6: 356 data |= UARK_SET_DATA_BITS(6); 357 break; 358 case CS7: 359 data |= UARK_SET_DATA_BITS(7); 360 break; 361 default: 362 case CS8: 363 data |= UARK_SET_DATA_BITS(8); 364 break; 365 } 366 uark_cfg_write(sc, 3, 0x00); 367 uark_cfg_write(sc, 3, data); 368 } 369 370 static void 371 uark_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr) 372 { 373 struct uark_softc *sc = ucom->sc_parent; 374 375 *lsr = sc->sc_lsr; 376 *msr = sc->sc_msr; 377 } 378 379 static void 380 uark_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff) 381 { 382 struct uark_softc *sc = ucom->sc_parent; 383 384 DPRINTF("onoff=%d\n", onoff); 385 386 uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00); 387 } 388 389 static void 390 uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value) 391 { 392 struct usb2_device_request req; 393 usb2_error_t err; 394 395 req.bmRequestType = UARK_WRITE; 396 req.bRequest = UARK_REQUEST; 397 USETW(req.wValue, value); 398 USETW(req.wIndex, index); 399 USETW(req.wLength, 0); 400 401 err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 402 &req, NULL, 0, 1000); 403 if (err) { 404 DPRINTFN(0, "device request failed, err=%s " 405 "(ignored)\n", usb2_errstr(err)); 406 } 407 } 408