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 struct mtx sc_mtx; 77 78 uint8_t sc_msr; 79 uint8_t sc_lsr; 80 }; 81 82 /* prototypes */ 83 84 static device_probe_t uark_probe; 85 static device_attach_t uark_attach; 86 static device_detach_t uark_detach; 87 88 static usb2_callback_t uark_bulk_write_callback; 89 static usb2_callback_t uark_bulk_read_callback; 90 91 static void uark_start_read(struct usb2_com_softc *); 92 static void uark_stop_read(struct usb2_com_softc *); 93 static void uark_start_write(struct usb2_com_softc *); 94 static void uark_stop_write(struct usb2_com_softc *); 95 static int uark_pre_param(struct usb2_com_softc *, struct termios *); 96 static void uark_cfg_param(struct usb2_com_softc *, struct termios *); 97 static void uark_cfg_get_status(struct usb2_com_softc *, uint8_t *, 98 uint8_t *); 99 static void uark_cfg_set_break(struct usb2_com_softc *, uint8_t); 100 static void uark_cfg_write(struct uark_softc *, uint16_t, uint16_t); 101 102 static const struct usb2_config 103 uark_xfer_config[UARK_N_TRANSFER] = { 104 105 [UARK_BULK_DT_WR] = { 106 .type = UE_BULK, 107 .endpoint = UE_ADDR_ANY, 108 .direction = UE_DIR_OUT, 109 .mh.bufsize = UARK_BUF_SIZE, 110 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 111 .mh.callback = &uark_bulk_write_callback, 112 }, 113 114 [UARK_BULK_DT_RD] = { 115 .type = UE_BULK, 116 .endpoint = UE_ADDR_ANY, 117 .direction = UE_DIR_IN, 118 .mh.bufsize = UARK_BUF_SIZE, 119 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 120 .mh.callback = &uark_bulk_read_callback, 121 }, 122 }; 123 124 static const struct usb2_com_callback uark_callback = { 125 .usb2_com_cfg_get_status = &uark_cfg_get_status, 126 .usb2_com_cfg_set_break = &uark_cfg_set_break, 127 .usb2_com_cfg_param = &uark_cfg_param, 128 .usb2_com_pre_param = &uark_pre_param, 129 .usb2_com_start_read = &uark_start_read, 130 .usb2_com_stop_read = &uark_stop_read, 131 .usb2_com_start_write = &uark_start_write, 132 .usb2_com_stop_write = &uark_stop_write, 133 }; 134 135 static device_method_t uark_methods[] = { 136 /* Device methods */ 137 DEVMETHOD(device_probe, uark_probe), 138 DEVMETHOD(device_attach, uark_attach), 139 DEVMETHOD(device_detach, uark_detach), 140 {0, 0} 141 }; 142 143 static devclass_t uark_devclass; 144 145 static driver_t uark_driver = { 146 .name = "uark", 147 .methods = uark_methods, 148 .size = sizeof(struct uark_softc), 149 }; 150 151 DRIVER_MODULE(uark, uhub, uark_driver, uark_devclass, NULL, 0); 152 MODULE_DEPEND(uark, ucom, 1, 1, 1); 153 MODULE_DEPEND(uark, usb, 1, 1, 1); 154 155 static const struct usb2_device_id uark_devs[] = { 156 {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)}, 157 }; 158 159 static int 160 uark_probe(device_t dev) 161 { 162 struct usb2_attach_arg *uaa = device_get_ivars(dev); 163 164 if (uaa->usb2_mode != USB_MODE_HOST) { 165 return (ENXIO); 166 } 167 if (uaa->info.bConfigIndex != 0) { 168 return (ENXIO); 169 } 170 if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) { 171 return (ENXIO); 172 } 173 return (usb2_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa)); 174 } 175 176 static int 177 uark_attach(device_t dev) 178 { 179 struct usb2_attach_arg *uaa = device_get_ivars(dev); 180 struct uark_softc *sc = device_get_softc(dev); 181 int32_t error; 182 uint8_t iface_index; 183 184 device_set_usb2_desc(dev); 185 mtx_init(&sc->sc_mtx, "uark", NULL, MTX_DEF); 186 187 sc->sc_udev = uaa->device; 188 189 iface_index = UARK_IFACE_INDEX; 190 error = usb2_transfer_setup 191 (uaa->device, &iface_index, sc->sc_xfer, 192 uark_xfer_config, UARK_N_TRANSFER, sc, &sc->sc_mtx); 193 194 if (error) { 195 device_printf(dev, "allocating control USB " 196 "transfers failed!\n"); 197 goto detach; 198 } 199 /* clear stall at first run */ 200 mtx_lock(&sc->sc_mtx); 201 usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_WR]); 202 usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]); 203 mtx_unlock(&sc->sc_mtx); 204 205 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, 206 &uark_callback, &sc->sc_mtx); 207 if (error) { 208 DPRINTF("usb2_com_attach failed\n"); 209 goto detach; 210 } 211 return (0); /* success */ 212 213 detach: 214 uark_detach(dev); 215 return (ENXIO); /* failure */ 216 } 217 218 static int 219 uark_detach(device_t dev) 220 { 221 struct uark_softc *sc = device_get_softc(dev); 222 223 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1); 224 usb2_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER); 225 mtx_destroy(&sc->sc_mtx); 226 227 return (0); 228 } 229 230 static void 231 uark_bulk_write_callback(struct usb2_xfer *xfer) 232 { 233 struct uark_softc *sc = xfer->priv_sc; 234 uint32_t actlen; 235 236 switch (USB_GET_STATE(xfer)) { 237 case USB_ST_SETUP: 238 case USB_ST_TRANSFERRED: 239 tr_setup: 240 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0, 241 UARK_BUF_SIZE, &actlen)) { 242 xfer->frlengths[0] = actlen; 243 usb2_start_hardware(xfer); 244 } 245 return; 246 247 default: /* Error */ 248 if (xfer->error != USB_ERR_CANCELLED) { 249 /* try to clear stall first */ 250 xfer->flags.stall_pipe = 1; 251 goto tr_setup; 252 } 253 return; 254 255 } 256 } 257 258 static void 259 uark_bulk_read_callback(struct usb2_xfer *xfer) 260 { 261 struct uark_softc *sc = xfer->priv_sc; 262 263 switch (USB_GET_STATE(xfer)) { 264 case USB_ST_TRANSFERRED: 265 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, 266 xfer->actlen); 267 268 case USB_ST_SETUP: 269 tr_setup: 270 xfer->frlengths[0] = xfer->max_data_length; 271 usb2_start_hardware(xfer); 272 return; 273 274 default: /* Error */ 275 if (xfer->error != USB_ERR_CANCELLED) { 276 /* try to clear stall first */ 277 xfer->flags.stall_pipe = 1; 278 goto tr_setup; 279 } 280 return; 281 } 282 } 283 284 static void 285 uark_start_read(struct usb2_com_softc *ucom) 286 { 287 struct uark_softc *sc = ucom->sc_parent; 288 289 usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_RD]); 290 } 291 292 static void 293 uark_stop_read(struct usb2_com_softc *ucom) 294 { 295 struct uark_softc *sc = ucom->sc_parent; 296 297 usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_RD]); 298 } 299 300 static void 301 uark_start_write(struct usb2_com_softc *ucom) 302 { 303 struct uark_softc *sc = ucom->sc_parent; 304 305 usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_WR]); 306 } 307 308 static void 309 uark_stop_write(struct usb2_com_softc *ucom) 310 { 311 struct uark_softc *sc = ucom->sc_parent; 312 313 usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_WR]); 314 } 315 316 static int 317 uark_pre_param(struct usb2_com_softc *ucom, struct termios *t) 318 { 319 if ((t->c_ospeed < 300) || (t->c_ospeed > 115200)) 320 return (EINVAL); 321 return (0); 322 } 323 324 static void 325 uark_cfg_param(struct usb2_com_softc *ucom, struct termios *t) 326 { 327 struct uark_softc *sc = ucom->sc_parent; 328 uint32_t speed = t->c_ospeed; 329 uint16_t data; 330 331 /* 332 * NOTE: When reverse computing the baud rate from the "data" all 333 * allowed baud rates are within 3% of the initial baud rate. 334 */ 335 data = (UARK_BAUD_REF + (speed / 2)) / speed; 336 337 uark_cfg_write(sc, 3, 0x83); 338 uark_cfg_write(sc, 0, data & 0xFF); 339 uark_cfg_write(sc, 1, data >> 8); 340 uark_cfg_write(sc, 3, 0x03); 341 342 if (t->c_cflag & CSTOPB) 343 data = UARK_STOP_BITS_2; 344 else 345 data = UARK_STOP_BITS_1; 346 347 if (t->c_cflag & PARENB) { 348 if (t->c_cflag & PARODD) 349 data |= UARK_PARITY_ODD; 350 else 351 data |= UARK_PARITY_EVEN; 352 } else 353 data |= UARK_PARITY_NONE; 354 355 switch (t->c_cflag & CSIZE) { 356 case CS5: 357 data |= UARK_SET_DATA_BITS(5); 358 break; 359 case CS6: 360 data |= UARK_SET_DATA_BITS(6); 361 break; 362 case CS7: 363 data |= UARK_SET_DATA_BITS(7); 364 break; 365 default: 366 case CS8: 367 data |= UARK_SET_DATA_BITS(8); 368 break; 369 } 370 uark_cfg_write(sc, 3, 0x00); 371 uark_cfg_write(sc, 3, data); 372 } 373 374 static void 375 uark_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr) 376 { 377 struct uark_softc *sc = ucom->sc_parent; 378 379 *lsr = sc->sc_lsr; 380 *msr = sc->sc_msr; 381 } 382 383 static void 384 uark_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff) 385 { 386 struct uark_softc *sc = ucom->sc_parent; 387 388 DPRINTF("onoff=%d\n", onoff); 389 390 uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00); 391 } 392 393 static void 394 uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value) 395 { 396 struct usb2_device_request req; 397 usb2_error_t err; 398 399 req.bmRequestType = UARK_WRITE; 400 req.bRequest = UARK_REQUEST; 401 USETW(req.wValue, value); 402 USETW(req.wIndex, index); 403 USETW(req.wLength, 0); 404 405 err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 406 &req, NULL, 0, 1000); 407 if (err) { 408 DPRINTFN(0, "device request failed, err=%s " 409 "(ignored)\n", usb2_errstr(err)); 410 } 411 } 412