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