This source file includes following definitions.
- usscanner_match
- usscanner_attach
- usscanner_detach
- usscanner_cleanup
- usscanner_activate
- usscanner_scsipi_minphys
- usscanner_sense
- usscanner_intr_cb
- usscanner_data_cb
- usscanner_sensedata_cb
- usscanner_done
- usscanner_sensecmd_cb
- usscanner_cmd_cb
- usscanner_scsipi_cmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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,
114 NULL,
115 NULL,
116 NULL,
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;
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
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
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
345
346 sc->sc_adapter.scsipi_cmd = usscanner_scsipi_cmd;
347 sc->sc_adapter.scsipi_minphys = usscanner_scsipi_minphys;
348
349
350
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
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
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
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
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;
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;
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;
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;
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 }