Annotation of sys/dev/usb/usscanner.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: usscanner.c,v 1.22 2007/06/14 10:11:16 mbalmer Exp $ */
2: /* $NetBSD: usscanner.c,v 1.6 2001/01/23 14:04:14 augustss Exp $ */
3:
4: /*
5: * Copyright (c) 2001 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) and LLoyd Parkes.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * This driver is partly based on information taken from the Linux driver
42: * by John Fremlin, Oliver Neukum, and Jeremy Hall.
43: */
44: /*
45: * Protocol:
46: * Send raw SCSI command on the bulk-out pipe.
47: * If output command then
48: * send further data on the bulk-out pipe
49: * else if input command then
50: * read data on the bulk-in pipe
51: * else
52: * don't do anything.
53: * Read status byte on the interrupt pipe (which doesn't seem to be
54: * an interrupt pipe at all). This operation sometimes times out.
55: */
56:
57: #include <sys/param.h>
58: #include <sys/systm.h>
59: #include <sys/kernel.h>
60: #include <sys/malloc.h>
61: #include <sys/device.h>
62: #include <sys/conf.h>
63: #include <sys/buf.h>
64:
65: #include <dev/usb/usb.h>
66: #include <dev/usb/usbdi.h>
67: #include <dev/usb/usbdi_util.h>
68:
69: #include <dev/usb/usbdevs.h>
70:
71: #include <scsi/scsi_all.h>
72: #include <scsi/scsiconf.h>
73: #include <machine/bus.h>
74:
75: #ifdef USSCANNER_DEBUG
76: #define DPRINTF(x) do { if (usscannerdebug) printf x; } while (0)
77: #define DPRINTFN(n,x) do { if (usscannerdebug>(n)) printf x; } while (0)
78: int usscannerdebug = 0;
79: #else
80: #define DPRINTF(x)
81: #define DPRINTFN(n,x)
82: #endif
83:
84: #define XS_CTL_DATA_IN SCSI_DATA_IN
85: #define XS_CTL_DATA_OUT SCSI_DATA_OUT
86: #define scsipi_adapter scsi_adapter
87: #define scsipi_cmd scsi_cmd
88: #define scsipi_device scsi_device
89: #define scsipi_done scsi_done
90: #define scsipi_link scsi_link
91: #define scsipi_minphys scsi_minphys
92: #define scsipi_sense scsi_sense
93: #define scsipi_xfer scsi_xfer
94: #define show_scsipi_xs show_scsi_xs
95: #define show_scsipi_cmd show_scsi_cmd
96: #define xs_control flags
97: #define xs_status status
98: #define XS_STS_DONE ITSDONE
99: #define XS_CTL_POLL SCSI_POLL
100:
101: #define USSCANNER_CONFIG_NO 1
102: #define USSCANNER_IFACE_IDX 0
103:
104: #define USSCANNER_SCSIID_HOST 0x00
105: #define USSCANNER_SCSIID_DEVICE 0x01
106:
107: #define USSCANNER_MAX_TRANSFER_SIZE MAXBSIZE
108:
109: #define USSCANNER_TIMEOUT 2000
110:
111: struct scsipi_device usscanner_dev =
112: {
113: NULL, /* Use default error handler */
114: NULL, /* have a queue, served by this */
115: NULL, /* have no async handler */
116: NULL, /* Use default 'done' routine */
117: };
118:
119: struct usscanner_softc {
120: struct device sc_dev;
121: usbd_device_handle sc_udev;
122: usbd_interface_handle sc_iface;
123:
124: int sc_in_addr;
125: usbd_pipe_handle sc_in_pipe;
126:
127: int sc_intr_addr;
128: usbd_pipe_handle sc_intr_pipe;
129: usbd_xfer_handle sc_intr_xfer;
130: u_char sc_status;
131:
132: int sc_out_addr;
133: usbd_pipe_handle sc_out_pipe;
134:
135: usbd_xfer_handle sc_cmd_xfer;
136: void *sc_cmd_buffer;
137: usbd_xfer_handle sc_data_xfer;
138: void *sc_data_buffer;
139:
140: int sc_state;
141: #define UAS_IDLE 0
142: #define UAS_CMD 1
143: #define UAS_DATA 2
144: #define UAS_SENSECMD 3
145: #define UAS_SENSEDATA 4
146: #define UAS_STATUS 5
147:
148: struct scsipi_xfer *sc_xs;
149:
150: struct device *sc_child; /* child device, for detach */
151:
152: struct scsipi_link sc_link;
153: struct scsi_adapter sc_atapi_adapter;
154: #define sc_adapter sc_atapi_adapter
155:
156: int sc_refcnt;
157: char sc_dying;
158: };
159:
160:
161: void usscanner_cleanup(struct usscanner_softc *sc);
162: int usscanner_scsipi_cmd(struct scsipi_xfer *xs);
163: void usscanner_scsipi_minphys(struct buf *bp);
164: void usscanner_done(struct usscanner_softc *sc);
165: void usscanner_sense(struct usscanner_softc *sc);
166: typedef void callback(usbd_xfer_handle, usbd_private_handle, usbd_status);
167: callback usscanner_intr_cb;
168: callback usscanner_cmd_cb;
169: callback usscanner_data_cb;
170: callback usscanner_sensecmd_cb;
171: callback usscanner_sensedata_cb;
172:
173: int usscanner_match(struct device *, void *, void *);
174: void usscanner_attach(struct device *, struct device *, void *);
175: int usscanner_detach(struct device *, int);
176: int usscanner_activate(struct device *, enum devact);
177:
178: struct cfdriver usscanner_cd = {
179: NULL, "usscanner", DV_DULL
180: };
181:
182: const struct cfattach usscanner_ca = {
183: sizeof(struct usscanner_softc),
184: usscanner_match,
185: usscanner_attach,
186: usscanner_detach,
187: usscanner_activate,
188: };
189:
190: int
191: usscanner_match(struct device *parent, void *match, void *aux)
192: {
193: struct usb_attach_arg *uaa = aux;
194:
195: DPRINTFN(50,("usscanner_match\n"));
196:
197: if (uaa->iface != NULL)
198: return (UMATCH_NONE);
199:
200: if (uaa->vendor == USB_VENDOR_HP &&
201: uaa->product == USB_PRODUCT_HP_5300C)
202: return (UMATCH_VENDOR_PRODUCT);
203: else
204: return (UMATCH_NONE);
205: }
206:
207: void
208: usscanner_attach(struct device *parent, struct device *self, void *aux)
209: {
210: struct usscanner_softc *sc = (struct usscanner_softc *)self;
211: struct usb_attach_arg *uaa = aux;
212: struct scsibus_attach_args saa;
213: usbd_device_handle dev = uaa->device;
214: usbd_interface_handle iface;
215: char *devinfop;
216: usbd_status err;
217: usb_endpoint_descriptor_t *ed;
218: u_int8_t epcount;
219: int i;
220:
221: DPRINTFN(10,("usscanner_attach: sc=%p\n", sc));
222:
223: devinfop = usbd_devinfo_alloc(dev, 0);
224: printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
225: usbd_devinfo_free(devinfop);
226:
227: err = usbd_set_config_no(dev, USSCANNER_CONFIG_NO, 1);
228: if (err) {
229: printf("%s: setting config no failed\n",
230: sc->sc_dev.dv_xname);
231: return;
232: }
233:
234: err = usbd_device2interface_handle(dev, USSCANNER_IFACE_IDX, &iface);
235: if (err) {
236: printf("%s: getting interface handle failed\n",
237: sc->sc_dev.dv_xname);
238: return;
239: }
240:
241: sc->sc_udev = dev;
242: sc->sc_iface = iface;
243:
244: epcount = 0;
245: (void)usbd_endpoint_count(iface, &epcount);
246:
247: sc->sc_in_addr = -1;
248: sc->sc_intr_addr = -1;
249: sc->sc_out_addr = -1;
250: for (i = 0; i < epcount; i++) {
251: ed = usbd_interface2endpoint_descriptor(iface, i);
252: if (ed == NULL) {
253: printf("%s: couldn't get ep %d\n",
254: sc->sc_dev.dv_xname, i);
255: return;
256: }
257: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
258: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
259: sc->sc_in_addr = ed->bEndpointAddress;
260: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
261: UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
262: sc->sc_intr_addr = ed->bEndpointAddress;
263: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
264: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
265: sc->sc_out_addr = ed->bEndpointAddress;
266: }
267: }
268: if (sc->sc_in_addr == -1 || sc->sc_intr_addr == -1 ||
269: sc->sc_out_addr == -1) {
270: printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
271: return;
272: }
273:
274: err = usbd_open_pipe(sc->sc_iface, sc->sc_in_addr,
275: USBD_EXCLUSIVE_USE, &sc->sc_in_pipe);
276: if (err) {
277: printf("%s: open in pipe failed, err=%d\n",
278: sc->sc_dev.dv_xname, err);
279: return;
280: }
281:
282: /* The interrupt endpoint must be opened as a normal pipe. */
283: err = usbd_open_pipe(sc->sc_iface, sc->sc_intr_addr,
284: USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
285:
286: if (err) {
287: printf("%s: open intr pipe failed, err=%d\n",
288: sc->sc_dev.dv_xname, err);
289: usscanner_cleanup(sc);
290: return;
291: }
292: err = usbd_open_pipe(sc->sc_iface, sc->sc_out_addr,
293: USBD_EXCLUSIVE_USE, &sc->sc_out_pipe);
294: if (err) {
295: printf("%s: open out pipe failed, err=%d\n",
296: sc->sc_dev.dv_xname, err);
297: usscanner_cleanup(sc);
298: return;
299: }
300:
301: sc->sc_cmd_xfer = usbd_alloc_xfer(uaa->device);
302: if (sc->sc_cmd_xfer == NULL) {
303: printf("%s: alloc cmd xfer failed, err=%d\n",
304: sc->sc_dev.dv_xname, err);
305: usscanner_cleanup(sc);
306: return;
307: }
308:
309: /* XXX too big */
310: sc->sc_cmd_buffer = usbd_alloc_buffer(sc->sc_cmd_xfer,
311: USSCANNER_MAX_TRANSFER_SIZE);
312: if (sc->sc_cmd_buffer == NULL) {
313: printf("%s: alloc cmd buffer failed, err=%d\n",
314: sc->sc_dev.dv_xname, err);
315: usscanner_cleanup(sc);
316: return;
317: }
318:
319: sc->sc_intr_xfer = usbd_alloc_xfer (uaa->device);
320: if (sc->sc_intr_xfer == NULL) {
321: printf("%s: alloc intr xfer failed, err=%d\n",
322: sc->sc_dev.dv_xname, err);
323: usscanner_cleanup(sc);
324: return;
325: }
326:
327: sc->sc_data_xfer = usbd_alloc_xfer(uaa->device);
328: if (sc->sc_data_xfer == NULL) {
329: printf("%s: alloc data xfer failed, err=%d\n",
330: sc->sc_dev.dv_xname, err);
331: usscanner_cleanup(sc);
332: return;
333: }
334: sc->sc_data_buffer = usbd_alloc_buffer(sc->sc_data_xfer,
335: USSCANNER_MAX_TRANSFER_SIZE);
336: if (sc->sc_data_buffer == NULL) {
337: printf("%s: alloc data buffer failed, err=%d\n",
338: sc->sc_dev.dv_xname, err);
339: usscanner_cleanup(sc);
340: return;
341: }
342:
343: /*
344: * Fill in the adapter.
345: */
346: sc->sc_adapter.scsipi_cmd = usscanner_scsipi_cmd;
347: sc->sc_adapter.scsipi_minphys = usscanner_scsipi_minphys;
348:
349: /*
350: * fill in the prototype scsipi_link.
351: */
352: sc->sc_link.flags &= ~SDEV_ATAPI;
353: sc->sc_link.adapter_buswidth = 2;
354: sc->sc_link.adapter_target = USSCANNER_SCSIID_HOST;
355:
356: sc->sc_link.adapter_softc = sc;
357: sc->sc_link.adapter = &sc->sc_adapter;
358: sc->sc_link.device = &usscanner_dev;
359: sc->sc_link.openings = 1;
360:
361: bzero(&saa, sizeof(saa));
362: saa.saa_sc_link = &sc->sc_link;
363:
364: sc->sc_child = config_found(&sc->sc_dev, &saa, scsiprint);
365:
366: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
367: &sc->sc_dev);
368:
369: DPRINTFN(10, ("usscanner_attach: %p\n", sc->sc_udev));
370: }
371:
372: int
373: usscanner_detach(struct device *self, int flags)
374: {
375: struct usscanner_softc *sc = (struct usscanner_softc *)self;
376: int rv, s;
377:
378: DPRINTF(("usscanner_detach: sc=%p flags=%d\n", sc, flags));
379:
380: sc->sc_dying = 1;
381: /* Abort all pipes. Causes processes waiting for transfer to wake. */
382: if (sc->sc_in_pipe != NULL)
383: usbd_abort_pipe(sc->sc_in_pipe);
384: if (sc->sc_intr_pipe != NULL)
385: usbd_abort_pipe(sc->sc_intr_pipe);
386: if (sc->sc_out_pipe != NULL)
387: usbd_abort_pipe(sc->sc_out_pipe);
388:
389: s = splusb();
390: if (--sc->sc_refcnt >= 0) {
391: /* Wait for processes to go away. */
392: usb_detach_wait(&sc->sc_dev);
393: }
394: splx(s);
395:
396: if (sc->sc_child != NULL)
397: rv = config_detach(sc->sc_child, flags);
398: else
399: rv = 0;
400:
401: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
402: &sc->sc_dev);
403:
404: return (rv);
405: }
406:
407: void
408: usscanner_cleanup(struct usscanner_softc *sc)
409: {
410: if (sc->sc_in_pipe != NULL) {
411: usbd_close_pipe(sc->sc_in_pipe);
412: sc->sc_in_pipe = NULL;
413: }
414: if (sc->sc_intr_pipe != NULL) {
415: usbd_close_pipe(sc->sc_intr_pipe);
416: sc->sc_intr_pipe = NULL;
417: }
418: if (sc->sc_out_pipe != NULL) {
419: usbd_close_pipe(sc->sc_out_pipe);
420: sc->sc_out_pipe = NULL;
421: }
422: if (sc->sc_cmd_xfer != NULL) {
423: usbd_free_xfer(sc->sc_cmd_xfer);
424: sc->sc_cmd_xfer = NULL;
425: }
426: if (sc->sc_data_xfer != NULL) {
427: usbd_free_xfer(sc->sc_data_xfer);
428: sc->sc_data_xfer = NULL;
429: }
430: }
431:
432: int
433: usscanner_activate(struct device *self, enum devact act)
434: {
435: struct usscanner_softc *sc = (struct usscanner_softc *)self;
436:
437: switch (act) {
438: case DVACT_ACTIVATE:
439: break;
440:
441: case DVACT_DEACTIVATE:
442: sc->sc_dying = 1;
443: break;
444: }
445: return (0);
446: }
447:
448: void
449: usscanner_scsipi_minphys(struct buf *bp)
450: {
451: if (bp->b_bcount > USSCANNER_MAX_TRANSFER_SIZE)
452: bp->b_bcount = USSCANNER_MAX_TRANSFER_SIZE;
453: minphys(bp);
454: }
455:
456: void
457: usscanner_sense(struct usscanner_softc *sc)
458: {
459: struct scsipi_xfer *xs = sc->sc_xs;
460: struct scsipi_link *sc_link = xs->sc_link;
461: struct scsipi_sense sense_cmd;
462: usbd_status err;
463:
464: /* fetch sense data */
465: memset(&sense_cmd, 0, sizeof(sense_cmd));
466: sense_cmd.opcode = REQUEST_SENSE;
467: sense_cmd.byte2 = sc_link->lun << SCSI_CMD_LUN_SHIFT;
468: sense_cmd.length = sizeof xs->sense;
469:
470: sc->sc_state = UAS_SENSECMD;
471: memcpy(sc->sc_cmd_buffer, &sense_cmd, sizeof sense_cmd);
472: usbd_setup_xfer(sc->sc_cmd_xfer, sc->sc_out_pipe, sc, sc->sc_cmd_buffer,
473: sizeof sense_cmd, USBD_NO_COPY, USSCANNER_TIMEOUT,
474: usscanner_sensecmd_cb);
475: err = usbd_transfer(sc->sc_cmd_xfer);
476: if (err == USBD_IN_PROGRESS)
477: return;
478:
479: xs->error = XS_DRIVER_STUFFUP;
480: usscanner_done(sc);
481: }
482:
483: void
484: usscanner_intr_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
485: usbd_status status)
486: {
487: struct usscanner_softc *sc = priv;
488: int s;
489:
490: DPRINTFN(10, ("usscanner_data_cb status=%d\n", status));
491:
492: #ifdef USSCANNER_DEBUG
493: if (sc->sc_state != UAS_STATUS) {
494: printf("%s: !UAS_STATUS\n", sc->sc_dev.dv_xname);
495: }
496: if (sc->sc_status != 0) {
497: printf("%s: status byte=0x%02x\n", sc->sc_dev.dv_xname, sc->sc_status);
498: }
499: #endif
500: /* XXX what should we do on non-0 status */
501:
502: sc->sc_state = UAS_IDLE;
503:
504: sc->sc_xs->xs_status |= XS_STS_DONE;
505: s = splbio();
506: scsipi_done(sc->sc_xs);
507: splx(s);
508: }
509:
510: void
511: usscanner_data_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
512: usbd_status status)
513: {
514: struct usscanner_softc *sc = priv;
515: struct scsipi_xfer *xs = sc->sc_xs;
516: u_int32_t len;
517:
518: DPRINTFN(10, ("usscanner_data_cb status=%d\n", status));
519:
520: #ifdef USSCANNER_DEBUG
521: if (sc->sc_state != UAS_DATA) {
522: printf("%s: !UAS_DATA\n", sc->sc_dev.dv_xname);
523: }
524: #endif
525:
526: usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
527:
528: xs->resid = xs->datalen - len;
529:
530: switch (status) {
531: case USBD_NORMAL_COMPLETION:
532: if (xs->xs_control & XS_CTL_DATA_IN)
533: memcpy(xs->data, sc->sc_data_buffer, len);
534: xs->error = XS_NOERROR;
535: break;
536: case USBD_TIMEOUT:
537: xs->error = XS_TIMEOUT;
538: break;
539: case USBD_CANCELLED:
540: if (xs->error == XS_SENSE) {
541: usscanner_sense(sc);
542: return;
543: }
544: break;
545: default:
546: xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
547: break;
548: }
549: usscanner_done(sc);
550: }
551:
552: void
553: usscanner_sensedata_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
554: usbd_status status)
555: {
556: struct usscanner_softc *sc = priv;
557: struct scsipi_xfer *xs = sc->sc_xs;
558: u_int32_t len;
559:
560: DPRINTFN(10, ("usscanner_sensedata_cb status=%d\n", status));
561:
562: #ifdef USSCANNER_DEBUG
563: if (sc->sc_state != UAS_SENSEDATA) {
564: printf("%s: !UAS_SENSEDATA\n", sc->sc_dev.dv_xname);
565: }
566: #endif
567:
568: usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
569:
570: switch (status) {
571: case USBD_NORMAL_COMPLETION:
572: memcpy(&xs->sense, sc->sc_data_buffer, len);
573: if (len < sizeof xs->sense)
574: xs->error = XS_SHORTSENSE;
575: break;
576: case USBD_TIMEOUT:
577: xs->error = XS_TIMEOUT;
578: break;
579: case USBD_CANCELLED:
580: xs->error = XS_RESET;
581: break;
582: default:
583: xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
584: break;
585: }
586: usscanner_done(sc);
587: }
588:
589: void
590: usscanner_done(struct usscanner_softc *sc)
591: {
592: struct scsipi_xfer *xs = sc->sc_xs;
593: usbd_status err;
594:
595: DPRINTFN(10,("usscanner_done: error=%d\n", sc->sc_xs->error));
596:
597: sc->sc_state = UAS_STATUS;
598: usbd_setup_xfer(sc->sc_intr_xfer, sc->sc_intr_pipe, sc, &sc->sc_status,
599: 1, USBD_SHORT_XFER_OK | USBD_NO_COPY,
600: USSCANNER_TIMEOUT, usscanner_intr_cb);
601: err = usbd_transfer(sc->sc_intr_xfer);
602: if (err == USBD_IN_PROGRESS)
603: return;
604: xs->error = XS_DRIVER_STUFFUP;
605: }
606:
607: void
608: usscanner_sensecmd_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
609: usbd_status status)
610: {
611: struct usscanner_softc *sc = priv;
612: struct scsipi_xfer *xs = sc->sc_xs;
613: usbd_status err;
614:
615: DPRINTFN(10, ("usscanner_sensecmd_cb status=%d\n", status));
616:
617: #ifdef USSCANNER_DEBUG
618: #ifdef notyet
619: if (usscannerdebug > 15)
620: xs->sc_link->flags |= DEBUGLEVEL;
621: #endif
622:
623: if (sc->sc_state != UAS_SENSECMD) {
624: printf("%s: !UAS_SENSECMD\n", sc->sc_dev.dv_xname);
625: xs->error = XS_DRIVER_STUFFUP;
626: goto done;
627: }
628: #endif
629:
630: switch (status) {
631: case USBD_NORMAL_COMPLETION:
632: break;
633: case USBD_TIMEOUT:
634: xs->error = XS_TIMEOUT;
635: goto done;
636: default:
637: xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
638: goto done;
639: }
640:
641: sc->sc_state = UAS_SENSEDATA;
642: usbd_setup_xfer(sc->sc_data_xfer, sc->sc_in_pipe, sc,
643: sc->sc_data_buffer,
644: sizeof xs->sense, USBD_SHORT_XFER_OK | USBD_NO_COPY,
645: USSCANNER_TIMEOUT, usscanner_sensedata_cb);
646: err = usbd_transfer(sc->sc_data_xfer);
647: if (err == USBD_IN_PROGRESS)
648: return;
649: xs->error = XS_DRIVER_STUFFUP;
650: done:
651: usscanner_done(sc);
652: }
653:
654: void
655: usscanner_cmd_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
656: usbd_status status)
657: {
658: struct usscanner_softc *sc = priv;
659: struct scsipi_xfer *xs = sc->sc_xs;
660: usbd_pipe_handle pipe;
661: usbd_status err;
662:
663: DPRINTFN(10, ("usscanner_cmd_cb status=%d\n", status));
664:
665: #ifdef USSCANNER_DEBUG
666: #ifdef notyet
667: if (usscannerdebug > 15)
668: xs->sc_link->flags |= DEBUGLEVEL;
669: #endif
670:
671: if (sc->sc_state != UAS_CMD) {
672: printf("%s: !UAS_CMD\n", sc->sc_dev.dv_xname);
673: xs->error = XS_DRIVER_STUFFUP;
674: goto done;
675: }
676: #endif
677:
678: switch (status) {
679: case USBD_NORMAL_COMPLETION:
680: break;
681: case USBD_TIMEOUT:
682: xs->error = XS_TIMEOUT;
683: goto done;
684: case USBD_CANCELLED:
685: goto done;
686: default:
687: xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
688: goto done;
689: }
690:
691: if (xs->datalen == 0) {
692: DPRINTFN(4, ("usscanner_cmd_cb: no data phase\n"));
693: xs->error = XS_NOERROR;
694: goto done;
695: }
696:
697: if (xs->xs_control & XS_CTL_DATA_IN) {
698: DPRINTFN(4, ("usscanner_cmd_cb: data in len=%d\n",
699: xs->datalen));
700: pipe = sc->sc_in_pipe;
701: } else {
702: DPRINTFN(4, ("usscanner_cmd_cb: data out len=%d\n",
703: xs->datalen));
704: memcpy(sc->sc_data_buffer, xs->data, xs->datalen);
705: pipe = sc->sc_out_pipe;
706: }
707: sc->sc_state = UAS_DATA;
708: usbd_setup_xfer(sc->sc_data_xfer, pipe, sc, sc->sc_data_buffer,
709: xs->datalen, USBD_SHORT_XFER_OK | USBD_NO_COPY,
710: xs->timeout, usscanner_data_cb);
711: err = usbd_transfer(sc->sc_data_xfer);
712: if (err == USBD_IN_PROGRESS)
713: return;
714: xs->error = XS_DRIVER_STUFFUP;
715:
716: done:
717: usscanner_done(sc);
718: }
719:
720: int
721: usscanner_scsipi_cmd(struct scsipi_xfer *xs)
722: {
723: struct scsipi_link *sc_link = xs->sc_link;
724: struct usscanner_softc *sc = sc_link->adapter_softc;
725: usbd_status err;
726:
727: #ifdef notyet
728: DPRINTFN(8, ("%s: usscanner_scsi_cmd: %d:%d "
729: "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n",
730: sc->sc_dev.dv_xname,
731: sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun,
732: xs, xs->cmd->opcode, xs->datalen,
733: sc_link->quirks, xs->xs_control & XS_CTL_POLL));
734: #endif
735:
736: if (sc->sc_dying) {
737: xs->error = XS_DRIVER_STUFFUP;
738: goto done;
739: }
740:
741: #ifdef USSCANNER_DEBUG
742: #ifdef notyet
743: if (sc_link->scsipi_scsi.target != USSCANNER_SCSIID_DEVICE) {
744: DPRINTF(("%s: wrong SCSI ID %d\n", sc->sc_dev.dv_xname,
745: sc_link->scsipi_scsi.target));
746: xs->error = XS_DRIVER_STUFFUP;
747: goto done;
748: }
749: #endif
750: if (sc->sc_state != UAS_IDLE) {
751: printf("%s: !UAS_IDLE\n", sc->sc_dev.dv_xname);
752: xs->error = XS_DRIVER_STUFFUP;
753: goto done;
754: }
755: #endif
756:
757: if (xs->datalen > USSCANNER_MAX_TRANSFER_SIZE) {
758: printf("umass_cmd: large datalen, %d\n", xs->datalen);
759: xs->error = XS_DRIVER_STUFFUP;
760: goto done;
761: }
762:
763: DPRINTFN(4, ("usscanner_scsi_cmd: async cmdlen=%d datalen=%d\n",
764: xs->cmdlen, xs->datalen));
765: sc->sc_state = UAS_CMD;
766: sc->sc_xs = xs;
767: memcpy(sc->sc_cmd_buffer, xs->cmd, xs->cmdlen);
768: usbd_setup_xfer(sc->sc_cmd_xfer, sc->sc_out_pipe, sc, sc->sc_cmd_buffer,
769: xs->cmdlen, USBD_NO_COPY, USSCANNER_TIMEOUT, usscanner_cmd_cb);
770: err = usbd_transfer(sc->sc_cmd_xfer);
771: if (err != USBD_IN_PROGRESS) {
772: xs->error = XS_DRIVER_STUFFUP;
773: goto done;
774: }
775:
776: return (SUCCESSFULLY_QUEUED);
777:
778:
779: done:
780: sc->sc_state = UAS_IDLE;
781: xs->xs_status |= XS_STS_DONE;
782: scsipi_done(xs);
783: if (xs->xs_control & XS_CTL_POLL)
784: return (COMPLETE);
785: else
786: return (SUCCESSFULLY_QUEUED);
787: }
CVSweb