1 /* $NetBSD: ulpt.c,v 1.38 2000/06/01 14:29:00 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 (lennart@augustsson.net) 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__) || defined(__OpenBSD__) 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(void *); 147 148 int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int); 149 int ulpt_status(struct ulpt_softc *); 150 void ulpt_reset(struct ulpt_softc *); 151 int ulpt_statusmsg(u_char, struct ulpt_softc *); 152 153 void ieee1284_print_id(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 reason 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(device_ptr_t self, enum devact act) 278 { 279 struct ulpt_softc *sc = (struct ulpt_softc *)self; 280 281 switch (act) { 282 case DVACT_ACTIVATE: 283 return (EOPNOTSUPP); 284 break; 285 286 case DVACT_DEACTIVATE: 287 sc->sc_dying = 1; 288 break; 289 } 290 return (0); 291 } 292 #endif 293 294 USB_DETACH(ulpt) 295 { 296 USB_DETACH_START(ulpt, sc); 297 int s; 298 #if defined(__NetBSD__) || defined(__OpenBSD__) 299 int maj, mn; 300 301 DPRINTF(("ulpt_detach: sc=%p flags=%d\n", sc, flags)); 302 #elif defined(__FreeBSD__) 303 DPRINTF(("ulpt_detach: sc=%p\n", sc)); 304 #endif 305 306 sc->sc_dying = 1; 307 if (sc->sc_bulkpipe != NULL) 308 usbd_abort_pipe(sc->sc_bulkpipe); 309 310 s = splusb(); 311 if (--sc->sc_refcnt >= 0) { 312 /* There is noone to wake, aborting the pipe is enough */ 313 /* Wait for processes to go away. */ 314 usb_detach_wait(USBDEV(sc->sc_dev)); 315 } 316 splx(s); 317 318 #if defined(__NetBSD__) || defined(__OpenBSD__) 319 /* locate the major number */ 320 for (maj = 0; maj < nchrdev; maj++) 321 if (cdevsw[maj].d_open == ulptopen) 322 break; 323 324 /* Nuke the vnodes for any open instances (calls close). */ 325 mn = self->dv_unit; 326 vdevgone(maj, mn, mn, VCHR); 327 #elif defined(__FreeBSD__) 328 /* XXX not implemented yet */ 329 330 destroy_dev(sc->dev); 331 destroy_dev(sc->dev_noprime); 332 #endif 333 334 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 335 USBDEV(sc->sc_dev)); 336 337 return (0); 338 } 339 340 int 341 ulpt_status(struct ulpt_softc *sc) 342 { 343 usb_device_request_t req; 344 usbd_status err; 345 u_char status; 346 347 req.bmRequestType = UT_READ_CLASS_INTERFACE; 348 req.bRequest = UR_GET_PORT_STATUS; 349 USETW(req.wValue, 0); 350 USETW(req.wIndex, sc->sc_ifaceno); 351 USETW(req.wLength, 1); 352 err = usbd_do_request(sc->sc_udev, &req, &status); 353 DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); 354 if (!err) 355 return (status); 356 else 357 return (0); 358 } 359 360 void 361 ulpt_reset(struct ulpt_softc *sc) 362 { 363 usb_device_request_t req; 364 365 DPRINTFN(1, ("ulpt_reset\n")); 366 req.bmRequestType = UT_WRITE_CLASS_OTHER; 367 req.bRequest = UR_SOFT_RESET; 368 USETW(req.wValue, 0); 369 USETW(req.wIndex, sc->sc_ifaceno); 370 USETW(req.wLength, 0); 371 (void)usbd_do_request(sc->sc_udev, &req, 0); 372 } 373 374 /* 375 * Reset the printer, then wait until it's selected and not busy. 376 */ 377 int 378 ulptopen(dev_t dev, int flag, int mode, struct proc *p) 379 { 380 u_char flags = ULPTFLAGS(dev); 381 struct ulpt_softc *sc; 382 usbd_status err; 383 int spin, error; 384 385 USB_GET_SC_OPEN(ulpt, ULPTUNIT(dev), sc); 386 387 if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) 388 return (ENXIO); 389 390 if (sc->sc_state) 391 return (EBUSY); 392 393 sc->sc_state = ULPT_INIT; 394 sc->sc_flags = flags; 395 DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags)); 396 397 #if defined(ULPT_DEBUG) && defined(__FreeBSD__) 398 /* Ignoring these flags might not be a good idea */ 399 if ((flags & ~ULPT_NOPRIME) != 0) 400 printf("ulptopen: flags ignored: %b\n", flags, 401 "\20\3POS_INIT\4POS_ACK\6PRIME_OPEN\7AUTOLF\10BYPASS"); 402 #endif 403 404 405 if ((flags & ULPT_NOPRIME) == 0) 406 ulpt_reset(sc); 407 408 for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) { 409 if (spin >= TIMEOUT) { 410 sc->sc_state = 0; 411 return (EBUSY); 412 } 413 414 /* wait 1/4 second, give up if we get a signal */ 415 error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "ulptop", STEP); 416 if (error != EWOULDBLOCK) { 417 sc->sc_state = 0; 418 return (error); 419 } 420 } 421 422 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulk, 0, &sc->sc_bulkpipe); 423 if (err) { 424 sc->sc_state = 0; 425 return (EIO); 426 } 427 428 sc->sc_state = ULPT_OPEN; 429 430 DPRINTF(("ulptopen: done\n")); 431 return (0); 432 } 433 434 int 435 ulpt_statusmsg(u_char status, struct ulpt_softc *sc) 436 { 437 u_char new; 438 439 status = (status ^ LPS_INVERT) & LPS_MASK; 440 new = status & ~sc->sc_laststatus; 441 sc->sc_laststatus = status; 442 443 if (new & LPS_SELECT) 444 log(LOG_NOTICE, "%s: offline\n", USBDEVNAME(sc->sc_dev)); 445 else if (new & LPS_NOPAPER) 446 log(LOG_NOTICE, "%s: out of paper\n", USBDEVNAME(sc->sc_dev)); 447 else if (new & LPS_NERR) 448 log(LOG_NOTICE, "%s: output error\n", USBDEVNAME(sc->sc_dev)); 449 450 return (status); 451 } 452 453 int 454 ulptclose(dev_t dev, int flag, int mode, struct proc *p) 455 { 456 struct ulpt_softc *sc; 457 458 USB_GET_SC(ulpt, ULPTUNIT(dev), sc); 459 460 if (sc->sc_state != ULPT_OPEN) 461 /* We are being forced to close before the open completed. */ 462 return (0); 463 464 usbd_close_pipe(sc->sc_bulkpipe); 465 sc->sc_bulkpipe = 0; 466 467 sc->sc_state = 0; 468 469 DPRINTF(("ulptclose: closed\n")); 470 return (0); 471 } 472 473 int 474 ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags) 475 { 476 u_int32_t n; 477 int error = 0; 478 void *bufp; 479 usbd_xfer_handle xfer; 480 usbd_status err; 481 482 DPRINTF(("ulptwrite\n")); 483 xfer = usbd_alloc_xfer(sc->sc_udev); 484 if (xfer == NULL) 485 return (ENOMEM); 486 bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); 487 if (bufp == NULL) { 488 usbd_free_xfer(xfer); 489 return (ENOMEM); 490 } 491 while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) { 492 ulpt_statusmsg(ulpt_status(sc), sc); 493 error = uiomove(bufp, n, uio); 494 if (error) 495 break; 496 DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n)); 497 err = usbd_bulk_transfer(xfer, sc->sc_bulkpipe, USBD_NO_COPY, 498 USBD_NO_TIMEOUT, bufp, &n, "ulptwr"); 499 if (err) { 500 DPRINTF(("ulptwrite: error=%d\n", err)); 501 error = EIO; 502 break; 503 } 504 } 505 usbd_free_xfer(xfer); 506 507 return (error); 508 } 509 510 int 511 ulptwrite(dev_t dev, struct uio *uio, int flags) 512 { 513 struct ulpt_softc *sc; 514 int error; 515 516 USB_GET_SC(ulpt, ULPTUNIT(dev), sc); 517 518 if (sc->sc_dying) 519 return (EIO); 520 521 sc->sc_refcnt++; 522 error = ulpt_do_write(sc, uio, flags); 523 if (--sc->sc_refcnt < 0) 524 usb_detach_wakeup(USBDEV(sc->sc_dev)); 525 return (error); 526 } 527 528 int 529 ulptioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 530 { 531 int error = 0; 532 533 switch (cmd) { 534 default: 535 error = ENODEV; 536 } 537 538 return (error); 539 } 540 541 #if 0 542 /* XXX This does not belong here. */ 543 /* 544 * Print select parts of a IEEE 1284 device ID. 545 */ 546 void 547 ieee1284_print_id(char *str) 548 { 549 char *p, *q; 550 551 for (p = str-1; p; p = strchr(p, ';')) { 552 p++; /* skip ';' */ 553 if (strncmp(p, "MFG:", 4) == 0 || 554 strncmp(p, "MANUFACTURER:", 14) == 0 || 555 strncmp(p, "MDL:", 4) == 0 || 556 strncmp(p, "MODEL:", 6) == 0) { 557 q = strchr(p, ';'); 558 if (q) 559 printf("%.*s", (int)(q - p + 1), p); 560 } 561 } 562 } 563 #endif 564 565 #if defined(__FreeBSD__) 566 DRIVER_MODULE(ulpt, uhub, ulpt_driver, ulpt_devclass, usbd_driver_load, 0); 567 #endif 568