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