1 #include <sys/cdefs.h> 2 __FBSDID("$FreeBSD$"); 3 4 /* $NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $ */ 5 6 /*- 7 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Lennart Augustsson (lennart@augustsson.net) at 12 * Carlstedt Research & Technology. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the NetBSD 25 * Foundation, Inc. and its contributors. 26 * 4. Neither the name of The NetBSD Foundation nor the names of its 27 * contributors may be used to endorse or promote products derived 28 * from this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 32 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 34 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 * POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43 /* 44 * Printer Class spec: http://www.usb.org/developers/data/devclass/usbprint109.PDF 45 * Printer Class spec: http://www.usb.org/developers/devclass_docs/usbprint11.pdf 46 */ 47 48 #include "usbdevs.h" 49 #include <dev/usb/usb.h> 50 #include <dev/usb/usb_mfunc.h> 51 #include <dev/usb/usb_error.h> 52 53 #define USB_DEBUG_VAR ulpt_debug 54 55 #include <dev/usb/usb_core.h> 56 #include <dev/usb/usb_debug.h> 57 #include <dev/usb/usb_process.h> 58 #include <dev/usb/usb_request.h> 59 #include <dev/usb/usb_lookup.h> 60 #include <dev/usb/usb_util.h> 61 #include <dev/usb/usb_busdma.h> 62 #include <dev/usb/usb_mbuf.h> 63 #include <dev/usb/usb_dev.h> 64 #include <dev/usb/usb_parse.h> 65 66 #include <sys/syslog.h> 67 68 #if USB_DEBUG 69 static int ulpt_debug = 0; 70 71 SYSCTL_NODE(_hw_usb2, OID_AUTO, ulpt, CTLFLAG_RW, 0, "USB ulpt"); 72 SYSCTL_INT(_hw_usb2_ulpt, OID_AUTO, debug, CTLFLAG_RW, 73 &ulpt_debug, 0, "Debug level"); 74 #endif 75 76 #define ULPT_BSIZE (1<<15) /* bytes */ 77 #define ULPT_IFQ_MAXLEN 2 /* units */ 78 79 #define UR_GET_DEVICE_ID 0x00 80 #define UR_GET_PORT_STATUS 0x01 81 #define UR_SOFT_RESET 0x02 82 83 #define LPS_NERR 0x08 /* printer no error */ 84 #define LPS_SELECT 0x10 /* printer selected */ 85 #define LPS_NOPAPER 0x20 /* printer out of paper */ 86 #define LPS_INVERT (LPS_SELECT|LPS_NERR) 87 #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) 88 89 enum { 90 ULPT_BULK_DT_WR, 91 ULPT_BULK_DT_RD, 92 ULPT_INTR_DT_RD, 93 ULPT_N_TRANSFER, 94 }; 95 96 struct ulpt_softc { 97 struct usb2_fifo_sc sc_fifo; 98 struct usb2_fifo_sc sc_fifo_noreset; 99 struct mtx sc_mtx; 100 struct usb2_callout sc_watchdog; 101 102 device_t sc_dev; 103 struct usb2_device *sc_udev; 104 struct usb2_fifo *sc_fifo_open[2]; 105 struct usb2_xfer *sc_xfer[ULPT_N_TRANSFER]; 106 107 int sc_fflags; /* current open flags, FREAD and 108 * FWRITE */ 109 uint8_t sc_iface_no; 110 uint8_t sc_last_status; 111 uint8_t sc_zlps; /* number of consequtive zero length 112 * packets received */ 113 }; 114 115 /* prototypes */ 116 117 static device_probe_t ulpt_probe; 118 static device_attach_t ulpt_attach; 119 static device_detach_t ulpt_detach; 120 121 static usb2_callback_t ulpt_write_callback; 122 static usb2_callback_t ulpt_read_callback; 123 static usb2_callback_t ulpt_status_callback; 124 125 static void ulpt_reset(struct ulpt_softc *); 126 static void ulpt_watchdog(void *); 127 128 static usb2_fifo_close_t ulpt_close; 129 static usb2_fifo_cmd_t ulpt_start_read; 130 static usb2_fifo_cmd_t ulpt_start_write; 131 static usb2_fifo_cmd_t ulpt_stop_read; 132 static usb2_fifo_cmd_t ulpt_stop_write; 133 static usb2_fifo_ioctl_t ulpt_ioctl; 134 static usb2_fifo_open_t ulpt_open; 135 static usb2_fifo_open_t unlpt_open; 136 137 static struct usb2_fifo_methods ulpt_fifo_methods = { 138 .f_close = &ulpt_close, 139 .f_ioctl = &ulpt_ioctl, 140 .f_open = &ulpt_open, 141 .f_start_read = &ulpt_start_read, 142 .f_start_write = &ulpt_start_write, 143 .f_stop_read = &ulpt_stop_read, 144 .f_stop_write = &ulpt_stop_write, 145 .basename[0] = "ulpt", 146 }; 147 148 static struct usb2_fifo_methods unlpt_fifo_methods = { 149 .f_close = &ulpt_close, 150 .f_ioctl = &ulpt_ioctl, 151 .f_open = &unlpt_open, 152 .f_start_read = &ulpt_start_read, 153 .f_start_write = &ulpt_start_write, 154 .f_stop_read = &ulpt_stop_read, 155 .f_stop_write = &ulpt_stop_write, 156 .basename[0] = "unlpt", 157 }; 158 159 static void 160 ulpt_reset(struct ulpt_softc *sc) 161 { 162 struct usb2_device_request req; 163 164 DPRINTFN(2, "\n"); 165 166 req.bRequest = UR_SOFT_RESET; 167 USETW(req.wValue, 0); 168 USETW(req.wIndex, sc->sc_iface_no); 169 USETW(req.wLength, 0); 170 171 /* 172 * There was a mistake in the USB printer 1.0 spec that gave the 173 * request type as UT_WRITE_CLASS_OTHER; it should have been 174 * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, 175 * so we try both. 176 */ 177 178 mtx_lock(&sc->sc_mtx); 179 req.bmRequestType = UT_WRITE_CLASS_OTHER; 180 if (usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx, 181 &req, NULL, 0, NULL, 2 * USB_MS_HZ)) { /* 1.0 */ 182 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 183 if (usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx, 184 &req, NULL, 0, NULL, 2 * USB_MS_HZ)) { /* 1.1 */ 185 /* ignore error */ 186 } 187 } 188 mtx_unlock(&sc->sc_mtx); 189 } 190 191 static void 192 ulpt_write_callback(struct usb2_xfer *xfer) 193 { 194 struct ulpt_softc *sc = xfer->priv_sc; 195 struct usb2_fifo *f = sc->sc_fifo_open[USB_FIFO_TX]; 196 uint32_t actlen; 197 198 if (f == NULL) { 199 /* should not happen */ 200 DPRINTF("no FIFO\n"); 201 return; 202 } 203 DPRINTF("state=0x%x\n", USB_GET_STATE(xfer)); 204 205 switch (USB_GET_STATE(xfer)) { 206 case USB_ST_TRANSFERRED: 207 case USB_ST_SETUP: 208 tr_setup: 209 if (usb2_fifo_get_data(f, xfer->frbuffers, 210 0, xfer->max_data_length, &actlen, 0)) { 211 212 xfer->frlengths[0] = actlen; 213 usb2_start_hardware(xfer); 214 } 215 break; 216 217 default: /* Error */ 218 if (xfer->error != USB_ERR_CANCELLED) { 219 /* try to clear stall first */ 220 xfer->flags.stall_pipe = 1; 221 goto tr_setup; 222 } 223 break; 224 } 225 } 226 227 static void 228 ulpt_read_callback(struct usb2_xfer *xfer) 229 { 230 struct ulpt_softc *sc = xfer->priv_sc; 231 struct usb2_fifo *f = sc->sc_fifo_open[USB_FIFO_RX]; 232 233 if (f == NULL) { 234 /* should not happen */ 235 DPRINTF("no FIFO\n"); 236 return; 237 } 238 DPRINTF("state=0x%x\n", USB_GET_STATE(xfer)); 239 240 switch (USB_GET_STATE(xfer)) { 241 case USB_ST_TRANSFERRED: 242 243 if (xfer->actlen == 0) { 244 245 if (sc->sc_zlps == 4) { 246 /* enable BULK throttle */ 247 xfer->interval = 500; /* ms */ 248 } else { 249 sc->sc_zlps++; 250 } 251 } else { 252 /* disable BULK throttle */ 253 254 xfer->interval = 0; 255 sc->sc_zlps = 0; 256 } 257 258 usb2_fifo_put_data(f, xfer->frbuffers, 259 0, xfer->actlen, 1); 260 261 case USB_ST_SETUP: 262 tr_setup: 263 if (usb2_fifo_put_bytes_max(f) != 0) { 264 xfer->frlengths[0] = xfer->max_data_length; 265 usb2_start_hardware(xfer); 266 } 267 break; 268 269 default: /* Error */ 270 /* disable BULK throttle */ 271 xfer->interval = 0; 272 sc->sc_zlps = 0; 273 274 if (xfer->error != USB_ERR_CANCELLED) { 275 /* try to clear stall first */ 276 xfer->flags.stall_pipe = 1; 277 goto tr_setup; 278 } 279 break; 280 } 281 } 282 283 static void 284 ulpt_status_callback(struct usb2_xfer *xfer) 285 { 286 struct ulpt_softc *sc = xfer->priv_sc; 287 struct usb2_device_request req; 288 uint8_t cur_status; 289 uint8_t new_status; 290 291 switch (USB_GET_STATE(xfer)) { 292 case USB_ST_TRANSFERRED: 293 294 usb2_copy_out(xfer->frbuffers + 1, 0, &cur_status, 1); 295 296 cur_status = (cur_status ^ LPS_INVERT) & LPS_MASK; 297 new_status = cur_status & ~sc->sc_last_status; 298 sc->sc_last_status = cur_status; 299 300 if (new_status & LPS_SELECT) 301 log(LOG_NOTICE, "%s: offline\n", 302 device_get_nameunit(sc->sc_dev)); 303 else if (new_status & LPS_NOPAPER) 304 log(LOG_NOTICE, "%s: out of paper\n", 305 device_get_nameunit(sc->sc_dev)); 306 else if (new_status & LPS_NERR) 307 log(LOG_NOTICE, "%s: output error\n", 308 device_get_nameunit(sc->sc_dev)); 309 break; 310 311 case USB_ST_SETUP: 312 req.bmRequestType = UT_READ_CLASS_INTERFACE; 313 req.bRequest = UR_GET_PORT_STATUS; 314 USETW(req.wValue, 0); 315 req.wIndex[0] = sc->sc_iface_no; 316 req.wIndex[1] = 0; 317 USETW(req.wLength, 1); 318 319 usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req)); 320 321 xfer->frlengths[0] = sizeof(req); 322 xfer->frlengths[1] = 1; 323 xfer->nframes = 2; 324 usb2_start_hardware(xfer); 325 break; 326 327 default: /* Error */ 328 DPRINTF("error=%s\n", usb2_errstr(xfer->error)); 329 if (xfer->error != USB_ERR_CANCELLED) { 330 /* wait for next watchdog timeout */ 331 } 332 break; 333 } 334 } 335 336 static const struct usb2_config ulpt_config[ULPT_N_TRANSFER] = { 337 [ULPT_BULK_DT_WR] = { 338 .type = UE_BULK, 339 .endpoint = UE_ADDR_ANY, 340 .direction = UE_DIR_OUT, 341 .mh.bufsize = ULPT_BSIZE, 342 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1}, 343 .mh.callback = &ulpt_write_callback, 344 }, 345 346 [ULPT_BULK_DT_RD] = { 347 .type = UE_BULK, 348 .endpoint = UE_ADDR_ANY, 349 .direction = UE_DIR_IN, 350 .mh.bufsize = ULPT_BSIZE, 351 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1}, 352 .mh.callback = &ulpt_read_callback, 353 }, 354 355 [ULPT_INTR_DT_RD] = { 356 .type = UE_CONTROL, 357 .endpoint = 0x00, /* Control pipe */ 358 .direction = UE_DIR_ANY, 359 .mh.bufsize = sizeof(struct usb2_device_request) + 1, 360 .mh.callback = &ulpt_status_callback, 361 .mh.timeout = 1000, /* 1 second */ 362 }, 363 }; 364 365 static void 366 ulpt_start_read(struct usb2_fifo *fifo) 367 { 368 struct ulpt_softc *sc = fifo->priv_sc0; 369 370 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_DT_RD]); 371 } 372 373 static void 374 ulpt_stop_read(struct usb2_fifo *fifo) 375 { 376 struct ulpt_softc *sc = fifo->priv_sc0; 377 378 usb2_transfer_stop(sc->sc_xfer[ULPT_BULK_DT_RD]); 379 } 380 381 static void 382 ulpt_start_write(struct usb2_fifo *fifo) 383 { 384 struct ulpt_softc *sc = fifo->priv_sc0; 385 386 usb2_transfer_start(sc->sc_xfer[ULPT_BULK_DT_WR]); 387 } 388 389 static void 390 ulpt_stop_write(struct usb2_fifo *fifo) 391 { 392 struct ulpt_softc *sc = fifo->priv_sc0; 393 394 usb2_transfer_stop(sc->sc_xfer[ULPT_BULK_DT_WR]); 395 } 396 397 static int 398 ulpt_open(struct usb2_fifo *fifo, int fflags) 399 { 400 struct ulpt_softc *sc = fifo->priv_sc0; 401 402 /* we assume that open is a serial process */ 403 404 if (sc->sc_fflags == 0) { 405 ulpt_reset(sc); 406 } 407 return (unlpt_open(fifo, fflags)); 408 } 409 410 static int 411 unlpt_open(struct usb2_fifo *fifo, int fflags) 412 { 413 struct ulpt_softc *sc = fifo->priv_sc0; 414 415 if (sc->sc_fflags & fflags) { 416 return (EBUSY); 417 } 418 if (fflags & FREAD) { 419 /* clear stall first */ 420 mtx_lock(&sc->sc_mtx); 421 usb2_transfer_set_stall(sc->sc_xfer[ULPT_BULK_DT_RD]); 422 mtx_unlock(&sc->sc_mtx); 423 if (usb2_fifo_alloc_buffer(fifo, 424 sc->sc_xfer[ULPT_BULK_DT_RD]->max_data_length, 425 ULPT_IFQ_MAXLEN)) { 426 return (ENOMEM); 427 } 428 /* set which FIFO is opened */ 429 sc->sc_fifo_open[USB_FIFO_RX] = fifo; 430 } 431 if (fflags & FWRITE) { 432 /* clear stall first */ 433 mtx_lock(&sc->sc_mtx); 434 usb2_transfer_set_stall(sc->sc_xfer[ULPT_BULK_DT_WR]); 435 mtx_unlock(&sc->sc_mtx); 436 if (usb2_fifo_alloc_buffer(fifo, 437 sc->sc_xfer[ULPT_BULK_DT_WR]->max_data_length, 438 ULPT_IFQ_MAXLEN)) { 439 return (ENOMEM); 440 } 441 /* set which FIFO is opened */ 442 sc->sc_fifo_open[USB_FIFO_TX] = fifo; 443 } 444 sc->sc_fflags |= fflags & (FREAD | FWRITE); 445 return (0); 446 } 447 448 static void 449 ulpt_close(struct usb2_fifo *fifo, int fflags) 450 { 451 struct ulpt_softc *sc = fifo->priv_sc0; 452 453 sc->sc_fflags &= ~(fflags & (FREAD | FWRITE)); 454 455 if (fflags & (FREAD | FWRITE)) { 456 usb2_fifo_free_buffer(fifo); 457 } 458 } 459 460 static int 461 ulpt_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data, 462 int fflags) 463 { 464 return (ENODEV); 465 } 466 467 static int 468 ulpt_probe(device_t dev) 469 { 470 struct usb2_attach_arg *uaa = device_get_ivars(dev); 471 472 DPRINTFN(11, "\n"); 473 474 if (uaa->usb2_mode != USB_MODE_HOST) { 475 return (ENXIO); 476 } 477 if ((uaa->info.bInterfaceClass == UICLASS_PRINTER) && 478 (uaa->info.bInterfaceSubClass == UISUBCLASS_PRINTER) && 479 ((uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_UNI) || 480 (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_BI) || 481 (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_1284))) { 482 return (0); 483 } 484 return (ENXIO); 485 } 486 487 static int 488 ulpt_attach(device_t dev) 489 { 490 struct usb2_attach_arg *uaa = device_get_ivars(dev); 491 struct ulpt_softc *sc = device_get_softc(dev); 492 struct usb2_interface_descriptor *id; 493 int unit = device_get_unit(dev); 494 int error; 495 uint8_t iface_index = uaa->info.bIfaceIndex; 496 uint8_t alt_index; 497 498 DPRINTFN(11, "sc=%p\n", sc); 499 500 sc->sc_dev = dev; 501 sc->sc_udev = uaa->device; 502 503 device_set_usb2_desc(dev); 504 505 mtx_init(&sc->sc_mtx, "ulpt lock", NULL, MTX_DEF | MTX_RECURSE); 506 507 usb2_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0); 508 509 /* search through all the descriptors looking for bidir mode */ 510 511 id = usb2_get_interface_descriptor(uaa->iface); 512 alt_index = 0 - 1; 513 while (1) { 514 if (id == NULL) { 515 break; 516 } 517 if ((id->bDescriptorType == UDESC_INTERFACE) && 518 (id->bLength >= sizeof(*id))) { 519 if (id->bInterfaceNumber != uaa->info.bIfaceNum) { 520 break; 521 } else { 522 alt_index++; 523 if ((id->bInterfaceClass == UICLASS_PRINTER) && 524 (id->bInterfaceSubClass == UISUBCLASS_PRINTER) && 525 (id->bInterfaceProtocol == UIPROTO_PRINTER_BI)) { 526 goto found; 527 } 528 } 529 } 530 id = (void *)usb2_desc_foreach( 531 usb2_get_config_descriptor(uaa->device), (void *)id); 532 } 533 goto detach; 534 535 found: 536 537 DPRINTF("setting alternate " 538 "config number: %d\n", alt_index); 539 540 if (alt_index) { 541 542 error = usb2_set_alt_interface_index 543 (uaa->device, iface_index, alt_index); 544 545 if (error) { 546 DPRINTF("could not set alternate " 547 "config, error=%s\n", usb2_errstr(error)); 548 goto detach; 549 } 550 } 551 sc->sc_iface_no = id->bInterfaceNumber; 552 553 error = usb2_transfer_setup(uaa->device, &iface_index, 554 sc->sc_xfer, ulpt_config, ULPT_N_TRANSFER, 555 sc, &sc->sc_mtx); 556 if (error) { 557 DPRINTF("error=%s\n", usb2_errstr(error)); 558 goto detach; 559 } 560 device_printf(sc->sc_dev, "using bi-directional mode\n"); 561 562 #if 0 563 /* 564 * This code is disabled because for some mysterious reason it causes 565 * printing not to work. But only sometimes, and mostly with 566 * UHCI and less often with OHCI. *sigh* 567 */ 568 { 569 struct usb2_config_descriptor *cd = usb2_get_config_descriptor(dev); 570 struct usb2_device_request req; 571 int len, alen; 572 573 req.bmRequestType = UT_READ_CLASS_INTERFACE; 574 req.bRequest = UR_GET_DEVICE_ID; 575 USETW(req.wValue, cd->bConfigurationValue); 576 USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); 577 USETW(req.wLength, sizeof devinfo - 1); 578 error = usb2_do_request_flags(dev, &req, devinfo, USB_SHORT_XFER_OK, 579 &alen, USB_DEFAULT_TIMEOUT); 580 if (error) { 581 device_printf(sc->sc_dev, "cannot get device id\n"); 582 } else if (alen <= 2) { 583 device_printf(sc->sc_dev, "empty device id, no " 584 "printer connected?\n"); 585 } else { 586 /* devinfo now contains an IEEE-1284 device ID */ 587 len = ((devinfo[0] & 0xff) << 8) | (devinfo[1] & 0xff); 588 if (len > sizeof devinfo - 3) 589 len = sizeof devinfo - 3; 590 devinfo[len] = 0; 591 printf("%s: device id <", device_get_nameunit(sc->sc_dev)); 592 ieee1284_print_id(devinfo + 2); 593 printf(">\n"); 594 } 595 } 596 #endif 597 598 error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 599 &ulpt_fifo_methods, &sc->sc_fifo, 600 unit, 0 - 1, uaa->info.bIfaceIndex, 601 UID_ROOT, GID_OPERATOR, 0644); 602 if (error) { 603 goto detach; 604 } 605 error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 606 &unlpt_fifo_methods, &sc->sc_fifo_noreset, 607 unit, 0 - 1, uaa->info.bIfaceIndex, 608 UID_ROOT, GID_OPERATOR, 0644); 609 if (error) { 610 goto detach; 611 } 612 /* start reading of status */ 613 614 mtx_lock(&sc->sc_mtx); 615 ulpt_watchdog(sc); 616 mtx_unlock(&sc->sc_mtx); 617 return (0); 618 619 detach: 620 ulpt_detach(dev); 621 return (ENOMEM); 622 } 623 624 static int 625 ulpt_detach(device_t dev) 626 { 627 struct ulpt_softc *sc = device_get_softc(dev); 628 629 DPRINTF("sc=%p\n", sc); 630 631 usb2_fifo_detach(&sc->sc_fifo); 632 usb2_fifo_detach(&sc->sc_fifo_noreset); 633 634 mtx_lock(&sc->sc_mtx); 635 usb2_callout_stop(&sc->sc_watchdog); 636 mtx_unlock(&sc->sc_mtx); 637 638 usb2_transfer_unsetup(sc->sc_xfer, ULPT_N_TRANSFER); 639 640 usb2_callout_drain(&sc->sc_watchdog); 641 642 mtx_destroy(&sc->sc_mtx); 643 644 return (0); 645 } 646 647 #if 0 648 /* XXX This does not belong here. */ 649 650 /* 651 * Compare two strings until the second ends. 652 */ 653 654 static uint8_t 655 ieee1284_compare(const char *a, const char *b) 656 { 657 while (1) { 658 659 if (*b == 0) { 660 break; 661 } 662 if (*a != *b) { 663 return 1; 664 } 665 b++; 666 a++; 667 } 668 return 0; 669 } 670 671 /* 672 * Print select parts of an IEEE 1284 device ID. 673 */ 674 void 675 ieee1284_print_id(char *str) 676 { 677 char *p, *q; 678 679 for (p = str - 1; p; p = strchr(p, ';')) { 680 p++; /* skip ';' */ 681 if (ieee1284_compare(p, "MFG:") == 0 || 682 ieee1284_compare(p, "MANUFACTURER:") == 0 || 683 ieee1284_compare(p, "MDL:") == 0 || 684 ieee1284_compare(p, "MODEL:") == 0) { 685 q = strchr(p, ';'); 686 if (q) 687 printf("%.*s", (int)(q - p + 1), p); 688 } 689 } 690 } 691 692 #endif 693 694 static void 695 ulpt_watchdog(void *arg) 696 { 697 struct ulpt_softc *sc = arg; 698 699 mtx_assert(&sc->sc_mtx, MA_OWNED); 700 701 usb2_transfer_start(sc->sc_xfer[ULPT_INTR_DT_RD]); 702 703 usb2_callout_reset(&sc->sc_watchdog, 704 hz, &ulpt_watchdog, sc); 705 } 706 707 static devclass_t ulpt_devclass; 708 709 static device_method_t ulpt_methods[] = { 710 DEVMETHOD(device_probe, ulpt_probe), 711 DEVMETHOD(device_attach, ulpt_attach), 712 DEVMETHOD(device_detach, ulpt_detach), 713 {0, 0} 714 }; 715 716 static driver_t ulpt_driver = { 717 .name = "ulpt", 718 .methods = ulpt_methods, 719 .size = sizeof(struct ulpt_softc), 720 }; 721 722 DRIVER_MODULE(ulpt, ushub, ulpt_driver, ulpt_devclass, NULL, 0); 723 MODULE_DEPEND(ulpt, usb, 1, 1, 1); 724 MODULE_DEPEND(ulpt, ucom, 1, 1, 1); 725