1 /* $OpenBSD: ulpt.c,v 1.53 2016/03/03 18:13:24 stefan 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/device.h> 43 #include <sys/uio.h> 44 #include <sys/conf.h> 45 #include <sys/vnode.h> 46 #include <sys/syslog.h> 47 #include <sys/types.h> 48 #include <sys/malloc.h> 49 50 #include <dev/usb/usb.h> 51 #include <dev/usb/usbdi.h> 52 #include <dev/usb/usbdi_util.h> 53 #include <dev/usb/usbdevs.h> 54 #include <dev/usb/usb_quirks.h> 55 56 #define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */ 57 #define STEP hz/4 58 59 #define LPTPRI (PZERO+8) 60 #define ULPT_BSIZE 16384 61 62 #ifdef ULPT_DEBUG 63 #define DPRINTF(x) do { if (ulptdebug) printf x; } while (0) 64 #define DPRINTFN(n,x) do { if (ulptdebug>(n)) printf x; } while (0) 65 int ulptdebug = 0; 66 #else 67 #define DPRINTF(x) 68 #define DPRINTFN(n,x) 69 #endif 70 71 #define UR_GET_DEVICE_ID 0 72 #define UR_GET_PORT_STATUS 1 73 #define UR_SOFT_RESET 2 74 75 #define LPS_NERR 0x08 /* printer no error */ 76 #define LPS_SELECT 0x10 /* printer selected */ 77 #define LPS_NOPAPER 0x20 /* printer out of paper */ 78 #define LPS_INVERT (LPS_SELECT|LPS_NERR) 79 #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) 80 81 struct ulpt_softc { 82 struct device sc_dev; 83 struct usbd_device *sc_udev; /* device */ 84 struct usbd_interface *sc_iface;/* interface */ 85 int sc_ifaceno; 86 87 int sc_out; 88 struct usbd_pipe *sc_out_pipe; /* bulk out pipe */ 89 90 int sc_in; 91 struct usbd_pipe *sc_in_pipe; /* bulk in pipe */ 92 struct usbd_xfer *sc_in_xfer1; 93 struct usbd_xfer *sc_in_xfer2; 94 u_char sc_junk[64]; /* somewhere to dump input */ 95 96 u_char sc_state; 97 #define ULPT_OPEN 0x01 /* device is open */ 98 #define ULPT_OBUSY 0x02 /* printer is busy doing output */ 99 #define ULPT_INIT 0x04 /* waiting to initialize for open */ 100 u_char sc_flags; 101 #define ULPT_NOPRIME 0x40 /* don't prime on open */ 102 #define ULPT_EFIRMWARE 0x80 /* error loading firmware */ 103 u_char sc_laststatus; 104 105 int sc_refcnt; 106 107 struct ulpt_fwdev *sc_fwdev; 108 }; 109 110 void ulpt_disco(void *); 111 112 int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int); 113 int ulpt_status(struct ulpt_softc *); 114 void ulpt_reset(struct ulpt_softc *); 115 int ulpt_statusmsg(u_char, struct ulpt_softc *); 116 117 /* 118 * Printers which need firmware uploads. 119 */ 120 void ulpt_load_firmware(struct device *); 121 usbd_status ulpt_ucode_loader_hp(struct ulpt_softc *); 122 struct ulpt_fwdev { 123 struct usb_devno uv_dev; 124 char *ucode_name; 125 usbd_status (*ucode_loader)(struct ulpt_softc *); 126 } ulpt_fwdevs[] = { 127 { 128 { USB_VENDOR_HP, USB_PRODUCT_HP_1000 }, 129 "ulpt-hp1000", 130 ulpt_ucode_loader_hp 131 }, 132 { 133 { USB_VENDOR_HP, USB_PRODUCT_HP_1005 }, 134 "ulpt-hp1005", 135 ulpt_ucode_loader_hp 136 }, 137 { 138 { USB_VENDOR_HP, USB_PRODUCT_HP_1018 }, 139 "ulpt-hp1018", 140 ulpt_ucode_loader_hp 141 }, 142 { 143 { USB_VENDOR_HP, USB_PRODUCT_HP_1020 }, 144 "ulpt-hp1020", 145 ulpt_ucode_loader_hp 146 }, 147 }; 148 149 #if 0 150 void ieee1284_print_id(char *); 151 #endif 152 153 #define ULPTUNIT(s) (minor(s) & 0x1f) 154 #define ULPTFLAGS(s) (minor(s) & 0xe0) 155 156 157 int ulpt_match(struct device *, void *, void *); 158 void ulpt_attach(struct device *, struct device *, void *); 159 int ulpt_detach(struct device *, int); 160 161 struct cfdriver ulpt_cd = { 162 NULL, "ulpt", DV_DULL 163 }; 164 165 const struct cfattach ulpt_ca = { 166 sizeof(struct ulpt_softc), ulpt_match, ulpt_attach, ulpt_detach 167 }; 168 169 int 170 ulpt_match(struct device *parent, void *match, void *aux) 171 { 172 struct usb_attach_arg *uaa = aux; 173 usb_interface_descriptor_t *id; 174 175 DPRINTFN(10,("ulpt_match\n")); 176 if (uaa->iface == NULL) 177 return (UMATCH_NONE); 178 id = usbd_get_interface_descriptor(uaa->iface); 179 if (id != NULL && 180 id->bInterfaceClass == UICLASS_PRINTER && 181 id->bInterfaceSubClass == UISUBCLASS_PRINTER && 182 ((id->bInterfaceProtocol == UIPROTO_PRINTER_UNI) || 183 (id->bInterfaceProtocol == UIPROTO_PRINTER_BI) || 184 (id->bInterfaceProtocol == UIPROTO_PRINTER_1284))) 185 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); 186 return (UMATCH_NONE); 187 } 188 189 void 190 ulpt_load_firmware(struct device *self) 191 { 192 struct ulpt_softc *sc = (struct ulpt_softc *)self; 193 usbd_status err; 194 195 err = (sc->sc_fwdev->ucode_loader)(sc); 196 if (err != USBD_NORMAL_COMPLETION) { 197 sc->sc_flags |= ULPT_EFIRMWARE; 198 printf("%s: could not load firmware '%s'\n", 199 sc->sc_dev.dv_xname, sc->sc_fwdev->ucode_name); 200 } else 201 sc->sc_flags &= ~ULPT_EFIRMWARE; 202 } 203 204 #define ulpt_lookup(v, p) \ 205 ((struct ulpt_fwdev *)usb_lookup(ulpt_fwdevs, v, p)) 206 207 void 208 ulpt_attach(struct device *parent, struct device *self, void *aux) 209 { 210 struct ulpt_softc *sc = (struct ulpt_softc *)self; 211 struct usb_attach_arg *uaa = aux; 212 struct usbd_device *dev = uaa->device; 213 struct usbd_interface *iface = uaa->iface; 214 usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface); 215 usb_interface_descriptor_t *id, *iend; 216 usb_config_descriptor_t *cdesc; 217 usbd_status err; 218 usb_endpoint_descriptor_t *ed; 219 int i, altno; 220 221 DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); 222 223 //printf("%s: iclass %d/%d\n", sc->sc_dev.dv_xname, 224 // ifcd->bInterfaceClass, ifcd->bInterfaceSubClass); 225 226 /* XXX 227 * Stepping through the alternate settings needs to be abstracted out. 228 */ 229 cdesc = usbd_get_config_descriptor(dev); 230 if (cdesc == NULL) { 231 printf("%s: failed to get configuration descriptor\n", 232 sc->sc_dev.dv_xname); 233 return; 234 } 235 iend = (usb_interface_descriptor_t *) 236 ((char *)cdesc + UGETW(cdesc->wTotalLength)); 237 #ifdef DIAGNOSTIC 238 if (ifcd < (usb_interface_descriptor_t *)cdesc || 239 ifcd >= iend) 240 panic("ulpt: iface desc out of range"); 241 #endif 242 /* Step through all the descriptors looking for bidir mode */ 243 for (id = ifcd, altno = 0; 244 id < iend; 245 id = (void *)((char *)id + id->bLength)) { 246 if (id->bDescriptorType == UDESC_INTERFACE && 247 id->bInterfaceNumber == ifcd->bInterfaceNumber) { 248 if (id->bInterfaceClass == UICLASS_PRINTER && 249 id->bInterfaceSubClass == UISUBCLASS_PRINTER && 250 (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /*|| 251 id->bInterfaceProtocol == UIPROTO_PRINTER_1284*/)) 252 goto found; 253 altno++; 254 } 255 } 256 id = ifcd; /* not found, use original */ 257 found: 258 if (id != ifcd) { 259 /* Found a new bidir setting */ 260 DPRINTF(("ulpt_attach: set altno = %d\n", altno)); 261 err = usbd_set_interface(iface, altno); 262 if (err) { 263 printf("%s: setting alternate interface failed\n", 264 sc->sc_dev.dv_xname); 265 usbd_deactivate(sc->sc_udev); 266 return; 267 } 268 } 269 270 271 sc->sc_in = -1; 272 sc->sc_out = -1; 273 274 id = usbd_get_interface_descriptor(iface); 275 for (i = 0; i < id->bNumEndpoints; i++) { 276 ed = usbd_interface2endpoint_descriptor(iface, i); 277 if (ed == NULL) { 278 printf("%s: couldn't get ep %d\n", 279 sc->sc_dev.dv_xname, i); 280 return; 281 } 282 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 283 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 284 sc->sc_in = ed->bEndpointAddress; 285 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 286 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 287 sc->sc_out = ed->bEndpointAddress; 288 } 289 } 290 if (sc->sc_out == -1) { 291 printf("%s: could not find bulk out endpoint\n", 292 sc->sc_dev.dv_xname); 293 usbd_deactivate(sc->sc_udev); 294 return; 295 } 296 297 if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) { 298 /* This device doesn't handle reading properly. */ 299 sc->sc_in = -1; 300 } 301 302 printf("%s: using %s-directional mode\n", sc->sc_dev.dv_xname, 303 sc->sc_in >= 0 ? "bi" : "uni"); 304 305 DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out)); 306 307 sc->sc_iface = iface; 308 sc->sc_ifaceno = id->bInterfaceNumber; 309 sc->sc_udev = dev; 310 311 /* maybe the device needs firmware */ 312 sc->sc_fwdev = ulpt_lookup(uaa->vendor, uaa->product); 313 if (sc->sc_fwdev) 314 config_mountroot(self, ulpt_load_firmware); 315 316 #if 0 317 /* 318 * This code is disabled because for some mysterious reason it causes 319 * printing not to work. But only sometimes, and mostly with 320 * UHCI and less often with OHCI. *sigh* 321 */ 322 { 323 usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); 324 usb_device_request_t req; 325 int len, alen; 326 327 req.bmRequestType = UT_READ_CLASS_INTERFACE; 328 req.bRequest = UR_GET_DEVICE_ID; 329 USETW(req.wValue, cd->bConfigurationValue); 330 USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); 331 USETW(req.wLength, DEVINFOSIZE - 1); 332 err = usbd_do_request_flags(dev, &req, devinfop, USBD_SHORT_XFER_OK, 333 &alen, USBD_DEFAULT_TIMEOUT); 334 if (err) { 335 printf("%s: cannot get device id\n", sc->sc_dev.dv_xname); 336 } else if (alen <= 2) { 337 printf("%s: empty device id, no printer connected?\n", 338 sc->sc_dev.dv_xname); 339 } else { 340 /* devinfop now contains an IEEE-1284 device ID */ 341 len = ((devinfop[0] & 0xff) << 8) | (devinfop[1] & 0xff); 342 if (len > DEVINFOSIZE - 3) 343 len = DEVINFOSIZE - 3; 344 devinfo[len] = 0; 345 printf("%s: device id <", sc->sc_dev.dv_xname); 346 ieee1284_print_id(devinfop+2); 347 printf(">\n"); 348 } 349 } 350 #endif 351 } 352 353 int 354 ulpt_detach(struct device *self, int flags) 355 { 356 struct ulpt_softc *sc = (struct ulpt_softc *)self; 357 int s; 358 int maj, mn; 359 360 DPRINTF(("ulpt_detach: sc=%p\n", sc)); 361 362 if (sc->sc_out_pipe != NULL) 363 usbd_abort_pipe(sc->sc_out_pipe); 364 if (sc->sc_in_pipe != NULL) 365 usbd_abort_pipe(sc->sc_in_pipe); 366 367 s = splusb(); 368 if (--sc->sc_refcnt >= 0) { 369 /* There is noone to wake, aborting the pipe is enough */ 370 /* Wait for processes to go away. */ 371 usb_detach_wait(&sc->sc_dev); 372 } 373 splx(s); 374 375 /* locate the major number */ 376 for (maj = 0; maj < nchrdev; maj++) 377 if (cdevsw[maj].d_open == ulptopen) 378 break; 379 380 /* Nuke the vnodes for any open instances (calls close). */ 381 mn = self->dv_unit; 382 vdevgone(maj, mn, mn, VCHR); 383 vdevgone(maj, mn | ULPT_NOPRIME , mn | ULPT_NOPRIME, VCHR); 384 385 return (0); 386 } 387 388 int 389 ulpt_status(struct ulpt_softc *sc) 390 { 391 usb_device_request_t req; 392 usbd_status err; 393 u_char status; 394 395 req.bmRequestType = UT_READ_CLASS_INTERFACE; 396 req.bRequest = UR_GET_PORT_STATUS; 397 USETW(req.wValue, 0); 398 USETW(req.wIndex, sc->sc_ifaceno); 399 USETW(req.wLength, 1); 400 err = usbd_do_request(sc->sc_udev, &req, &status); 401 DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); 402 if (!err) 403 return (status); 404 else 405 return (0); 406 } 407 408 void 409 ulpt_reset(struct ulpt_softc *sc) 410 { 411 usb_device_request_t req; 412 413 DPRINTFN(1, ("ulpt_reset\n")); 414 req.bRequest = UR_SOFT_RESET; 415 USETW(req.wValue, 0); 416 USETW(req.wIndex, sc->sc_ifaceno); 417 USETW(req.wLength, 0); 418 419 /* 420 * There was a mistake in the USB printer 1.0 spec that gave the 421 * request type as UT_WRITE_CLASS_OTHER; it should have been 422 * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, 423 * so we try both. 424 */ 425 req.bmRequestType = UT_WRITE_CLASS_OTHER; 426 if (usbd_do_request(sc->sc_udev, &req, 0)) { /* 1.0 */ 427 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 428 (void)usbd_do_request(sc->sc_udev, &req, 0); /* 1.1 */ 429 } 430 } 431 432 static void 433 ulpt_input(struct usbd_xfer *xfer, void *priv, usbd_status status) 434 { 435 struct ulpt_softc *sc = priv; 436 437 DPRINTFN(2,("ulpt_input: got some data\n")); 438 /* Do it again. */ 439 if (xfer == sc->sc_in_xfer1) 440 usbd_transfer(sc->sc_in_xfer2); 441 else 442 usbd_transfer(sc->sc_in_xfer1); 443 } 444 445 int ulptusein = 1; 446 447 /* 448 * Reset the printer, then wait until it's selected and not busy. 449 */ 450 int 451 ulptopen(dev_t dev, int flag, int mode, struct proc *p) 452 { 453 u_char flags = ULPTFLAGS(dev); 454 struct ulpt_softc *sc; 455 usbd_status err; 456 int error; 457 458 if (ULPTUNIT(dev) >= ulpt_cd.cd_ndevs) 459 return (ENXIO); 460 sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; 461 if (sc == NULL) 462 return (ENXIO); 463 464 if (sc == NULL || sc->sc_iface == NULL || usbd_is_dying(sc->sc_udev)) 465 return (ENXIO); 466 467 if (sc->sc_state) 468 return (EBUSY); 469 470 /* If a previous attempt to load firmware failed, retry. */ 471 if (sc->sc_flags & ULPT_EFIRMWARE) { 472 ulpt_load_firmware(&sc->sc_dev); 473 if (sc->sc_flags & ULPT_EFIRMWARE) 474 return (EIO); 475 } 476 477 sc->sc_state = ULPT_INIT; 478 sc->sc_flags = flags; 479 DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags)); 480 481 error = 0; 482 sc->sc_refcnt++; 483 484 if ((flags & ULPT_NOPRIME) == 0) { 485 ulpt_reset(sc); 486 if (usbd_is_dying(sc->sc_udev)) { 487 error = ENXIO; 488 sc->sc_state = 0; 489 goto done; 490 } 491 } 492 493 err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); 494 if (err) { 495 sc->sc_state = 0; 496 error = EIO; 497 goto done; 498 } 499 if (ulptusein && sc->sc_in != -1) { 500 DPRINTF(("ulpt_open: open input pipe\n")); 501 err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe); 502 if (err) { 503 error = EIO; 504 usbd_close_pipe(sc->sc_out_pipe); 505 sc->sc_out_pipe = NULL; 506 sc->sc_state = 0; 507 goto done; 508 } 509 sc->sc_in_xfer1 = usbd_alloc_xfer(sc->sc_udev); 510 sc->sc_in_xfer2 = usbd_alloc_xfer(sc->sc_udev); 511 if (sc->sc_in_xfer1 == NULL || sc->sc_in_xfer2 == NULL) { 512 error = ENOMEM; 513 if (sc->sc_in_xfer1 != NULL) { 514 usbd_free_xfer(sc->sc_in_xfer1); 515 sc->sc_in_xfer1 = NULL; 516 } 517 if (sc->sc_in_xfer2 != NULL) { 518 usbd_free_xfer(sc->sc_in_xfer2); 519 sc->sc_in_xfer2 = NULL; 520 } 521 usbd_close_pipe(sc->sc_out_pipe); 522 sc->sc_out_pipe = NULL; 523 usbd_close_pipe(sc->sc_in_pipe); 524 sc->sc_in_pipe = NULL; 525 sc->sc_state = 0; 526 goto done; 527 } 528 usbd_setup_xfer(sc->sc_in_xfer1, sc->sc_in_pipe, sc, 529 sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK, 530 USBD_NO_TIMEOUT, ulpt_input); 531 usbd_setup_xfer(sc->sc_in_xfer2, sc->sc_in_pipe, sc, 532 sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK, 533 USBD_NO_TIMEOUT, ulpt_input); 534 usbd_transfer(sc->sc_in_xfer1); /* ignore failed start */ 535 } 536 537 sc->sc_state = ULPT_OPEN; 538 539 done: 540 if (--sc->sc_refcnt < 0) 541 usb_detach_wakeup(&sc->sc_dev); 542 543 DPRINTF(("ulptopen: done, error=%d\n", error)); 544 return (error); 545 } 546 547 int 548 ulpt_statusmsg(u_char status, struct ulpt_softc *sc) 549 { 550 u_char new; 551 552 status = (status ^ LPS_INVERT) & LPS_MASK; 553 new = status & ~sc->sc_laststatus; 554 sc->sc_laststatus = status; 555 556 if (new & LPS_SELECT) 557 log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname); 558 else if (new & LPS_NOPAPER) 559 log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname); 560 else if (new & LPS_NERR) 561 log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname); 562 563 return (status); 564 } 565 566 int 567 ulptclose(dev_t dev, int flag, int mode, struct proc *p) 568 { 569 struct ulpt_softc *sc; 570 571 sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; 572 573 if (sc->sc_state != ULPT_OPEN) 574 /* We are being forced to close before the open completed. */ 575 return (0); 576 577 if (sc->sc_out_pipe != NULL) { 578 usbd_close_pipe(sc->sc_out_pipe); 579 sc->sc_out_pipe = NULL; 580 } 581 if (sc->sc_in_pipe != NULL) { 582 usbd_abort_pipe(sc->sc_in_pipe); 583 usbd_close_pipe(sc->sc_in_pipe); 584 sc->sc_in_pipe = NULL; 585 if (sc->sc_in_xfer1 != NULL) { 586 usbd_free_xfer(sc->sc_in_xfer1); 587 sc->sc_in_xfer1 = NULL; 588 } 589 if (sc->sc_in_xfer2 != NULL) { 590 usbd_free_xfer(sc->sc_in_xfer2); 591 sc->sc_in_xfer2 = NULL; 592 } 593 } 594 595 sc->sc_state = 0; 596 597 DPRINTF(("ulptclose: closed\n")); 598 return (0); 599 } 600 601 int 602 ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags) 603 { 604 size_t n; 605 int error = 0; 606 void *bufp; 607 struct usbd_xfer *xfer; 608 usbd_status err; 609 610 DPRINTF(("ulptwrite\n")); 611 xfer = usbd_alloc_xfer(sc->sc_udev); 612 if (xfer == NULL) 613 return (ENOMEM); 614 bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); 615 if (bufp == NULL) { 616 usbd_free_xfer(xfer); 617 return (ENOMEM); 618 } 619 while ((n = ulmin(ULPT_BSIZE, uio->uio_resid)) != 0) { 620 ulpt_statusmsg(ulpt_status(sc), sc); 621 error = uiomove(bufp, n, uio); 622 if (error) 623 break; 624 DPRINTFN(1, ("ulptwrite: transfer %zu bytes\n", n)); 625 usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, n, 626 USBD_NO_COPY | USBD_SYNCHRONOUS | USBD_CATCH, 0, NULL); 627 err = usbd_transfer(xfer); 628 if (err) { 629 usbd_clear_endpoint_stall(sc->sc_out_pipe); 630 DPRINTF(("ulptwrite: error=%d\n", err)); 631 error = EIO; 632 break; 633 } 634 } 635 usbd_free_xfer(xfer); 636 637 return (error); 638 } 639 640 int 641 ulptwrite(dev_t dev, struct uio *uio, int flags) 642 { 643 struct ulpt_softc *sc; 644 int error; 645 646 sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; 647 648 if (usbd_is_dying(sc->sc_udev) || (sc->sc_flags & ULPT_EFIRMWARE)) 649 return (EIO); 650 651 sc->sc_refcnt++; 652 error = ulpt_do_write(sc, uio, flags); 653 if (--sc->sc_refcnt < 0) 654 usb_detach_wakeup(&sc->sc_dev); 655 return (error); 656 } 657 658 usbd_status 659 ulpt_ucode_loader_hp(struct ulpt_softc *sc) 660 { 661 usbd_status error; 662 int load_error; 663 uint8_t *ucode; 664 uint32_t len; 665 size_t ucode_size; 666 const char *ucode_name = sc->sc_fwdev->ucode_name; 667 int offset = 0, remain; 668 struct usbd_xfer *xfer; 669 void *bufp; 670 671 /* open microcode file */ 672 load_error = loadfirmware(ucode_name, &ucode, &ucode_size); 673 if (load_error != 0) { 674 printf("%s: failed loadfirmware of file %s (error %d)\n", 675 sc->sc_dev.dv_xname, ucode_name, load_error); 676 return (USBD_INVAL); 677 } 678 679 /* upload microcode */ 680 error = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); 681 if (error) 682 goto free_ucode; 683 xfer = usbd_alloc_xfer(sc->sc_udev); 684 if (xfer == NULL) 685 goto close_pipe; 686 bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); 687 if (bufp == NULL) { 688 error = USBD_NOMEM; 689 goto free_xfer; 690 } 691 remain = ucode_size; 692 while (remain > 0) { 693 len = min(remain, ULPT_BSIZE); 694 memcpy(bufp, &ucode[offset], len); 695 usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, len, 696 USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL); 697 error = usbd_transfer(xfer); 698 if (error != USBD_NORMAL_COMPLETION) { 699 usbd_clear_endpoint_stall(sc->sc_out_pipe); 700 printf("%s: ucode upload error=%s!\n", 701 sc->sc_dev.dv_xname, usbd_errstr(error)); 702 break; 703 } 704 DPRINTF(("%s: uploaded %d bytes ucode\n", 705 sc->sc_dev.dv_xname, len)); 706 707 offset += len; 708 remain -= len; 709 } 710 free_xfer: 711 usbd_free_xfer(xfer); 712 close_pipe: 713 usbd_close_pipe(sc->sc_out_pipe); 714 sc->sc_out_pipe = NULL; 715 free_ucode: 716 free(ucode, M_DEVBUF, 0); 717 718 return (error); 719 } 720 721 #if 0 722 /* XXX This does not belong here. */ 723 /* 724 * Print select parts of a IEEE 1284 device ID. 725 */ 726 void 727 ieee1284_print_id(char *str) 728 { 729 char *p, *q; 730 731 for (p = str-1; p; p = strchr(p, ';')) { 732 p++; /* skip ';' */ 733 if (strncmp(p, "MFG:", 4) == 0 || 734 strncmp(p, "MANUFACTURER:", 14) == 0 || 735 strncmp(p, "MDL:", 4) == 0 || 736 strncmp(p, "MODEL:", 6) == 0) { 737 q = strchr(p, ';'); 738 if (q) 739 printf("%.*s", (int)(q - p + 1), p); 740 } 741 } 742 } 743 #endif 744