1 /* $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ */ 2 3 #include <sys/cdefs.h> 4 __FBSDID("$FreeBSD$"); 5 6 /*- 7 * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama@jp.FreeBSD.org>. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 */ 32 33 /* 34 * uvscom: SUNTAC Slipper U VS-10U driver. 35 * Slipper U is a PC Card to USB converter for data communication card 36 * adapter. It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in, 37 * P-in m@ater and various data communication card adapters. 38 */ 39 40 #include "usbdevs.h" 41 #include <dev/usb/usb.h> 42 #include <dev/usb/usb_mfunc.h> 43 #include <dev/usb/usb_error.h> 44 #include <dev/usb/usb_cdc.h> 45 46 #define USB_DEBUG_VAR uvscom_debug 47 48 #include <dev/usb/usb_core.h> 49 #include <dev/usb/usb_debug.h> 50 #include <dev/usb/usb_process.h> 51 #include <dev/usb/usb_request.h> 52 #include <dev/usb/usb_lookup.h> 53 #include <dev/usb/usb_util.h> 54 #include <dev/usb/usb_busdma.h> 55 56 #include <dev/usb/serial/usb_serial.h> 57 58 #if USB_DEBUG 59 static int uvscom_debug = 0; 60 61 SYSCTL_NODE(_hw_usb2, OID_AUTO, uvscom, CTLFLAG_RW, 0, "USB uvscom"); 62 SYSCTL_INT(_hw_usb2_uvscom, OID_AUTO, debug, CTLFLAG_RW, 63 &uvscom_debug, 0, "Debug level"); 64 #endif 65 66 #define UVSCOM_MODVER 1 /* module version */ 67 68 #define UVSCOM_CONFIG_INDEX 0 69 #define UVSCOM_IFACE_INDEX 0 70 71 /* Request */ 72 #define UVSCOM_SET_SPEED 0x10 73 #define UVSCOM_LINE_CTL 0x11 74 #define UVSCOM_SET_PARAM 0x12 75 #define UVSCOM_READ_STATUS 0xd0 76 #define UVSCOM_SHUTDOWN 0xe0 77 78 /* UVSCOM_SET_SPEED parameters */ 79 #define UVSCOM_SPEED_150BPS 0x00 80 #define UVSCOM_SPEED_300BPS 0x01 81 #define UVSCOM_SPEED_600BPS 0x02 82 #define UVSCOM_SPEED_1200BPS 0x03 83 #define UVSCOM_SPEED_2400BPS 0x04 84 #define UVSCOM_SPEED_4800BPS 0x05 85 #define UVSCOM_SPEED_9600BPS 0x06 86 #define UVSCOM_SPEED_19200BPS 0x07 87 #define UVSCOM_SPEED_38400BPS 0x08 88 #define UVSCOM_SPEED_57600BPS 0x09 89 #define UVSCOM_SPEED_115200BPS 0x0a 90 91 /* UVSCOM_LINE_CTL parameters */ 92 #define UVSCOM_BREAK 0x40 93 #define UVSCOM_RTS 0x02 94 #define UVSCOM_DTR 0x01 95 #define UVSCOM_LINE_INIT 0x08 96 97 /* UVSCOM_SET_PARAM parameters */ 98 #define UVSCOM_DATA_MASK 0x03 99 #define UVSCOM_DATA_BIT_8 0x03 100 #define UVSCOM_DATA_BIT_7 0x02 101 #define UVSCOM_DATA_BIT_6 0x01 102 #define UVSCOM_DATA_BIT_5 0x00 103 104 #define UVSCOM_STOP_MASK 0x04 105 #define UVSCOM_STOP_BIT_2 0x04 106 #define UVSCOM_STOP_BIT_1 0x00 107 108 #define UVSCOM_PARITY_MASK 0x18 109 #define UVSCOM_PARITY_EVEN 0x18 110 #define UVSCOM_PARITY_ODD 0x08 111 #define UVSCOM_PARITY_NONE 0x00 112 113 /* Status bits */ 114 #define UVSCOM_TXRDY 0x04 115 #define UVSCOM_RXRDY 0x01 116 117 #define UVSCOM_DCD 0x08 118 #define UVSCOM_NOCARD 0x04 119 #define UVSCOM_DSR 0x02 120 #define UVSCOM_CTS 0x01 121 #define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS) 122 123 #define UVSCOM_BULK_BUF_SIZE 1024 /* bytes */ 124 125 enum { 126 UVSCOM_BULK_DT_WR, 127 UVSCOM_BULK_DT_RD, 128 UVSCOM_INTR_DT_RD, 129 UVSCOM_N_TRANSFER, 130 }; 131 132 struct uvscom_softc { 133 struct usb2_com_super_softc sc_super_ucom; 134 struct usb2_com_softc sc_ucom; 135 136 struct usb2_xfer *sc_xfer[UVSCOM_N_TRANSFER]; 137 struct usb2_device *sc_udev; 138 139 uint16_t sc_line; /* line control register */ 140 141 uint8_t sc_iface_no; /* interface number */ 142 uint8_t sc_iface_index; /* interface index */ 143 uint8_t sc_lsr; /* local status register */ 144 uint8_t sc_msr; /* uvscom status register */ 145 uint8_t sc_unit_status; /* unit status */ 146 }; 147 148 /* prototypes */ 149 150 static device_probe_t uvscom_probe; 151 static device_attach_t uvscom_attach; 152 static device_detach_t uvscom_detach; 153 154 static usb2_callback_t uvscom_write_callback; 155 static usb2_callback_t uvscom_read_callback; 156 static usb2_callback_t uvscom_intr_callback; 157 158 static void uvscom_cfg_set_dtr(struct usb2_com_softc *, uint8_t); 159 static void uvscom_cfg_set_rts(struct usb2_com_softc *, uint8_t); 160 static void uvscom_cfg_set_break(struct usb2_com_softc *, uint8_t); 161 static int uvscom_pre_param(struct usb2_com_softc *, struct termios *); 162 static void uvscom_cfg_param(struct usb2_com_softc *, struct termios *); 163 static int uvscom_pre_open(struct usb2_com_softc *); 164 static void uvscom_cfg_open(struct usb2_com_softc *); 165 static void uvscom_cfg_close(struct usb2_com_softc *); 166 static void uvscom_start_read(struct usb2_com_softc *); 167 static void uvscom_stop_read(struct usb2_com_softc *); 168 static void uvscom_start_write(struct usb2_com_softc *); 169 static void uvscom_stop_write(struct usb2_com_softc *); 170 static void uvscom_cfg_get_status(struct usb2_com_softc *, uint8_t *, 171 uint8_t *); 172 static void uvscom_cfg_write(struct uvscom_softc *, uint8_t, uint16_t); 173 static uint16_t uvscom_cfg_read_status(struct uvscom_softc *); 174 175 static const struct usb2_config uvscom_config[UVSCOM_N_TRANSFER] = { 176 177 [UVSCOM_BULK_DT_WR] = { 178 .type = UE_BULK, 179 .endpoint = UE_ADDR_ANY, 180 .direction = UE_DIR_OUT, 181 .mh.bufsize = UVSCOM_BULK_BUF_SIZE, 182 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 183 .mh.callback = &uvscom_write_callback, 184 }, 185 186 [UVSCOM_BULK_DT_RD] = { 187 .type = UE_BULK, 188 .endpoint = UE_ADDR_ANY, 189 .direction = UE_DIR_IN, 190 .mh.bufsize = UVSCOM_BULK_BUF_SIZE, 191 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 192 .mh.callback = &uvscom_read_callback, 193 }, 194 195 [UVSCOM_INTR_DT_RD] = { 196 .type = UE_INTERRUPT, 197 .endpoint = UE_ADDR_ANY, 198 .direction = UE_DIR_IN, 199 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 200 .mh.bufsize = 0, /* use wMaxPacketSize */ 201 .mh.callback = &uvscom_intr_callback, 202 }, 203 }; 204 205 static const struct usb2_com_callback uvscom_callback = { 206 .usb2_com_cfg_get_status = &uvscom_cfg_get_status, 207 .usb2_com_cfg_set_dtr = &uvscom_cfg_set_dtr, 208 .usb2_com_cfg_set_rts = &uvscom_cfg_set_rts, 209 .usb2_com_cfg_set_break = &uvscom_cfg_set_break, 210 .usb2_com_cfg_param = &uvscom_cfg_param, 211 .usb2_com_cfg_open = &uvscom_cfg_open, 212 .usb2_com_cfg_close = &uvscom_cfg_close, 213 .usb2_com_pre_open = &uvscom_pre_open, 214 .usb2_com_pre_param = &uvscom_pre_param, 215 .usb2_com_start_read = &uvscom_start_read, 216 .usb2_com_stop_read = &uvscom_stop_read, 217 .usb2_com_start_write = &uvscom_start_write, 218 .usb2_com_stop_write = &uvscom_stop_write, 219 }; 220 221 static const struct usb2_device_id uvscom_devs[] = { 222 /* SUNTAC U-Cable type A4 */ 223 {USB_VPI(USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4, 0)}, 224 /* SUNTAC U-Cable type D2 */ 225 {USB_VPI(USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L, 0)}, 226 /* SUNTAC Ir-Trinity */ 227 {USB_VPI(USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U, 0)}, 228 /* SUNTAC U-Cable type P1 */ 229 {USB_VPI(USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1, 0)}, 230 /* SUNTAC Slipper U */ 231 {USB_VPI(USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U, 0)}, 232 }; 233 234 static device_method_t uvscom_methods[] = { 235 DEVMETHOD(device_probe, uvscom_probe), 236 DEVMETHOD(device_attach, uvscom_attach), 237 DEVMETHOD(device_detach, uvscom_detach), 238 {0, 0} 239 }; 240 241 static devclass_t uvscom_devclass; 242 243 static driver_t uvscom_driver = { 244 .name = "uvscom", 245 .methods = uvscom_methods, 246 .size = sizeof(struct uvscom_softc), 247 }; 248 249 DRIVER_MODULE(uvscom, ushub, uvscom_driver, uvscom_devclass, NULL, 0); 250 MODULE_DEPEND(uvscom, ucom, 1, 1, 1); 251 MODULE_DEPEND(uvscom, usb, 1, 1, 1); 252 MODULE_VERSION(uvscom, UVSCOM_MODVER); 253 254 static int 255 uvscom_probe(device_t dev) 256 { 257 struct usb2_attach_arg *uaa = device_get_ivars(dev); 258 259 if (uaa->usb2_mode != USB_MODE_HOST) { 260 return (ENXIO); 261 } 262 if (uaa->info.bConfigIndex != UVSCOM_CONFIG_INDEX) { 263 return (ENXIO); 264 } 265 if (uaa->info.bIfaceIndex != UVSCOM_IFACE_INDEX) { 266 return (ENXIO); 267 } 268 return (usb2_lookup_id_by_uaa(uvscom_devs, sizeof(uvscom_devs), uaa)); 269 } 270 271 static int 272 uvscom_attach(device_t dev) 273 { 274 struct usb2_attach_arg *uaa = device_get_ivars(dev); 275 struct uvscom_softc *sc = device_get_softc(dev); 276 int error; 277 278 device_set_usb2_desc(dev); 279 280 sc->sc_udev = uaa->device; 281 282 DPRINTF("sc=%p\n", sc); 283 284 sc->sc_iface_no = uaa->info.bIfaceNum; 285 sc->sc_iface_index = UVSCOM_IFACE_INDEX; 286 287 error = usb2_transfer_setup(uaa->device, &sc->sc_iface_index, 288 sc->sc_xfer, uvscom_config, UVSCOM_N_TRANSFER, sc, &Giant); 289 290 if (error) { 291 DPRINTF("could not allocate all USB transfers!\n"); 292 goto detach; 293 } 294 sc->sc_line = UVSCOM_LINE_INIT; 295 296 /* clear stall at first run */ 297 usb2_transfer_set_stall(sc->sc_xfer[UVSCOM_BULK_DT_WR]); 298 usb2_transfer_set_stall(sc->sc_xfer[UVSCOM_BULK_DT_RD]); 299 300 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, 301 &uvscom_callback, &Giant); 302 if (error) { 303 goto detach; 304 } 305 /* start interrupt pipe */ 306 mtx_lock(&Giant); 307 usb2_transfer_start(sc->sc_xfer[UVSCOM_INTR_DT_RD]); 308 mtx_unlock(&Giant); 309 310 return (0); 311 312 detach: 313 uvscom_detach(dev); 314 return (ENXIO); 315 } 316 317 static int 318 uvscom_detach(device_t dev) 319 { 320 struct uvscom_softc *sc = device_get_softc(dev); 321 322 DPRINTF("sc=%p\n", sc); 323 324 /* stop interrupt pipe */ 325 326 if (sc->sc_xfer[UVSCOM_INTR_DT_RD]) { 327 usb2_transfer_stop(sc->sc_xfer[UVSCOM_INTR_DT_RD]); 328 } 329 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1); 330 331 usb2_transfer_unsetup(sc->sc_xfer, UVSCOM_N_TRANSFER); 332 333 return (0); 334 } 335 336 static void 337 uvscom_write_callback(struct usb2_xfer *xfer) 338 { 339 struct uvscom_softc *sc = xfer->priv_sc; 340 uint32_t actlen; 341 342 switch (USB_GET_STATE(xfer)) { 343 case USB_ST_SETUP: 344 case USB_ST_TRANSFERRED: 345 tr_setup: 346 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0, 347 UVSCOM_BULK_BUF_SIZE, &actlen)) { 348 349 xfer->frlengths[0] = actlen; 350 usb2_start_hardware(xfer); 351 } 352 return; 353 354 default: /* Error */ 355 if (xfer->error != USB_ERR_CANCELLED) { 356 /* try to clear stall first */ 357 xfer->flags.stall_pipe = 1; 358 goto tr_setup; 359 } 360 return; 361 } 362 } 363 364 static void 365 uvscom_read_callback(struct usb2_xfer *xfer) 366 { 367 struct uvscom_softc *sc = xfer->priv_sc; 368 369 switch (USB_GET_STATE(xfer)) { 370 case USB_ST_TRANSFERRED: 371 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, xfer->actlen); 372 373 case USB_ST_SETUP: 374 tr_setup: 375 xfer->frlengths[0] = xfer->max_data_length; 376 usb2_start_hardware(xfer); 377 return; 378 379 default: /* Error */ 380 if (xfer->error != USB_ERR_CANCELLED) { 381 /* try to clear stall first */ 382 xfer->flags.stall_pipe = 1; 383 goto tr_setup; 384 } 385 return; 386 } 387 } 388 389 static void 390 uvscom_intr_callback(struct usb2_xfer *xfer) 391 { 392 struct uvscom_softc *sc = xfer->priv_sc; 393 uint8_t buf[2]; 394 395 switch (USB_GET_STATE(xfer)) { 396 case USB_ST_TRANSFERRED: 397 if (xfer->actlen >= 2) { 398 399 usb2_copy_out(xfer->frbuffers, 0, buf, sizeof(buf)); 400 401 sc->sc_lsr = 0; 402 sc->sc_msr = 0; 403 sc->sc_unit_status = buf[1]; 404 405 if (buf[0] & UVSCOM_TXRDY) { 406 sc->sc_lsr |= ULSR_TXRDY; 407 } 408 if (buf[0] & UVSCOM_RXRDY) { 409 sc->sc_lsr |= ULSR_RXRDY; 410 } 411 if (buf[1] & UVSCOM_CTS) { 412 sc->sc_msr |= SER_CTS; 413 } 414 if (buf[1] & UVSCOM_DSR) { 415 sc->sc_msr |= SER_DSR; 416 } 417 if (buf[1] & UVSCOM_DCD) { 418 sc->sc_msr |= SER_DCD; 419 } 420 /* 421 * the UCOM layer will ignore this call if the TTY 422 * device is closed! 423 */ 424 usb2_com_status_change(&sc->sc_ucom); 425 } 426 case USB_ST_SETUP: 427 tr_setup: 428 xfer->frlengths[0] = xfer->max_data_length; 429 usb2_start_hardware(xfer); 430 return; 431 432 default: /* Error */ 433 if (xfer->error != USB_ERR_CANCELLED) { 434 /* try to clear stall first */ 435 xfer->flags.stall_pipe = 1; 436 goto tr_setup; 437 } 438 return; 439 } 440 } 441 442 static void 443 uvscom_cfg_set_dtr(struct usb2_com_softc *ucom, uint8_t onoff) 444 { 445 struct uvscom_softc *sc = ucom->sc_parent; 446 447 DPRINTF("onoff = %d\n", onoff); 448 449 if (onoff) 450 sc->sc_line |= UVSCOM_DTR; 451 else 452 sc->sc_line &= ~UVSCOM_DTR; 453 454 uvscom_cfg_write(sc, UVSCOM_LINE_CTL, sc->sc_line); 455 } 456 457 static void 458 uvscom_cfg_set_rts(struct usb2_com_softc *ucom, uint8_t onoff) 459 { 460 struct uvscom_softc *sc = ucom->sc_parent; 461 462 DPRINTF("onoff = %d\n", onoff); 463 464 if (onoff) 465 sc->sc_line |= UVSCOM_RTS; 466 else 467 sc->sc_line &= ~UVSCOM_RTS; 468 469 uvscom_cfg_write(sc, UVSCOM_LINE_CTL, sc->sc_line); 470 } 471 472 static void 473 uvscom_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff) 474 { 475 struct uvscom_softc *sc = ucom->sc_parent; 476 477 DPRINTF("onoff = %d\n", onoff); 478 479 if (onoff) 480 sc->sc_line |= UVSCOM_BREAK; 481 else 482 sc->sc_line &= ~UVSCOM_BREAK; 483 484 uvscom_cfg_write(sc, UVSCOM_LINE_CTL, sc->sc_line); 485 } 486 487 static int 488 uvscom_pre_param(struct usb2_com_softc *ucom, struct termios *t) 489 { 490 switch (t->c_ospeed) { 491 case B150: 492 case B300: 493 case B600: 494 case B1200: 495 case B2400: 496 case B4800: 497 case B9600: 498 case B19200: 499 case B38400: 500 case B57600: 501 case B115200: 502 default: 503 return (EINVAL); 504 } 505 return (0); 506 } 507 508 static void 509 uvscom_cfg_param(struct usb2_com_softc *ucom, struct termios *t) 510 { 511 struct uvscom_softc *sc = ucom->sc_parent; 512 uint16_t value; 513 514 DPRINTF("\n"); 515 516 switch (t->c_ospeed) { 517 case B150: 518 value = UVSCOM_SPEED_150BPS; 519 break; 520 case B300: 521 value = UVSCOM_SPEED_300BPS; 522 break; 523 case B600: 524 value = UVSCOM_SPEED_600BPS; 525 break; 526 case B1200: 527 value = UVSCOM_SPEED_1200BPS; 528 break; 529 case B2400: 530 value = UVSCOM_SPEED_2400BPS; 531 break; 532 case B4800: 533 value = UVSCOM_SPEED_4800BPS; 534 break; 535 case B9600: 536 value = UVSCOM_SPEED_9600BPS; 537 break; 538 case B19200: 539 value = UVSCOM_SPEED_19200BPS; 540 break; 541 case B38400: 542 value = UVSCOM_SPEED_38400BPS; 543 break; 544 case B57600: 545 value = UVSCOM_SPEED_57600BPS; 546 break; 547 case B115200: 548 value = UVSCOM_SPEED_115200BPS; 549 break; 550 default: 551 return; 552 } 553 554 uvscom_cfg_write(sc, UVSCOM_SET_SPEED, value); 555 556 value = 0; 557 558 if (t->c_cflag & CSTOPB) { 559 value |= UVSCOM_STOP_BIT_2; 560 } 561 if (t->c_cflag & PARENB) { 562 if (t->c_cflag & PARODD) { 563 value |= UVSCOM_PARITY_ODD; 564 } else { 565 value |= UVSCOM_PARITY_EVEN; 566 } 567 } else { 568 value |= UVSCOM_PARITY_NONE; 569 } 570 571 switch (t->c_cflag & CSIZE) { 572 case CS5: 573 value |= UVSCOM_DATA_BIT_5; 574 break; 575 case CS6: 576 value |= UVSCOM_DATA_BIT_6; 577 break; 578 case CS7: 579 value |= UVSCOM_DATA_BIT_7; 580 break; 581 default: 582 case CS8: 583 value |= UVSCOM_DATA_BIT_8; 584 break; 585 } 586 587 uvscom_cfg_write(sc, UVSCOM_SET_PARAM, value); 588 } 589 590 static int 591 uvscom_pre_open(struct usb2_com_softc *ucom) 592 { 593 struct uvscom_softc *sc = ucom->sc_parent; 594 595 DPRINTF("sc = %p\n", sc); 596 597 /* check if PC card was inserted */ 598 599 if (sc->sc_unit_status & UVSCOM_NOCARD) { 600 DPRINTF("no PC card!\n"); 601 return (ENXIO); 602 } 603 return (0); 604 } 605 606 static void 607 uvscom_cfg_open(struct usb2_com_softc *ucom) 608 { 609 struct uvscom_softc *sc = ucom->sc_parent; 610 611 DPRINTF("sc = %p\n", sc); 612 613 uvscom_cfg_read_status(sc); 614 } 615 616 static void 617 uvscom_cfg_close(struct usb2_com_softc *ucom) 618 { 619 struct uvscom_softc *sc = ucom->sc_parent; 620 621 DPRINTF("sc=%p\n", sc); 622 623 uvscom_cfg_write(sc, UVSCOM_SHUTDOWN, 0); 624 } 625 626 static void 627 uvscom_start_read(struct usb2_com_softc *ucom) 628 { 629 struct uvscom_softc *sc = ucom->sc_parent; 630 631 usb2_transfer_start(sc->sc_xfer[UVSCOM_BULK_DT_RD]); 632 } 633 634 static void 635 uvscom_stop_read(struct usb2_com_softc *ucom) 636 { 637 struct uvscom_softc *sc = ucom->sc_parent; 638 639 usb2_transfer_stop(sc->sc_xfer[UVSCOM_BULK_DT_RD]); 640 } 641 642 static void 643 uvscom_start_write(struct usb2_com_softc *ucom) 644 { 645 struct uvscom_softc *sc = ucom->sc_parent; 646 647 usb2_transfer_start(sc->sc_xfer[UVSCOM_BULK_DT_WR]); 648 } 649 650 static void 651 uvscom_stop_write(struct usb2_com_softc *ucom) 652 { 653 struct uvscom_softc *sc = ucom->sc_parent; 654 655 usb2_transfer_stop(sc->sc_xfer[UVSCOM_BULK_DT_WR]); 656 } 657 658 static void 659 uvscom_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr) 660 { 661 struct uvscom_softc *sc = ucom->sc_parent; 662 663 *lsr = sc->sc_lsr; 664 *msr = sc->sc_msr; 665 } 666 667 static void 668 uvscom_cfg_write(struct uvscom_softc *sc, uint8_t index, uint16_t value) 669 { 670 struct usb2_device_request req; 671 usb2_error_t err; 672 673 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 674 req.bRequest = index; 675 USETW(req.wValue, value); 676 USETW(req.wIndex, 0); 677 USETW(req.wLength, 0); 678 679 err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 680 &req, NULL, 0, 1000); 681 if (err) { 682 DPRINTFN(0, "device request failed, err=%s " 683 "(ignored)\n", usb2_errstr(err)); 684 } 685 } 686 687 static uint16_t 688 uvscom_cfg_read_status(struct uvscom_softc *sc) 689 { 690 struct usb2_device_request req; 691 usb2_error_t err; 692 uint8_t data[2]; 693 694 req.bmRequestType = UT_READ_VENDOR_DEVICE; 695 req.bRequest = UVSCOM_READ_STATUS; 696 USETW(req.wValue, 0); 697 USETW(req.wIndex, 0); 698 USETW(req.wLength, 2); 699 700 err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 701 &req, data, 0, 1000); 702 if (err) { 703 DPRINTFN(0, "device request failed, err=%s " 704 "(ignored)\n", usb2_errstr(err)); 705 } 706 return (data[0] | (data[1] << 8)); 707 } 708