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 27 #include <sys/stdint.h> 28 #include <sys/param.h> 29 #include <sys/queue.h> 30 #include <sys/types.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/bus.h> 34 #include <sys/module.h> 35 #include <sys/lock.h> 36 #include <sys/condvar.h> 37 #include <sys/sysctl.h> 38 #include <sys/unistd.h> 39 #include <sys/callout.h> 40 #include <sys/malloc.h> 41 #include <sys/priv.h> 42 43 #include <bus/u4b/usb.h> 44 #include <bus/u4b/usbdi.h> 45 #include <bus/u4b/usbdi_util.h> 46 #include <bus/u4b/usbhid.h> 47 #include <bus/u4b/usbdevs.h> 48 49 #define USB_DEBUG_VAR usb_debug 50 #include <bus/u4b/usb_debug.h> 51 #include <bus/u4b/usb_process.h> 52 53 #include <bus/u4b/serial/usb_serial.h> 54 55 #define UARK_BUF_SIZE 1024 /* bytes */ 56 57 #define UARK_SET_DATA_BITS(x) ((x) - 5) 58 59 #define UARK_PARITY_NONE 0x00 60 #define UARK_PARITY_ODD 0x08 61 #define UARK_PARITY_EVEN 0x18 62 63 #define UARK_STOP_BITS_1 0x00 64 #define UARK_STOP_BITS_2 0x04 65 66 #define UARK_BAUD_REF 3000000 67 68 #define UARK_WRITE 0x40 69 #define UARK_READ 0xc0 70 71 #define UARK_REQUEST 0xfe 72 73 #define UARK_CONFIG_INDEX 0 74 #define UARK_IFACE_INDEX 0 75 76 enum { 77 UARK_BULK_DT_WR, 78 UARK_BULK_DT_RD, 79 UARK_N_TRANSFER, 80 }; 81 82 struct uark_softc { 83 struct ucom_super_softc sc_super_ucom; 84 struct ucom_softc sc_ucom; 85 86 struct usb_xfer *sc_xfer[UARK_N_TRANSFER]; 87 struct usb_device *sc_udev; 88 struct lock sc_lock; 89 90 uint8_t sc_msr; 91 uint8_t sc_lsr; 92 }; 93 94 /* prototypes */ 95 96 static device_probe_t uark_probe; 97 static device_attach_t uark_attach; 98 static device_detach_t uark_detach; 99 100 static usb_callback_t uark_bulk_write_callback; 101 static usb_callback_t uark_bulk_read_callback; 102 103 static void uark_start_read(struct ucom_softc *); 104 static void uark_stop_read(struct ucom_softc *); 105 static void uark_start_write(struct ucom_softc *); 106 static void uark_stop_write(struct ucom_softc *); 107 static int uark_pre_param(struct ucom_softc *, struct termios *); 108 static void uark_cfg_param(struct ucom_softc *, struct termios *); 109 static void uark_cfg_get_status(struct ucom_softc *, uint8_t *, 110 uint8_t *); 111 static void uark_cfg_set_break(struct ucom_softc *, uint8_t); 112 static void uark_cfg_write(struct uark_softc *, uint16_t, uint16_t); 113 static void uark_poll(struct ucom_softc *ucom); 114 115 static const struct usb_config 116 uark_xfer_config[UARK_N_TRANSFER] = { 117 118 [UARK_BULK_DT_WR] = { 119 .type = UE_BULK, 120 .endpoint = UE_ADDR_ANY, 121 .direction = UE_DIR_OUT, 122 .bufsize = UARK_BUF_SIZE, 123 .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 124 .callback = &uark_bulk_write_callback, 125 }, 126 127 [UARK_BULK_DT_RD] = { 128 .type = UE_BULK, 129 .endpoint = UE_ADDR_ANY, 130 .direction = UE_DIR_IN, 131 .bufsize = UARK_BUF_SIZE, 132 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 133 .callback = &uark_bulk_read_callback, 134 }, 135 }; 136 137 static const struct ucom_callback uark_callback = { 138 .ucom_cfg_get_status = &uark_cfg_get_status, 139 .ucom_cfg_set_break = &uark_cfg_set_break, 140 .ucom_cfg_param = &uark_cfg_param, 141 .ucom_pre_param = &uark_pre_param, 142 .ucom_start_read = &uark_start_read, 143 .ucom_stop_read = &uark_stop_read, 144 .ucom_start_write = &uark_start_write, 145 .ucom_stop_write = &uark_stop_write, 146 .ucom_poll = &uark_poll, 147 }; 148 149 static device_method_t uark_methods[] = { 150 /* Device methods */ 151 DEVMETHOD(device_probe, uark_probe), 152 DEVMETHOD(device_attach, uark_attach), 153 DEVMETHOD(device_detach, uark_detach), 154 {0, 0} 155 }; 156 157 static devclass_t uark_devclass; 158 159 static driver_t uark_driver = { 160 .name = "uark", 161 .methods = uark_methods, 162 .size = sizeof(struct uark_softc), 163 }; 164 165 DRIVER_MODULE(uark, uhub, uark_driver, uark_devclass, NULL, 0); 166 MODULE_DEPEND(uark, ucom, 1, 1, 1); 167 MODULE_DEPEND(uark, usb, 1, 1, 1); 168 MODULE_VERSION(uark, 1); 169 170 static const STRUCT_USB_HOST_ID uark_devs[] = { 171 {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)}, 172 }; 173 174 static int 175 uark_probe(device_t dev) 176 { 177 struct usb_attach_arg *uaa = device_get_ivars(dev); 178 179 if (uaa->usb_mode != USB_MODE_HOST) { 180 return (ENXIO); 181 } 182 if (uaa->info.bConfigIndex != 0) { 183 return (ENXIO); 184 } 185 if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) { 186 return (ENXIO); 187 } 188 return (usbd_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa)); 189 } 190 191 static int 192 uark_attach(device_t dev) 193 { 194 struct usb_attach_arg *uaa = device_get_ivars(dev); 195 struct uark_softc *sc = device_get_softc(dev); 196 int32_t error; 197 uint8_t iface_index; 198 199 device_set_usb_desc(dev); 200 lockinit(&sc->sc_lock, "uark", 0, LK_CANRECURSE); 201 202 sc->sc_udev = uaa->device; 203 204 iface_index = UARK_IFACE_INDEX; 205 error = usbd_transfer_setup 206 (uaa->device, &iface_index, sc->sc_xfer, 207 uark_xfer_config, UARK_N_TRANSFER, sc, &sc->sc_lock); 208 209 if (error) { 210 device_printf(dev, "allocating control USB " 211 "transfers failed\n"); 212 goto detach; 213 } 214 /* clear stall at first run */ 215 lockmgr(&sc->sc_lock, LK_EXCLUSIVE); 216 usbd_xfer_set_stall(sc->sc_xfer[UARK_BULK_DT_WR]); 217 usbd_xfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]); 218 lockmgr(&sc->sc_lock, LK_RELEASE); 219 220 error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, 221 &uark_callback, &sc->sc_lock); 222 if (error) { 223 DPRINTF("ucom_attach failed\n"); 224 goto detach; 225 } 226 ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev); 227 228 return (0); /* success */ 229 230 detach: 231 uark_detach(dev); 232 return (ENXIO); /* failure */ 233 } 234 235 static int 236 uark_detach(device_t dev) 237 { 238 struct uark_softc *sc = device_get_softc(dev); 239 240 ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); 241 usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER); 242 lockuninit(&sc->sc_lock); 243 244 return (0); 245 } 246 247 static void 248 uark_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 249 { 250 struct uark_softc *sc = usbd_xfer_softc(xfer); 251 struct usb_page_cache *pc; 252 uint32_t actlen; 253 254 switch (USB_GET_STATE(xfer)) { 255 case USB_ST_SETUP: 256 case USB_ST_TRANSFERRED: 257 tr_setup: 258 pc = usbd_xfer_get_frame(xfer, 0); 259 if (ucom_get_data(&sc->sc_ucom, pc, 0, 260 UARK_BUF_SIZE, &actlen)) { 261 usbd_xfer_set_frame_len(xfer, 0, actlen); 262 usbd_transfer_submit(xfer); 263 } 264 return; 265 266 default: /* Error */ 267 if (error != USB_ERR_CANCELLED) { 268 /* try to clear stall first */ 269 usbd_xfer_set_stall(xfer); 270 goto tr_setup; 271 } 272 return; 273 274 } 275 } 276 277 static void 278 uark_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 279 { 280 struct uark_softc *sc = usbd_xfer_softc(xfer); 281 struct usb_page_cache *pc; 282 int actlen; 283 284 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 285 286 switch (USB_GET_STATE(xfer)) { 287 case USB_ST_TRANSFERRED: 288 pc = usbd_xfer_get_frame(xfer, 0); 289 ucom_put_data(&sc->sc_ucom, pc, 0, actlen); 290 291 case USB_ST_SETUP: 292 tr_setup: 293 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 294 usbd_transfer_submit(xfer); 295 return; 296 297 default: /* Error */ 298 if (error != USB_ERR_CANCELLED) { 299 /* try to clear stall first */ 300 usbd_xfer_set_stall(xfer); 301 goto tr_setup; 302 } 303 return; 304 } 305 } 306 307 static void 308 uark_start_read(struct ucom_softc *ucom) 309 { 310 struct uark_softc *sc = ucom->sc_parent; 311 312 usbd_transfer_start(sc->sc_xfer[UARK_BULK_DT_RD]); 313 } 314 315 static void 316 uark_stop_read(struct ucom_softc *ucom) 317 { 318 struct uark_softc *sc = ucom->sc_parent; 319 320 usbd_transfer_stop(sc->sc_xfer[UARK_BULK_DT_RD]); 321 } 322 323 static void 324 uark_start_write(struct ucom_softc *ucom) 325 { 326 struct uark_softc *sc = ucom->sc_parent; 327 328 usbd_transfer_start(sc->sc_xfer[UARK_BULK_DT_WR]); 329 } 330 331 static void 332 uark_stop_write(struct ucom_softc *ucom) 333 { 334 struct uark_softc *sc = ucom->sc_parent; 335 336 usbd_transfer_stop(sc->sc_xfer[UARK_BULK_DT_WR]); 337 } 338 339 static int 340 uark_pre_param(struct ucom_softc *ucom, struct termios *t) 341 { 342 if ((t->c_ospeed < 300) || (t->c_ospeed > 115200)) 343 return (EINVAL); 344 return (0); 345 } 346 347 static void 348 uark_cfg_param(struct ucom_softc *ucom, struct termios *t) 349 { 350 struct uark_softc *sc = ucom->sc_parent; 351 uint32_t speed = t->c_ospeed; 352 uint16_t data; 353 354 /* 355 * NOTE: When reverse computing the baud rate from the "data" all 356 * allowed baud rates are within 3% of the initial baud rate. 357 */ 358 data = (UARK_BAUD_REF + (speed / 2)) / speed; 359 360 uark_cfg_write(sc, 3, 0x83); 361 uark_cfg_write(sc, 0, data & 0xFF); 362 uark_cfg_write(sc, 1, data >> 8); 363 uark_cfg_write(sc, 3, 0x03); 364 365 if (t->c_cflag & CSTOPB) 366 data = UARK_STOP_BITS_2; 367 else 368 data = UARK_STOP_BITS_1; 369 370 if (t->c_cflag & PARENB) { 371 if (t->c_cflag & PARODD) 372 data |= UARK_PARITY_ODD; 373 else 374 data |= UARK_PARITY_EVEN; 375 } else 376 data |= UARK_PARITY_NONE; 377 378 switch (t->c_cflag & CSIZE) { 379 case CS5: 380 data |= UARK_SET_DATA_BITS(5); 381 break; 382 case CS6: 383 data |= UARK_SET_DATA_BITS(6); 384 break; 385 case CS7: 386 data |= UARK_SET_DATA_BITS(7); 387 break; 388 default: 389 case CS8: 390 data |= UARK_SET_DATA_BITS(8); 391 break; 392 } 393 uark_cfg_write(sc, 3, 0x00); 394 uark_cfg_write(sc, 3, data); 395 } 396 397 static void 398 uark_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr) 399 { 400 struct uark_softc *sc = ucom->sc_parent; 401 402 *lsr = sc->sc_lsr; 403 *msr = sc->sc_msr; 404 } 405 406 static void 407 uark_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff) 408 { 409 struct uark_softc *sc = ucom->sc_parent; 410 411 DPRINTF("onoff=%d\n", onoff); 412 413 uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00); 414 } 415 416 static void 417 uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value) 418 { 419 struct usb_device_request req; 420 usb_error_t err; 421 422 req.bmRequestType = UARK_WRITE; 423 req.bRequest = UARK_REQUEST; 424 USETW(req.wValue, value); 425 USETW(req.wIndex, index); 426 USETW(req.wLength, 0); 427 428 err = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 429 &req, NULL, 0, 1000); 430 if (err) { 431 DPRINTFN(0, "device request failed, err=%s " 432 "(ignored)\n", usbd_errstr(err)); 433 } 434 } 435 436 static void 437 uark_poll(struct ucom_softc *ucom) 438 { 439 struct uark_softc *sc = ucom->sc_parent; 440 usbd_transfer_poll(sc->sc_xfer, UARK_N_TRANSFER); 441 } 442