1 /* $NetBSD: ulpt.c,v 1.33 2000/03/06 20:58:39 augustss Exp $ */ 2 /* $FreeBSD: src/sys/dev/usb/ulpt.c,v 1.24 1999/11/17 22:33:44 n_hibma Exp $ */ 3 4 /* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson (augustss@carlstedt.se) at 10 * Carlstedt Research & Technology. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 /* 42 * Printer Class spec: http://www.usb.org/developers/data/usbprn10.pdf 43 */ 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/proc.h> 48 #include <sys/kernel.h> 49 #if defined(__NetBSD__) 50 #include <sys/device.h> 51 #include <sys/ioctl.h> 52 #elif defined(__FreeBSD__) 53 #include <sys/ioccom.h> 54 #include <sys/module.h> 55 #include <sys/bus.h> 56 #endif 57 #include <sys/uio.h> 58 #include <sys/conf.h> 59 #include <sys/vnode.h> 60 #include <sys/syslog.h> 61 62 #include <dev/usb/usb.h> 63 #include <dev/usb/usbdi.h> 64 #include <dev/usb/usbdi_util.h> 65 #include <dev/usb/usbdevs.h> 66 #include <dev/usb/usb_quirks.h> 67 68 #define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */ 69 #define STEP hz/4 70 71 #define LPTPRI (PZERO+8) 72 #define ULPT_BSIZE 16384 73 74 #ifdef ULPT_DEBUG 75 #define DPRINTF(x) if (ulptdebug) logprintf x 76 #define DPRINTFN(n,x) if (ulptdebug>(n)) logprintf x 77 int ulptdebug = 0; 78 #else 79 #define DPRINTF(x) 80 #define DPRINTFN(n,x) 81 #endif 82 83 #define UR_GET_DEVICE_ID 0 84 #define UR_GET_PORT_STATUS 1 85 #define UR_SOFT_RESET 2 86 87 #define LPS_NERR 0x08 /* printer no error */ 88 #define LPS_SELECT 0x10 /* printer selected */ 89 #define LPS_NOPAPER 0x20 /* printer out of paper */ 90 #define LPS_INVERT (LPS_SELECT|LPS_NERR) 91 #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) 92 93 struct ulpt_softc { 94 USBBASEDEVICE sc_dev; 95 usbd_device_handle sc_udev; /* device */ 96 usbd_interface_handle sc_iface; /* interface */ 97 int sc_ifaceno; 98 usbd_pipe_handle sc_bulkpipe; /* bulk pipe */ 99 int sc_bulk; 100 101 u_char sc_state; 102 #define ULPT_OPEN 0x01 /* device is open */ 103 #define ULPT_OBUSY 0x02 /* printer is busy doing output */ 104 #define ULPT_INIT 0x04 /* waiting to initialize for open */ 105 u_char sc_flags; 106 #define ULPT_NOPRIME 0x40 /* don't prime on open */ 107 u_char sc_laststatus; 108 109 int sc_refcnt; 110 u_char sc_dying; 111 112 #if defined(__FreeBSD__) 113 dev_t dev; 114 dev_t dev_noprime; 115 #endif 116 }; 117 118 #if defined(__NetBSD__) || defined(__OpenBSD__) 119 cdev_decl(ulpt); 120 #elif defined(__FreeBSD__) 121 static d_open_t ulptopen; 122 static d_close_t ulptclose; 123 static d_write_t ulptwrite; 124 static d_ioctl_t ulptioctl; 125 126 #define ULPT_CDEV_MAJOR 113 127 128 static struct cdevsw ulpt_cdevsw = { 129 /* open */ ulptopen, 130 /* close */ ulptclose, 131 /* read */ noread, 132 /* write */ ulptwrite, 133 /* ioctl */ ulptioctl, 134 /* poll */ nopoll, 135 /* mmap */ nommap, 136 /* strategy */ nostrategy, 137 /* name */ "ulpt", 138 /* maj */ ULPT_CDEV_MAJOR, 139 /* dump */ nodump, 140 /* psize */ nopsize, 141 /* flags */ 0, 142 /* bmaj */ -1 143 }; 144 #endif 145 146 void ulpt_disco __P((void *)); 147 148 int ulpt_do_write __P((struct ulpt_softc *, struct uio *uio, int)); 149 int ulpt_status __P((struct ulpt_softc *)); 150 void ulpt_reset __P((struct ulpt_softc *)); 151 int ulpt_statusmsg __P((u_char, struct ulpt_softc *)); 152 153 void ieee1284_print_id __P((char *)); 154 155 #define ULPTUNIT(s) (minor(s) & 0x1f) 156 #define ULPTFLAGS(s) (minor(s) & 0xe0) 157 158 159 USB_DECLARE_DRIVER(ulpt); 160 161 USB_MATCH(ulpt) 162 { 163 USB_MATCH_START(ulpt, uaa); 164 usb_interface_descriptor_t *id; 165 166 DPRINTFN(10,("ulpt_match\n")); 167 if (uaa->iface == NULL) 168 return (UMATCH_NONE); 169 id = usbd_get_interface_descriptor(uaa->iface); 170 if (id != NULL && 171 id->bInterfaceClass == UICLASS_PRINTER && 172 id->bInterfaceSubClass == UISUBCLASS_PRINTER && 173 (id->bInterfaceProtocol == UIPROTO_PRINTER_UNI || 174 id->bInterfaceProtocol == UIPROTO_PRINTER_BI)) 175 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); 176 return (UMATCH_NONE); 177 } 178 179 USB_ATTACH(ulpt) 180 { 181 USB_ATTACH_START(ulpt, sc, uaa); 182 usbd_device_handle dev = uaa->device; 183 usbd_interface_handle iface = uaa->iface; 184 usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); 185 char devinfo[1024]; 186 usb_endpoint_descriptor_t *ed; 187 usbd_status err; 188 189 DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); 190 usbd_devinfo(dev, 0, devinfo); 191 USB_ATTACH_SETUP; 192 printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), 193 devinfo, id->bInterfaceClass, id->bInterfaceSubClass); 194 195 /* Figure out which endpoint is the bulk out endpoint. */ 196 ed = usbd_interface2endpoint_descriptor(iface, 0); 197 if (ed == NULL) 198 goto nobulk; 199 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT || 200 (ed->bmAttributes & UE_XFERTYPE) != UE_BULK) { 201 /* In case we are using a bidir protocol... */ 202 ed = usbd_interface2endpoint_descriptor(iface, 1); 203 if (ed == NULL) 204 goto nobulk; 205 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT || 206 (ed->bmAttributes & UE_XFERTYPE) != UE_BULK) 207 goto nobulk; 208 } 209 sc->sc_bulk = ed->bEndpointAddress; 210 DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_bulk)); 211 212 sc->sc_iface = iface; 213 err = usbd_interface2device_handle(iface, &sc->sc_udev); 214 if (err) { 215 sc->sc_dying = 1; 216 USB_ATTACH_ERROR_RETURN; 217 } 218 sc->sc_ifaceno = id->bInterfaceNumber; 219 220 #if 0 221 /* 222 * This code is disabled because for some mysterious it causes 223 * printing not to work. But only sometimes, and mostly with 224 * UHCI and less often with OHCI. *sigh* 225 */ 226 { 227 usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); 228 usb_device_request_t req; 229 int len, alen; 230 231 req.bmRequestType = UT_READ_CLASS_INTERFACE; 232 req.bRequest = UR_GET_DEVICE_ID; 233 USETW(req.wValue, cd->bConfigurationValue); 234 USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); 235 USETW(req.wLength, sizeof devinfo - 1); 236 err = usbd_do_request_flags(dev, &req, devinfo,USBD_SHORT_XFER_OK, 237 &alen); 238 if (err) { 239 printf("%s: cannot get device id\n", USBDEVNAME(sc->sc_dev)); 240 } else if (alen <= 2) { 241 printf("%s: empty device id, no printer connected?\n", 242 USBDEVNAME(sc->sc_dev)); 243 } else { 244 /* devinfo now contains an IEEE-1284 device ID */ 245 len = ((devinfo[0] & 0xff) << 8) | (devinfo[1] & 0xff); 246 if (len > sizeof devinfo - 3) 247 len = sizeof devinfo - 3; 248 devinfo[len] = 0; 249 printf("%s: device id <", USBDEVNAME(sc->sc_dev)); 250 ieee1284_print_id(devinfo+2); 251 printf(">\n"); 252 } 253 } 254 #endif 255 256 #if defined(__FreeBSD__) 257 sc->dev = make_dev(&ulpt_cdevsw, device_get_unit(self), 258 UID_ROOT, GID_OPERATOR, 0644, "ulpt%d", device_get_unit(self)); 259 sc->dev_noprime = make_dev(&ulpt_cdevsw, 260 device_get_unit(self)|ULPT_NOPRIME, 261 UID_ROOT, GID_OPERATOR, 0644, "unlpt%d", device_get_unit(self)); 262 #endif 263 264 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 265 USBDEV(sc->sc_dev)); 266 267 USB_ATTACH_SUCCESS_RETURN; 268 269 nobulk: 270 printf("%s: could not find bulk endpoint\n", USBDEVNAME(sc->sc_dev)); 271 sc->sc_dying = 1; 272 USB_ATTACH_ERROR_RETURN; 273 } 274 275 #if defined(__NetBSD__) || defined(__OpenBSD__) 276 int 277 ulpt_activate(self, act) 278 device_ptr_t self; 279 enum devact act; 280 { 281 struct ulpt_softc *sc = (struct ulpt_softc *)self; 282 283 switch (act) { 284 case DVACT_ACTIVATE: 285 return (EOPNOTSUPP); 286 break; 287 288 case DVACT_DEACTIVATE: 289 sc->sc_dying = 1; 290 break; 291 } 292 return (0); 293 } 294 #endif 295 296 USB_DETACH(ulpt) 297 { 298 USB_DETACH_START(ulpt, sc); 299 int s; 300 #if defined(__NetBSD__) || defined(__OpenBSD__) 301 int maj, mn; 302 303 DPRINTF(("ulpt_detach: sc=%p flags=%d\n", sc, flags)); 304 #elif defined(__FreeBSD__) 305 DPRINTF(("ulpt_detach: sc=%p\n", sc)); 306 #endif 307 308 sc->sc_dying = 1; 309 if (sc->sc_bulkpipe != NULL) 310 usbd_abort_pipe(sc->sc_bulkpipe); 311 312 s = splusb(); 313 if (--sc->sc_refcnt >= 0) { 314 /* There is noone to wake, aborting the pipe is enough */ 315 /* Wait for processes to go away. */ 316 usb_detach_wait(USBDEV(sc->sc_dev)); 317 } 318 splx(s); 319 320 #if defined(__NetBSD__) || defined(__OpenBSD__) 321 /* locate the major number */ 322 for (maj = 0; maj < nchrdev; maj++) 323 if (cdevsw[maj].d_open == ulptopen) 324 break; 325 326 /* Nuke the vnodes for any open instances (calls close). */ 327 mn = self->dv_unit; 328 vdevgone(maj, mn, mn, VCHR); 329 #elif defined(__FreeBSD__) 330 /* XXX not implemented yet */ 331 332 destroy_dev(sc->dev); 333 destroy_dev(sc->dev_noprime); 334 #endif 335 336 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 337 USBDEV(sc->sc_dev)); 338 339 return (0); 340 } 341 342 int 343 ulpt_status(sc) 344 struct ulpt_softc *sc; 345 { 346 usb_device_request_t req; 347 usbd_status err; 348 u_char status; 349 350 req.bmRequestType = UT_READ_CLASS_INTERFACE; 351 req.bRequest = UR_GET_PORT_STATUS; 352 USETW(req.wValue, 0); 353 USETW(req.wIndex, sc->sc_ifaceno); 354 USETW(req.wLength, 1); 355 err = usbd_do_request(sc->sc_udev, &req, &status); 356 DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); 357 if (!err) 358 return (status); 359 else 360 return (0); 361 } 362 363 void 364 ulpt_reset(sc) 365 struct ulpt_softc *sc; 366 { 367 usb_device_request_t req; 368 369 DPRINTFN(1, ("ulpt_reset\n")); 370 req.bmRequestType = UT_WRITE_CLASS_OTHER; 371 req.bRequest = UR_SOFT_RESET; 372 USETW(req.wValue, 0); 373 USETW(req.wIndex, sc->sc_ifaceno); 374 USETW(req.wLength, 0); 375 (void)usbd_do_request(sc->sc_udev, &req, 0); 376 } 377 378 /* 379 * Reset the printer, then wait until it's selected and not busy. 380 */ 381 int 382 ulptopen(dev, flag, mode, p) 383 dev_t dev; 384 int flag; 385 int mode; 386 struct proc *p; 387 { 388 u_char flags = ULPTFLAGS(dev); 389 struct ulpt_softc *sc; 390 usbd_status err; 391 int spin, error; 392 393 USB_GET_SC_OPEN(ulpt, ULPTUNIT(dev), sc); 394 395 if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) 396 return (ENXIO); 397 398 if (sc->sc_state) 399 return (EBUSY); 400 401 sc->sc_state = ULPT_INIT; 402 sc->sc_flags = flags; 403 DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags)); 404 405 #if defined(ULPT_DEBUG) && defined(__FreeBSD__) 406 /* Ignoring these flags might not be a good idea */ 407 if ((flags & ~ULPT_NOPRIME) != 0) 408 printf("ulptopen: flags ignored: %b\n", flags, 409 "\20\3POS_INIT\4POS_ACK\6PRIME_OPEN\7AUTOLF\10BYPASS"); 410 #endif 411 412 413 if ((flags & ULPT_NOPRIME) == 0) 414 ulpt_reset(sc); 415 416 for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) { 417 if (spin >= TIMEOUT) { 418 sc->sc_state = 0; 419 return (EBUSY); 420 } 421 422 /* wait 1/4 second, give up if we get a signal */ 423 error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "ulptop", STEP); 424 if (error != EWOULDBLOCK) { 425 sc->sc_state = 0; 426 return (error); 427 } 428 } 429 430 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulk, 0, &sc->sc_bulkpipe); 431 if (err) { 432 sc->sc_state = 0; 433 return (EIO); 434 } 435 436 sc->sc_state = ULPT_OPEN; 437 438 DPRINTF(("ulptopen: done\n")); 439 return (0); 440 } 441 442 int 443 ulpt_statusmsg(status, sc) 444 u_char status; 445 struct ulpt_softc *sc; 446 { 447 u_char new; 448 449 status = (status ^ LPS_INVERT) & LPS_MASK; 450 new = status & ~sc->sc_laststatus; 451 sc->sc_laststatus = status; 452 453 if (new & LPS_SELECT) 454 log(LOG_NOTICE, "%s: offline\n", USBDEVNAME(sc->sc_dev)); 455 else if (new & LPS_NOPAPER) 456 log(LOG_NOTICE, "%s: out of paper\n", USBDEVNAME(sc->sc_dev)); 457 else if (new & LPS_NERR) 458 log(LOG_NOTICE, "%s: output error\n", USBDEVNAME(sc->sc_dev)); 459 460 return (status); 461 } 462 463 int 464 ulptclose(dev, flag, mode, p) 465 dev_t dev; 466 int flag; 467 int mode; 468 struct proc *p; 469 { 470 struct ulpt_softc *sc; 471 472 USB_GET_SC(ulpt, ULPTUNIT(dev), sc); 473 474 if (sc->sc_state != ULPT_OPEN) 475 /* We are being forced to close before the open completed. */ 476 return (0); 477 478 usbd_close_pipe(sc->sc_bulkpipe); 479 sc->sc_bulkpipe = 0; 480 481 sc->sc_state = 0; 482 483 DPRINTF(("ulptclose: closed\n")); 484 return (0); 485 } 486 487 int 488 ulpt_do_write(sc, uio, flags) 489 struct ulpt_softc *sc; 490 struct uio *uio; 491 int flags; 492 { 493 u_int32_t n; 494 int error = 0; 495 void *bufp; 496 usbd_xfer_handle xfer; 497 usbd_status err; 498 499 DPRINTF(("ulptwrite\n")); 500 xfer = usbd_alloc_xfer(sc->sc_udev); 501 if (xfer == NULL) 502 return (ENOMEM); 503 bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); 504 if (bufp == NULL) { 505 usbd_free_xfer(xfer); 506 return (ENOMEM); 507 } 508 while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) { 509 ulpt_statusmsg(ulpt_status(sc), sc); 510 error = uiomove(bufp, n, uio); 511 if (error) 512 break; 513 DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n)); 514 err = usbd_bulk_transfer(xfer, sc->sc_bulkpipe, USBD_NO_COPY, 515 USBD_NO_TIMEOUT, bufp, &n, "ulptwr"); 516 if (err) { 517 DPRINTF(("ulptwrite: error=%d\n", err)); 518 error = EIO; 519 break; 520 } 521 } 522 usbd_free_xfer(xfer); 523 524 return (error); 525 } 526 527 int 528 ulptwrite(dev, uio, flags) 529 dev_t dev; 530 struct uio *uio; 531 int flags; 532 { 533 struct ulpt_softc *sc; 534 int error; 535 536 USB_GET_SC(ulpt, ULPTUNIT(dev), sc); 537 538 if (sc->sc_dying) 539 return (EIO); 540 541 sc->sc_refcnt++; 542 error = ulpt_do_write(sc, uio, flags); 543 if (--sc->sc_refcnt < 0) 544 usb_detach_wakeup(USBDEV(sc->sc_dev)); 545 return (error); 546 } 547 548 int 549 ulptioctl(dev, cmd, data, flag, p) 550 dev_t dev; 551 u_long cmd; 552 caddr_t data; 553 int flag; 554 struct proc *p; 555 { 556 int error = 0; 557 558 switch (cmd) { 559 default: 560 error = ENODEV; 561 } 562 563 return (error); 564 } 565 566 #if 0 567 /* XXX This does not belong here. */ 568 /* 569 * Print select parts of a IEEE 1284 device ID. 570 */ 571 void 572 ieee1284_print_id(str) 573 char *str; 574 { 575 char *p, *q; 576 577 for (p = str-1; p; p = strchr(p, ';')) { 578 p++; /* skip ';' */ 579 if (strncmp(p, "MFG:", 4) == 0 || 580 strncmp(p, "MANUFACTURER:", 14) == 0 || 581 strncmp(p, "MDL:", 4) == 0 || 582 strncmp(p, "MODEL:", 6) == 0) { 583 q = strchr(p, ';'); 584 if (q) 585 printf("%.*s", (int)(q - p + 1), p); 586 } 587 } 588 } 589 #endif 590 591 #if defined(__FreeBSD__) 592 DRIVER_MODULE(ulpt, uhub, ulpt_driver, ulpt_devclass, usbd_driver_load, 0); 593 #endif 594