1 /* $NetBSD: usscanner.c,v 1.28 2009/09/23 19:07:19 plunky Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) and LLoyd Parkes.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * This driver is partly based on information taken from the Linux driver
34 * by John Fremlin, Oliver Neukum, and Jeremy Hall.
38 * Send raw SCSI command on the bulk-out pipe.
39 * If output command then
40 * send further data on the bulk-out pipe
41 * else if input command then
42 * read data on the bulk-in pipe
45 * Read status byte on the interrupt pipe (which doesn't seem to be
46 * an interrupt pipe at all). This operation sometimes times out.
49 #include <sys/cdefs.h>
50 __KERNEL_RCSID(0, "$NetBSD: usscanner.c,v 1.28 2009/09/23 19:07:19 plunky Exp $");
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/malloc.h>
57 #include <sys/device.h>
61 #include <dev/usb/usb.h>
62 #include <dev/usb/usbdi.h>
63 #include <dev/usb/usbdi_util.h>
65 #include <dev/usb/usbdevs.h>
67 #include <sys/scsiio.h>
68 #include <dev/scsipi/scsi_spc.h>
69 #include <dev/scsipi/scsi_all.h>
70 #include <dev/scsipi/scsipi_all.h>
71 #include <dev/scsipi/scsiconf.h>
72 #include <dev/scsipi/atapiconf.h>
74 #ifdef USSCANNER_DEBUG
75 #define DPRINTF(x) if (usscannerdebug) logprintf x
76 #define DPRINTFN(n,x) if (usscannerdebug>(n)) logprintf x
77 int usscannerdebug
= 0;
84 #define USSCANNER_CONFIG_NO 1
85 #define USSCANNER_IFACE_IDX 0
87 #define USSCANNER_SCSIID_HOST 0x00
88 #define USSCANNER_SCSIID_DEVICE 0x01
90 #define USSCANNER_MAX_TRANSFER_SIZE MAXPHYS
92 #define USSCANNER_TIMEOUT 2000
94 struct usscanner_softc
{
96 usbd_device_handle sc_udev
;
97 usbd_interface_handle sc_iface
;
100 usbd_pipe_handle sc_in_pipe
;
103 usbd_pipe_handle sc_intr_pipe
;
104 usbd_xfer_handle sc_intr_xfer
;
108 usbd_pipe_handle sc_out_pipe
;
110 usbd_xfer_handle sc_cmd_xfer
;
112 usbd_xfer_handle sc_data_xfer
;
113 void *sc_data_buffer
;
119 #define UAS_SENSECMD 3
120 #define UAS_SENSEDATA 4
123 struct scsipi_xfer
*sc_xs
;
125 device_ptr_t sc_child
; /* child device, for detach */
127 struct scsipi_adapter sc_adapter
;
128 struct scsipi_channel sc_channel
;
135 Static
void usscanner_cleanup(struct usscanner_softc
*sc
);
136 Static
void usscanner_scsipi_request(struct scsipi_channel
*chan
,
137 scsipi_adapter_req_t req
, void *arg
);
138 Static
void usscanner_scsipi_minphys(struct buf
*bp
);
139 Static
void usscanner_done(struct usscanner_softc
*sc
);
140 Static
void usscanner_sense(struct usscanner_softc
*sc
);
141 typedef void callback(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
142 Static callback usscanner_intr_cb
;
143 Static callback usscanner_cmd_cb
;
144 Static callback usscanner_data_cb
;
145 Static callback usscanner_sensecmd_cb
;
146 Static callback usscanner_sensedata_cb
;
148 int usscanner_match(device_t
, cfdata_t
, void *);
149 void usscanner_attach(device_t
, device_t
, void *);
150 void usscanner_childdet(device_t
, device_t
);
151 int usscanner_detach(device_t
, int);
152 int usscanner_activate(device_t
, enum devact
);
153 extern struct cfdriver usscanner_cd
;
154 CFATTACH_DECL2_NEW(usscanner
, sizeof(struct usscanner_softc
),
155 usscanner_match
, usscanner_attach
, usscanner_detach
, usscanner_activate
,
156 NULL
, usscanner_childdet
);
160 USB_MATCH_START(usscanner
, uaa
);
162 DPRINTFN(50,("usscanner_match\n"));
164 if (uaa
->vendor
== USB_VENDOR_HP
&&
165 uaa
->product
== USB_PRODUCT_HP_5300C
)
166 return (UMATCH_VENDOR_PRODUCT
);
168 return (UMATCH_NONE
);
171 USB_ATTACH(usscanner
)
173 USB_ATTACH_START(usscanner
, sc
, uaa
);
174 usbd_device_handle dev
= uaa
->device
;
175 usbd_interface_handle iface
;
178 usb_endpoint_descriptor_t
*ed
;
182 DPRINTFN(10,("usscanner_attach: sc=%p\n", sc
));
189 devinfop
= usbd_devinfo_alloc(dev
, 0);
190 aprint_normal_dev(self
, "%s\n", devinfop
);
191 usbd_devinfo_free(devinfop
);
193 err
= usbd_set_config_no(dev
, USSCANNER_CONFIG_NO
, 1);
195 aprint_error_dev(self
, "setting config no failed\n");
196 USB_ATTACH_ERROR_RETURN
;
199 err
= usbd_device2interface_handle(dev
, USSCANNER_IFACE_IDX
, &iface
);
201 aprint_error_dev(self
, "getting interface handle failed\n");
202 USB_ATTACH_ERROR_RETURN
;
206 sc
->sc_iface
= iface
;
209 (void)usbd_endpoint_count(iface
, &epcount
);
212 sc
->sc_intr_addr
= -1;
213 sc
->sc_out_addr
= -1;
214 for (i
= 0; i
< epcount
; i
++) {
215 ed
= usbd_interface2endpoint_descriptor(iface
, i
);
217 aprint_error_dev(self
, "couldn't get ep %d\n", i
);
218 USB_ATTACH_ERROR_RETURN
;
220 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
221 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
222 sc
->sc_in_addr
= ed
->bEndpointAddress
;
223 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
224 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_INTERRUPT
) {
225 sc
->sc_intr_addr
= ed
->bEndpointAddress
;
226 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
227 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
228 sc
->sc_out_addr
= ed
->bEndpointAddress
;
231 if (sc
->sc_in_addr
== -1 || sc
->sc_intr_addr
== -1 ||
232 sc
->sc_out_addr
== -1) {
233 aprint_error_dev(self
, "missing endpoint\n");
234 USB_ATTACH_ERROR_RETURN
;
237 err
= usbd_open_pipe(sc
->sc_iface
, sc
->sc_in_addr
,
238 USBD_EXCLUSIVE_USE
, &sc
->sc_in_pipe
);
240 aprint_error_dev(self
, "open in pipe failed, err=%d\n", err
);
241 USB_ATTACH_ERROR_RETURN
;
244 /* The interrupt endpoint must be opened as a normal pipe. */
245 err
= usbd_open_pipe(sc
->sc_iface
, sc
->sc_intr_addr
,
246 USBD_EXCLUSIVE_USE
, &sc
->sc_intr_pipe
);
249 aprint_error_dev(self
, "open intr pipe failed, err=%d\n", err
);
250 usscanner_cleanup(sc
);
251 USB_ATTACH_ERROR_RETURN
;
253 err
= usbd_open_pipe(sc
->sc_iface
, sc
->sc_out_addr
,
254 USBD_EXCLUSIVE_USE
, &sc
->sc_out_pipe
);
256 aprint_error_dev(self
, "open out pipe failed, err=%d\n", err
);
257 usscanner_cleanup(sc
);
258 USB_ATTACH_ERROR_RETURN
;
261 sc
->sc_cmd_xfer
= usbd_alloc_xfer(uaa
->device
);
262 if (sc
->sc_cmd_xfer
== NULL
) {
263 aprint_error_dev(self
, "alloc cmd xfer failed, err=%d\n", err
);
264 usscanner_cleanup(sc
);
265 USB_ATTACH_ERROR_RETURN
;
269 sc
->sc_cmd_buffer
= usbd_alloc_buffer(sc
->sc_cmd_xfer
,
270 USSCANNER_MAX_TRANSFER_SIZE
);
271 if (sc
->sc_cmd_buffer
== NULL
) {
272 aprint_error_dev(self
, "alloc cmd buffer failed, err=%d\n",
274 usscanner_cleanup(sc
);
275 USB_ATTACH_ERROR_RETURN
;
278 sc
->sc_intr_xfer
= usbd_alloc_xfer (uaa
->device
);
279 if (sc
->sc_intr_xfer
== NULL
) {
280 aprint_error_dev(self
, "alloc intr xfer failed, err=%d\n", err
);
281 usscanner_cleanup(sc
);
282 USB_ATTACH_ERROR_RETURN
;
285 sc
->sc_data_xfer
= usbd_alloc_xfer(uaa
->device
);
286 if (sc
->sc_data_xfer
== NULL
) {
287 aprint_error_dev(self
, "alloc data xfer failed, err=%d\n", err
);
288 usscanner_cleanup(sc
);
289 USB_ATTACH_ERROR_RETURN
;
291 sc
->sc_data_buffer
= usbd_alloc_buffer(sc
->sc_data_xfer
,
292 USSCANNER_MAX_TRANSFER_SIZE
);
293 if (sc
->sc_data_buffer
== NULL
) {
294 aprint_error_dev(self
, "alloc data buffer failed, err=%d\n",
296 usscanner_cleanup(sc
);
297 USB_ATTACH_ERROR_RETURN
;
301 * Fill in the adapter.
303 sc
->sc_adapter
.adapt_request
= usscanner_scsipi_request
;
304 sc
->sc_adapter
.adapt_dev
= sc
->sc_dev
;
305 sc
->sc_adapter
.adapt_nchannels
= 1;
306 sc
->sc_adapter
.adapt_openings
= 1;
307 sc
->sc_adapter
.adapt_max_periph
= 1;
308 sc
->sc_adapter
.adapt_minphys
= usscanner_scsipi_minphys
;
312 * fill in the scsipi_channel.
314 sc
->sc_channel
.chan_adapter
= &sc
->sc_adapter
;
315 sc
->sc_channel
.chan_bustype
= &scsi_bustype
;
316 sc
->sc_channel
.chan_channel
= 0;
317 sc
->sc_channel
.chan_ntargets
= USSCANNER_SCSIID_DEVICE
+ 1;
318 sc
->sc_channel
.chan_nluns
= 1;
319 sc
->sc_channel
.chan_id
= USSCANNER_SCSIID_HOST
;
321 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->sc_udev
,
324 sc
->sc_child
= config_found(sc
->sc_dev
, &sc
->sc_channel
, scsiprint
);
326 DPRINTFN(10, ("usscanner_attach: %p\n", sc
->sc_udev
));
328 USB_ATTACH_SUCCESS_RETURN
;
331 /* No SCSI bus, just ignore it */
332 usscanner_cleanup(sc
);
334 aprint_error_dev(self
,
335 "no scsibus configured, see usscanner(4) for details\n");
337 USB_ATTACH_ERROR_RETURN
;
343 usscanner_childdet(device_t self
, device_t child
)
345 struct usscanner_softc
*sc
= device_private(self
);
347 KASSERT(sc
->sc_child
== NULL
);
351 USB_DETACH(usscanner
)
353 USB_DETACH_START(usscanner
, sc
);
356 DPRINTF(("usscanner_detach: sc=%p flags=%d\n", sc
, flags
));
359 /* Abort all pipes. Causes processes waiting for transfer to wake. */
360 if (sc
->sc_in_pipe
!= NULL
)
361 usbd_abort_pipe(sc
->sc_in_pipe
);
362 if (sc
->sc_intr_pipe
!= NULL
)
363 usbd_abort_pipe(sc
->sc_intr_pipe
);
364 if (sc
->sc_out_pipe
!= NULL
)
365 usbd_abort_pipe(sc
->sc_out_pipe
);
368 if (--sc
->sc_refcnt
>= 0) {
369 /* Wait for processes to go away. */
370 usb_detach_wait(USBDEV(sc
->sc_dev
));
374 if (sc
->sc_child
!= NULL
)
375 rv
= config_detach(sc
->sc_child
, flags
);
379 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->sc_udev
,
386 usscanner_cleanup(struct usscanner_softc
*sc
)
388 if (sc
->sc_in_pipe
!= NULL
) {
389 usbd_close_pipe(sc
->sc_in_pipe
);
390 sc
->sc_in_pipe
= NULL
;
392 if (sc
->sc_intr_pipe
!= NULL
) {
393 usbd_close_pipe(sc
->sc_intr_pipe
);
394 sc
->sc_intr_pipe
= NULL
;
396 if (sc
->sc_out_pipe
!= NULL
) {
397 usbd_close_pipe(sc
->sc_out_pipe
);
398 sc
->sc_out_pipe
= NULL
;
400 if (sc
->sc_cmd_xfer
!= NULL
) {
401 usbd_free_xfer(sc
->sc_cmd_xfer
);
402 sc
->sc_cmd_xfer
= NULL
;
404 if (sc
->sc_data_xfer
!= NULL
) {
405 usbd_free_xfer(sc
->sc_data_xfer
);
406 sc
->sc_data_xfer
= NULL
;
411 usscanner_activate(device_t self
, enum devact act
)
413 struct usscanner_softc
*sc
= device_private(self
);
416 case DVACT_DEACTIVATE
:
425 usscanner_scsipi_minphys(struct buf
*bp
)
427 if (bp
->b_bcount
> USSCANNER_MAX_TRANSFER_SIZE
)
428 bp
->b_bcount
= USSCANNER_MAX_TRANSFER_SIZE
;
433 usscanner_sense(struct usscanner_softc
*sc
)
435 struct scsipi_xfer
*xs
= sc
->sc_xs
;
436 struct scsipi_periph
*periph
= xs
->xs_periph
;
437 struct scsi_request_sense sense_cmd
;
440 /* fetch sense data */
441 memset(&sense_cmd
, 0, sizeof(sense_cmd
));
442 sense_cmd
.opcode
= SCSI_REQUEST_SENSE
;
443 sense_cmd
.byte2
= periph
->periph_lun
<< SCSI_CMD_LUN_SHIFT
;
444 sense_cmd
.length
= sizeof xs
->sense
;
446 sc
->sc_state
= UAS_SENSECMD
;
447 memcpy(sc
->sc_cmd_buffer
, &sense_cmd
, sizeof sense_cmd
);
448 usbd_setup_xfer(sc
->sc_cmd_xfer
, sc
->sc_out_pipe
, sc
, sc
->sc_cmd_buffer
,
449 sizeof sense_cmd
, USBD_NO_COPY
, USSCANNER_TIMEOUT
,
450 usscanner_sensecmd_cb
);
451 err
= usbd_transfer(sc
->sc_cmd_xfer
);
452 if (err
== USBD_IN_PROGRESS
)
455 xs
->error
= XS_DRIVER_STUFFUP
;
460 usscanner_intr_cb(usbd_xfer_handle xfer
, usbd_private_handle priv
,
463 struct usscanner_softc
*sc
= priv
;
466 DPRINTFN(10, ("usscanner_data_cb status=%d\n", status
));
468 #ifdef USSCANNER_DEBUG
469 if (sc
->sc_state
!= UAS_STATUS
) {
470 printf("%s: !UAS_STATUS\n", USBDEVNAME(sc
->sc_dev
));
472 if (sc
->sc_status
!= 0) {
473 printf("%s: status byte=0x%02x\n", USBDEVNAME(sc
->sc_dev
), sc
->sc_status
);
476 /* XXX what should we do on non-0 status */
478 sc
->sc_state
= UAS_IDLE
;
481 scsipi_done(sc
->sc_xs
);
486 usscanner_data_cb(usbd_xfer_handle xfer
, usbd_private_handle priv
,
489 struct usscanner_softc
*sc
= priv
;
490 struct scsipi_xfer
*xs
= sc
->sc_xs
;
493 DPRINTFN(10, ("usscanner_data_cb status=%d\n", status
));
495 #ifdef USSCANNER_DEBUG
496 if (sc
->sc_state
!= UAS_DATA
) {
497 printf("%s: !UAS_DATA\n", USBDEVNAME(sc
->sc_dev
));
501 usbd_get_xfer_status(xfer
, NULL
, NULL
, &len
, NULL
);
503 xs
->resid
= xs
->datalen
- len
;
506 case USBD_NORMAL_COMPLETION
:
507 if (xs
->xs_control
& XS_CTL_DATA_IN
)
508 memcpy(xs
->data
, sc
->sc_data_buffer
, len
);
509 xs
->error
= XS_NOERROR
;
512 xs
->error
= XS_TIMEOUT
;
515 if (xs
->error
== XS_SENSE
) {
521 xs
->error
= XS_DRIVER_STUFFUP
; /* XXX ? */
528 usscanner_sensedata_cb(usbd_xfer_handle xfer
, usbd_private_handle priv
,
531 struct usscanner_softc
*sc
= priv
;
532 struct scsipi_xfer
*xs
= sc
->sc_xs
;
535 DPRINTFN(10, ("usscanner_sensedata_cb status=%d\n", status
));
537 #ifdef USSCANNER_DEBUG
538 if (sc
->sc_state
!= UAS_SENSEDATA
) {
539 printf("%s: !UAS_SENSEDATA\n", USBDEVNAME(sc
->sc_dev
));
543 usbd_get_xfer_status(xfer
, NULL
, NULL
, &len
, NULL
);
546 case USBD_NORMAL_COMPLETION
:
547 memcpy(&xs
->sense
, sc
->sc_data_buffer
, len
);
548 if (len
< sizeof xs
->sense
)
549 xs
->error
= XS_SHORTSENSE
;
552 xs
->error
= XS_TIMEOUT
;
555 xs
->error
= XS_RESET
;
558 xs
->error
= XS_DRIVER_STUFFUP
; /* XXX ? */
565 usscanner_done(struct usscanner_softc
*sc
)
567 struct scsipi_xfer
*xs
= sc
->sc_xs
;
570 DPRINTFN(10,("usscanner_done: error=%d\n", sc
->sc_xs
->error
));
572 sc
->sc_state
= UAS_STATUS
;
573 usbd_setup_xfer(sc
->sc_intr_xfer
, sc
->sc_intr_pipe
, sc
, &sc
->sc_status
,
574 1, USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
575 USSCANNER_TIMEOUT
, usscanner_intr_cb
);
576 err
= usbd_transfer(sc
->sc_intr_xfer
);
577 if (err
== USBD_IN_PROGRESS
)
579 xs
->error
= XS_DRIVER_STUFFUP
;
583 usscanner_sensecmd_cb(usbd_xfer_handle xfer
, usbd_private_handle priv
,
586 struct usscanner_softc
*sc
= priv
;
587 struct scsipi_xfer
*xs
= sc
->sc_xs
;
590 DPRINTFN(10, ("usscanner_sensecmd_cb status=%d\n", status
));
592 #ifdef USSCANNER_DEBUG
593 if (usscannerdebug
> 15)
594 xs
->xs_periph
->periph_flags
|= 1; /* XXX 1 */
596 if (sc
->sc_state
!= UAS_SENSECMD
) {
597 aprint_error_dev(sc
->sc_dev
, "!UAS_SENSECMD\n");
598 xs
->error
= XS_DRIVER_STUFFUP
;
604 case USBD_NORMAL_COMPLETION
:
607 xs
->error
= XS_TIMEOUT
;
610 xs
->error
= XS_DRIVER_STUFFUP
; /* XXX ? */
614 sc
->sc_state
= UAS_SENSEDATA
;
615 usbd_setup_xfer(sc
->sc_data_xfer
, sc
->sc_in_pipe
, sc
,
617 sizeof xs
->sense
, USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
618 USSCANNER_TIMEOUT
, usscanner_sensedata_cb
);
619 err
= usbd_transfer(sc
->sc_data_xfer
);
620 if (err
== USBD_IN_PROGRESS
)
622 xs
->error
= XS_DRIVER_STUFFUP
;
628 usscanner_cmd_cb(usbd_xfer_handle xfer
, usbd_private_handle priv
,
631 struct usscanner_softc
*sc
= priv
;
632 struct scsipi_xfer
*xs
= sc
->sc_xs
;
633 usbd_pipe_handle pipe
;
636 DPRINTFN(10, ("usscanner_cmd_cb status=%d\n", status
));
638 #ifdef USSCANNER_DEBUG
639 if (usscannerdebug
> 15)
640 xs
->xs_periph
->periph_flags
|= 1; /* XXX 1 */
642 if (sc
->sc_state
!= UAS_CMD
) {
643 aprint_error_dev(sc
->sc_dev
, "!UAS_CMD\n");
644 xs
->error
= XS_DRIVER_STUFFUP
;
650 case USBD_NORMAL_COMPLETION
:
653 xs
->error
= XS_TIMEOUT
;
658 xs
->error
= XS_DRIVER_STUFFUP
; /* XXX ? */
662 if (xs
->datalen
== 0) {
663 DPRINTFN(4, ("usscanner_cmd_cb: no data phase\n"));
664 xs
->error
= XS_NOERROR
;
668 if (xs
->xs_control
& XS_CTL_DATA_IN
) {
669 DPRINTFN(4, ("usscanner_cmd_cb: data in len=%d\n",
671 pipe
= sc
->sc_in_pipe
;
673 DPRINTFN(4, ("usscanner_cmd_cb: data out len=%d\n",
675 memcpy(sc
->sc_data_buffer
, xs
->data
, xs
->datalen
);
676 pipe
= sc
->sc_out_pipe
;
678 sc
->sc_state
= UAS_DATA
;
679 usbd_setup_xfer(sc
->sc_data_xfer
, pipe
, sc
, sc
->sc_data_buffer
,
680 xs
->datalen
, USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
681 xs
->timeout
, usscanner_data_cb
);
682 err
= usbd_transfer(sc
->sc_data_xfer
);
683 if (err
== USBD_IN_PROGRESS
)
685 xs
->error
= XS_DRIVER_STUFFUP
;
692 usscanner_scsipi_request(struct scsipi_channel
*chan
, scsipi_adapter_req_t req
, void *arg
)
694 struct scsipi_xfer
*xs
;
695 struct scsipi_periph
*periph
;
696 struct usscanner_softc
*sc
=
697 device_private(chan
->chan_adapter
->adapt_dev
);
701 case ADAPTER_REQ_RUN_XFER
:
703 periph
= xs
->xs_periph
;
705 DPRINTFN(8, ("%s: usscanner_scsipi_request: %d:%d "
706 "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n",
707 USBDEVNAME(sc
->sc_dev
),
708 periph
->periph_target
, periph
->periph_lun
,
709 xs
, xs
->cmd
->opcode
, xs
->datalen
,
710 periph
->periph_quirks
, xs
->xs_control
& XS_CTL_POLL
));
713 xs
->error
= XS_DRIVER_STUFFUP
;
717 #ifdef USSCANNER_DEBUG
718 if (periph
->periph_target
!= USSCANNER_SCSIID_DEVICE
) {
719 DPRINTF(("%s: wrong SCSI ID %d\n",
720 USBDEVNAME(sc
->sc_dev
), periph
->periph_target
));
721 xs
->error
= XS_DRIVER_STUFFUP
;
724 if (sc
->sc_state
!= UAS_IDLE
) {
725 printf("%s: !UAS_IDLE\n", USBDEVNAME(sc
->sc_dev
));
726 xs
->error
= XS_DRIVER_STUFFUP
;
731 if (xs
->datalen
> USSCANNER_MAX_TRANSFER_SIZE
) {
732 aprint_normal_dev(sc
->sc_dev
,
733 "usscanner_scsipi_request: large datalen, %d\n",
735 xs
->error
= XS_DRIVER_STUFFUP
;
739 DPRINTFN(4, ("%s: usscanner_scsipi_request: async cmdlen=%d"
740 " datalen=%d\n", USBDEVNAME(sc
->sc_dev
), xs
->cmdlen
,
742 sc
->sc_state
= UAS_CMD
;
744 memcpy(sc
->sc_cmd_buffer
, xs
->cmd
, xs
->cmdlen
);
745 usbd_setup_xfer(sc
->sc_cmd_xfer
, sc
->sc_out_pipe
, sc
,
746 sc
->sc_cmd_buffer
, xs
->cmdlen
, USBD_NO_COPY
,
747 USSCANNER_TIMEOUT
, usscanner_cmd_cb
);
748 err
= usbd_transfer(sc
->sc_cmd_xfer
);
749 if (err
!= USBD_IN_PROGRESS
) {
750 xs
->error
= XS_DRIVER_STUFFUP
;
758 sc
->sc_state
= UAS_IDLE
;
762 case ADAPTER_REQ_GROW_RESOURCES
:
763 /* XXX Not supported. */
765 case ADAPTER_REQ_SET_XFER_MODE
:
766 /* XXX Not supported. */