1 /* $OpenBSD: ulpt.c,v 1.34 2008/06/26 05:42:18 ray Exp $ */ 2 /* $NetBSD: ulpt.c,v 1.57 2003/01/05 10:19:42 scw Exp $ */ 3 /* $FreeBSD: src/sys/dev/usb/ulpt.c,v 1.24 1999/11/17 22:33:44 n_hibma Exp $ */ 4 5 /* 6 * Copyright (c) 1998 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Lennart Augustsson (lennart@augustsson.net) at 11 * Carlstedt Research & Technology. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * Printer Class spec: 37 * http://www.usb.org/developers/devclass_docs/usbprint11.pdf 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/proc.h> 43 #include <sys/kernel.h> 44 #include <sys/device.h> 45 #include <sys/ioctl.h> 46 #include <sys/uio.h> 47 #include <sys/conf.h> 48 #include <sys/vnode.h> 49 #include <sys/syslog.h> 50 51 #include <dev/usb/usb.h> 52 #include <dev/usb/usbdi.h> 53 #include <dev/usb/usbdi_util.h> 54 #include <dev/usb/usbdevs.h> 55 #include <dev/usb/usb_quirks.h> 56 57 #define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */ 58 #define STEP hz/4 59 60 #define LPTPRI (PZERO+8) 61 #define ULPT_BSIZE 16384 62 63 #ifdef ULPT_DEBUG 64 #define DPRINTF(x) do { if (ulptdebug) printf x; } while (0) 65 #define DPRINTFN(n,x) do { if (ulptdebug>(n)) printf x; } while (0) 66 int ulptdebug = 0; 67 #else 68 #define DPRINTF(x) 69 #define DPRINTFN(n,x) 70 #endif 71 72 #define UR_GET_DEVICE_ID 0 73 #define UR_GET_PORT_STATUS 1 74 #define UR_SOFT_RESET 2 75 76 #define LPS_NERR 0x08 /* printer no error */ 77 #define LPS_SELECT 0x10 /* printer selected */ 78 #define LPS_NOPAPER 0x20 /* printer out of paper */ 79 #define LPS_INVERT (LPS_SELECT|LPS_NERR) 80 #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) 81 82 struct ulpt_softc { 83 struct device sc_dev; 84 usbd_device_handle sc_udev; /* device */ 85 usbd_interface_handle sc_iface; /* interface */ 86 int sc_ifaceno; 87 88 int sc_out; 89 usbd_pipe_handle sc_out_pipe; /* bulk out pipe */ 90 91 int sc_in; 92 usbd_pipe_handle sc_in_pipe; /* bulk in pipe */ 93 usbd_xfer_handle sc_in_xfer1; 94 usbd_xfer_handle sc_in_xfer2; 95 u_char sc_junk[64]; /* somewhere to dump input */ 96 97 u_char sc_state; 98 #define ULPT_OPEN 0x01 /* device is open */ 99 #define ULPT_OBUSY 0x02 /* printer is busy doing output */ 100 #define ULPT_INIT 0x04 /* waiting to initialize for open */ 101 u_char sc_flags; 102 #define ULPT_NOPRIME 0x40 /* don't prime on open */ 103 u_char sc_laststatus; 104 105 int sc_refcnt; 106 u_char sc_dying; 107 }; 108 109 void ulpt_disco(void *); 110 111 int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int); 112 int ulpt_status(struct ulpt_softc *); 113 void ulpt_reset(struct ulpt_softc *); 114 int ulpt_statusmsg(u_char, struct ulpt_softc *); 115 116 #if 0 117 void ieee1284_print_id(char *); 118 #endif 119 120 #define ULPTUNIT(s) (minor(s) & 0x1f) 121 #define ULPTFLAGS(s) (minor(s) & 0xe0) 122 123 124 int ulpt_match(struct device *, void *, void *); 125 void ulpt_attach(struct device *, struct device *, void *); 126 int ulpt_detach(struct device *, int); 127 int ulpt_activate(struct device *, enum devact); 128 129 struct cfdriver ulpt_cd = { 130 NULL, "ulpt", DV_DULL 131 }; 132 133 const struct cfattach ulpt_ca = { 134 sizeof(struct ulpt_softc), 135 ulpt_match, 136 ulpt_attach, 137 ulpt_detach, 138 ulpt_activate, 139 }; 140 141 int 142 ulpt_match(struct device *parent, void *match, void *aux) 143 { 144 struct usb_attach_arg *uaa = aux; 145 usb_interface_descriptor_t *id; 146 147 DPRINTFN(10,("ulpt_match\n")); 148 if (uaa->iface == NULL) 149 return (UMATCH_NONE); 150 id = usbd_get_interface_descriptor(uaa->iface); 151 if (id != NULL && 152 id->bInterfaceClass == UICLASS_PRINTER && 153 id->bInterfaceSubClass == UISUBCLASS_PRINTER && 154 ((id->bInterfaceProtocol == UIPROTO_PRINTER_UNI) || 155 (id->bInterfaceProtocol == UIPROTO_PRINTER_BI) || 156 (id->bInterfaceProtocol == UIPROTO_PRINTER_1284))) 157 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); 158 return (UMATCH_NONE); 159 } 160 161 void 162 ulpt_attach(struct device *parent, struct device *self, void *aux) 163 { 164 struct ulpt_softc *sc = (struct ulpt_softc *)self; 165 struct usb_attach_arg *uaa = aux; 166 usbd_device_handle dev = uaa->device; 167 usbd_interface_handle iface = uaa->iface; 168 usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface); 169 usb_interface_descriptor_t *id, *iend; 170 usb_config_descriptor_t *cdesc; 171 usbd_status err; 172 usb_endpoint_descriptor_t *ed; 173 u_int8_t epcount; 174 int i, altno; 175 176 DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); 177 178 //printf("%s: iclass %d/%d\n", sc->sc_dev.dv_xname, 179 // ifcd->bInterfaceClass, ifcd->bInterfaceSubClass); 180 181 /* XXX 182 * Stepping through the alternate settings needs to be abstracted out. 183 */ 184 cdesc = usbd_get_config_descriptor(dev); 185 if (cdesc == NULL) { 186 printf("%s: failed to get configuration descriptor\n", 187 sc->sc_dev.dv_xname); 188 return; 189 } 190 iend = (usb_interface_descriptor_t *) 191 ((char *)cdesc + UGETW(cdesc->wTotalLength)); 192 #ifdef DIAGNOSTIC 193 if (ifcd < (usb_interface_descriptor_t *)cdesc || 194 ifcd >= iend) 195 panic("ulpt: iface desc out of range"); 196 #endif 197 /* Step through all the descriptors looking for bidir mode */ 198 for (id = ifcd, altno = 0; 199 id < iend; 200 id = (void *)((char *)id + id->bLength)) { 201 if (id->bDescriptorType == UDESC_INTERFACE && 202 id->bInterfaceNumber == ifcd->bInterfaceNumber) { 203 if (id->bInterfaceClass == UICLASS_PRINTER && 204 id->bInterfaceSubClass == UISUBCLASS_PRINTER && 205 (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /*|| 206 id->bInterfaceProtocol == UIPROTO_PRINTER_1284*/)) 207 goto found; 208 altno++; 209 } 210 } 211 id = ifcd; /* not found, use original */ 212 found: 213 if (id != ifcd) { 214 /* Found a new bidir setting */ 215 DPRINTF(("ulpt_attach: set altno = %d\n", altno)); 216 err = usbd_set_interface(iface, altno); 217 if (err) { 218 printf("%s: setting alternate interface failed\n", 219 sc->sc_dev.dv_xname); 220 sc->sc_dying = 1; 221 return; 222 } 223 } 224 225 epcount = 0; 226 (void)usbd_endpoint_count(iface, &epcount); 227 228 sc->sc_in = -1; 229 sc->sc_out = -1; 230 for (i = 0; i < epcount; i++) { 231 ed = usbd_interface2endpoint_descriptor(iface, i); 232 if (ed == NULL) { 233 printf("%s: couldn't get ep %d\n", 234 sc->sc_dev.dv_xname, i); 235 return; 236 } 237 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 238 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 239 sc->sc_in = ed->bEndpointAddress; 240 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 241 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 242 sc->sc_out = ed->bEndpointAddress; 243 } 244 } 245 if (sc->sc_out == -1) { 246 printf("%s: could not find bulk out endpoint\n", 247 sc->sc_dev.dv_xname); 248 sc->sc_dying = 1; 249 return; 250 } 251 252 if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) { 253 /* This device doesn't handle reading properly. */ 254 sc->sc_in = -1; 255 } 256 257 printf("%s: using %s-directional mode\n", sc->sc_dev.dv_xname, 258 sc->sc_in >= 0 ? "bi" : "uni"); 259 260 DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out)); 261 262 sc->sc_iface = iface; 263 sc->sc_ifaceno = id->bInterfaceNumber; 264 sc->sc_udev = dev; 265 266 #if 0 267 /* 268 * This code is disabled because for some mysterious reason it causes 269 * printing not to work. But only sometimes, and mostly with 270 * UHCI and less often with OHCI. *sigh* 271 */ 272 { 273 usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); 274 usb_device_request_t req; 275 int len, alen; 276 277 req.bmRequestType = UT_READ_CLASS_INTERFACE; 278 req.bRequest = UR_GET_DEVICE_ID; 279 USETW(req.wValue, cd->bConfigurationValue); 280 USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); 281 USETW(req.wLength, DEVINFOSIZE - 1); 282 err = usbd_do_request_flags(dev, &req, devinfop, USBD_SHORT_XFER_OK, 283 &alen, USBD_DEFAULT_TIMEOUT); 284 if (err) { 285 printf("%s: cannot get device id\n", sc->sc_dev.dv_xname); 286 } else if (alen <= 2) { 287 printf("%s: empty device id, no printer connected?\n", 288 sc->sc_dev.dv_xname); 289 } else { 290 /* devinfop now contains an IEEE-1284 device ID */ 291 len = ((devinfop[0] & 0xff) << 8) | (devinfop[1] & 0xff); 292 if (len > DEVINFOSIZE - 3) 293 len = DEVINFOSIZE - 3; 294 devinfo[len] = 0; 295 printf("%s: device id <", sc->sc_dev.dv_xname); 296 ieee1284_print_id(devinfop+2); 297 printf(">\n"); 298 } 299 } 300 #endif 301 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 302 &sc->sc_dev); 303 } 304 305 int 306 ulpt_activate(struct device *self, enum devact act) 307 { 308 struct ulpt_softc *sc = (struct ulpt_softc *)self; 309 310 switch (act) { 311 case DVACT_ACTIVATE: 312 break; 313 314 case DVACT_DEACTIVATE: 315 sc->sc_dying = 1; 316 break; 317 } 318 return (0); 319 } 320 321 int 322 ulpt_detach(struct device *self, int flags) 323 { 324 struct ulpt_softc *sc = (struct ulpt_softc *)self; 325 int s; 326 int maj, mn; 327 328 DPRINTF(("ulpt_detach: sc=%p\n", sc)); 329 330 sc->sc_dying = 1; 331 if (sc->sc_out_pipe != NULL) 332 usbd_abort_pipe(sc->sc_out_pipe); 333 if (sc->sc_in_pipe != NULL) 334 usbd_abort_pipe(sc->sc_in_pipe); 335 336 s = splusb(); 337 if (--sc->sc_refcnt >= 0) { 338 /* There is noone to wake, aborting the pipe is enough */ 339 /* Wait for processes to go away. */ 340 usb_detach_wait(&sc->sc_dev); 341 } 342 splx(s); 343 344 /* locate the major number */ 345 for (maj = 0; maj < nchrdev; maj++) 346 if (cdevsw[maj].d_open == ulptopen) 347 break; 348 349 /* Nuke the vnodes for any open instances (calls close). */ 350 mn = self->dv_unit; 351 vdevgone(maj, mn, mn, VCHR); 352 vdevgone(maj, mn | ULPT_NOPRIME , mn | ULPT_NOPRIME, VCHR); 353 354 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 355 &sc->sc_dev); 356 357 return (0); 358 } 359 360 int 361 ulpt_status(struct ulpt_softc *sc) 362 { 363 usb_device_request_t req; 364 usbd_status err; 365 u_char status; 366 367 req.bmRequestType = UT_READ_CLASS_INTERFACE; 368 req.bRequest = UR_GET_PORT_STATUS; 369 USETW(req.wValue, 0); 370 USETW(req.wIndex, sc->sc_ifaceno); 371 USETW(req.wLength, 1); 372 err = usbd_do_request(sc->sc_udev, &req, &status); 373 DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); 374 if (!err) 375 return (status); 376 else 377 return (0); 378 } 379 380 void 381 ulpt_reset(struct ulpt_softc *sc) 382 { 383 usb_device_request_t req; 384 385 DPRINTFN(1, ("ulpt_reset\n")); 386 req.bRequest = UR_SOFT_RESET; 387 USETW(req.wValue, 0); 388 USETW(req.wIndex, sc->sc_ifaceno); 389 USETW(req.wLength, 0); 390 391 /* 392 * There was a mistake in the USB printer 1.0 spec that gave the 393 * request type as UT_WRITE_CLASS_OTHER; it should have been 394 * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, 395 * so we try both. 396 */ 397 req.bmRequestType = UT_WRITE_CLASS_OTHER; 398 if (usbd_do_request(sc->sc_udev, &req, 0)) { /* 1.0 */ 399 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 400 (void)usbd_do_request(sc->sc_udev, &req, 0); /* 1.1 */ 401 } 402 } 403 404 static void 405 ulpt_input(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 406 { 407 struct ulpt_softc *sc = priv; 408 409 DPRINTFN(2,("ulpt_input: got some data\n")); 410 /* Do it again. */ 411 if (xfer == sc->sc_in_xfer1) 412 usbd_transfer(sc->sc_in_xfer2); 413 else 414 usbd_transfer(sc->sc_in_xfer1); 415 } 416 417 int ulptusein = 1; 418 419 /* 420 * Reset the printer, then wait until it's selected and not busy. 421 */ 422 int 423 ulptopen(dev_t dev, int flag, int mode, struct proc *p) 424 { 425 u_char flags = ULPTFLAGS(dev); 426 struct ulpt_softc *sc; 427 usbd_status err; 428 int spin, error; 429 430 if (ULPTUNIT(dev) >= ulpt_cd.cd_ndevs) 431 return (ENXIO); 432 sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; 433 if (sc == NULL) 434 return (ENXIO); 435 436 if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) 437 return (ENXIO); 438 439 if (sc->sc_state) 440 return (EBUSY); 441 442 sc->sc_state = ULPT_INIT; 443 sc->sc_flags = flags; 444 DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags)); 445 446 error = 0; 447 sc->sc_refcnt++; 448 449 if ((flags & ULPT_NOPRIME) == 0) 450 ulpt_reset(sc); 451 452 for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) { 453 DPRINTF(("ulpt_open: waiting a while\n")); 454 if (spin >= TIMEOUT) { 455 error = EBUSY; 456 sc->sc_state = 0; 457 goto done; 458 } 459 460 /* wait 1/4 second, give up if we get a signal */ 461 error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "ulptop", STEP); 462 if (error != EWOULDBLOCK) { 463 sc->sc_state = 0; 464 goto done; 465 } 466 467 if (sc->sc_dying) { 468 error = ENXIO; 469 sc->sc_state = 0; 470 goto done; 471 } 472 } 473 474 err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); 475 if (err) { 476 sc->sc_state = 0; 477 error = EIO; 478 goto done; 479 } 480 if (ulptusein && sc->sc_in != -1) { 481 DPRINTF(("ulpt_open: open input pipe\n")); 482 err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe); 483 if (err) { 484 error = EIO; 485 usbd_close_pipe(sc->sc_out_pipe); 486 sc->sc_out_pipe = NULL; 487 sc->sc_state = 0; 488 goto done; 489 } 490 sc->sc_in_xfer1 = usbd_alloc_xfer(sc->sc_udev); 491 sc->sc_in_xfer2 = usbd_alloc_xfer(sc->sc_udev); 492 if (sc->sc_in_xfer1 == NULL || sc->sc_in_xfer2 == NULL) { 493 error = ENOMEM; 494 if (sc->sc_in_xfer1 != NULL) { 495 usbd_free_xfer(sc->sc_in_xfer1); 496 sc->sc_in_xfer1 = NULL; 497 } 498 if (sc->sc_in_xfer2 != NULL) { 499 usbd_free_xfer(sc->sc_in_xfer2); 500 sc->sc_in_xfer2 = NULL; 501 } 502 usbd_close_pipe(sc->sc_out_pipe); 503 sc->sc_out_pipe = NULL; 504 usbd_close_pipe(sc->sc_in_pipe); 505 sc->sc_in_pipe = NULL; 506 sc->sc_state = 0; 507 goto done; 508 } 509 usbd_setup_xfer(sc->sc_in_xfer1, sc->sc_in_pipe, sc, 510 sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK, 511 USBD_NO_TIMEOUT, ulpt_input); 512 usbd_setup_xfer(sc->sc_in_xfer2, sc->sc_in_pipe, sc, 513 sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK, 514 USBD_NO_TIMEOUT, ulpt_input); 515 usbd_transfer(sc->sc_in_xfer1); /* ignore failed start */ 516 } 517 518 sc->sc_state = ULPT_OPEN; 519 520 done: 521 if (--sc->sc_refcnt < 0) 522 usb_detach_wakeup(&sc->sc_dev); 523 524 DPRINTF(("ulptopen: done, error=%d\n", error)); 525 return (error); 526 } 527 528 int 529 ulpt_statusmsg(u_char status, struct ulpt_softc *sc) 530 { 531 u_char new; 532 533 status = (status ^ LPS_INVERT) & LPS_MASK; 534 new = status & ~sc->sc_laststatus; 535 sc->sc_laststatus = status; 536 537 if (new & LPS_SELECT) 538 log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname); 539 else if (new & LPS_NOPAPER) 540 log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname); 541 else if (new & LPS_NERR) 542 log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname); 543 544 return (status); 545 } 546 547 int 548 ulptclose(dev_t dev, int flag, int mode, struct proc *p) 549 { 550 struct ulpt_softc *sc; 551 552 sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; 553 554 if (sc->sc_state != ULPT_OPEN) 555 /* We are being forced to close before the open completed. */ 556 return (0); 557 558 if (sc->sc_out_pipe != NULL) { 559 usbd_close_pipe(sc->sc_out_pipe); 560 sc->sc_out_pipe = NULL; 561 } 562 if (sc->sc_in_pipe != NULL) { 563 usbd_abort_pipe(sc->sc_in_pipe); 564 usbd_close_pipe(sc->sc_in_pipe); 565 sc->sc_in_pipe = NULL; 566 if (sc->sc_in_xfer1 != NULL) { 567 usbd_free_xfer(sc->sc_in_xfer1); 568 sc->sc_in_xfer1 = NULL; 569 } 570 if (sc->sc_in_xfer2 != NULL) { 571 usbd_free_xfer(sc->sc_in_xfer2); 572 sc->sc_in_xfer2 = NULL; 573 } 574 } 575 576 sc->sc_state = 0; 577 578 DPRINTF(("ulptclose: closed\n")); 579 return (0); 580 } 581 582 int 583 ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags) 584 { 585 u_int32_t n; 586 int error = 0; 587 void *bufp; 588 usbd_xfer_handle xfer; 589 usbd_status err; 590 591 DPRINTF(("ulptwrite\n")); 592 xfer = usbd_alloc_xfer(sc->sc_udev); 593 if (xfer == NULL) 594 return (ENOMEM); 595 bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); 596 if (bufp == NULL) { 597 usbd_free_xfer(xfer); 598 return (ENOMEM); 599 } 600 while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) { 601 ulpt_statusmsg(ulpt_status(sc), sc); 602 error = uiomove(bufp, n, uio); 603 if (error) 604 break; 605 DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n)); 606 err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY, 607 USBD_NO_TIMEOUT, bufp, &n, "ulptwr"); 608 if (err) { 609 DPRINTF(("ulptwrite: error=%d\n", err)); 610 error = EIO; 611 break; 612 } 613 } 614 usbd_free_xfer(xfer); 615 616 return (error); 617 } 618 619 int 620 ulptwrite(dev_t dev, struct uio *uio, int flags) 621 { 622 struct ulpt_softc *sc; 623 int error; 624 625 sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; 626 627 if (sc->sc_dying) 628 return (EIO); 629 630 sc->sc_refcnt++; 631 error = ulpt_do_write(sc, uio, flags); 632 if (--sc->sc_refcnt < 0) 633 usb_detach_wakeup(&sc->sc_dev); 634 return (error); 635 } 636 637 int 638 ulptioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 639 { 640 int error = 0; 641 642 switch (cmd) { 643 default: 644 error = ENODEV; 645 } 646 647 return (error); 648 } 649 650 #if 0 651 /* XXX This does not belong here. */ 652 /* 653 * Print select parts of a IEEE 1284 device ID. 654 */ 655 void 656 ieee1284_print_id(char *str) 657 { 658 char *p, *q; 659 660 for (p = str-1; p; p = strchr(p, ';')) { 661 p++; /* skip ';' */ 662 if (strncmp(p, "MFG:", 4) == 0 || 663 strncmp(p, "MANUFACTURER:", 14) == 0 || 664 strncmp(p, "MDL:", 4) == 0 || 665 strncmp(p, "MODEL:", 6) == 0) { 666 q = strchr(p, ';'); 667 if (q) 668 printf("%.*s", (int)(q - p + 1), p); 669 } 670 } 671 } 672 #endif 673