# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.226 -> 1.227 # drivers/usb/hpusbscsi.h 1.2 -> 1.3 # drivers/usb/hpusbscsi.c 1.3 -> 1.4 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/03/22 oliver@oenone.homelinux.org 1.227 # USB hpusbscsi driver # # some scanners need special handling of request sense # -------------------------------------------- # diff -Nru a/drivers/usb/hpusbscsi.c b/drivers/usb/hpusbscsi.c --- a/drivers/usb/hpusbscsi.c Fri Mar 22 15:47:42 2002 +++ b/drivers/usb/hpusbscsi.c Fri Mar 22 15:47:42 2002 @@ -120,6 +120,9 @@ if (scsi_register_module (MODULE_SCSI_HA, &(new->ctempl))) goto err_out; + new->sense_command[0] = REQUEST_SENSE; + new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH; + /* adding to list for module unload */ list_add (&hpusbscsi_devices, &new->lh); @@ -163,7 +166,6 @@ int result; INIT_LIST_HEAD (&hpusbscsi_devices); - DEBUG ("Driver loaded\n"); if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) { printk (KERN_ERR "hpusbscsi: driver registration failed\n"); @@ -371,6 +373,7 @@ static void control_interrupt_callback (struct urb *u) { struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; + u8 scsi_state; DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); if(u->status < 0) { @@ -378,10 +381,23 @@ handle_usb_error(hpusbscsi); return; } - hpusbscsi->srb->result &= SCSI_ERR_MASK; - hpusbscsi->srb->result |= hpusbscsi->scsi_state_byte; - if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT) + scsi_state = hpusbscsi->scsi_state_byte; + if (hpusbscsi->state != HP_STATE_ERROR) { + hpusbscsi->srb->result &= SCSI_ERR_MASK; + hpusbscsi->srb->result |= scsi_state; + } + + if (scsi_state == CHECK_CONDITION << 1) { + if (hpusbscsi->state == HP_STATE_WAIT) { + issue_request_sense(hpusbscsi); + } else { + /* we request sense after an eventual data transfer */ + hpusbscsi->state = HP_STATE_ERROR; + } + } + + if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1) /* we do a callback to the scsi layer if and only if all data has been transfered */ hpusbscsi->scallback(hpusbscsi->srb); @@ -396,6 +412,8 @@ hpusbscsi->state = HP_STATE_PREMATURE; TRACE_STATE; break; + case HP_STATE_ERROR: + break; default: printk(KERN_ERR"hpusbscsi: Unexpected status report.\n"); TRACE_STATE; @@ -474,11 +492,16 @@ DEBUG("Data transfer done\n"); TRACE_STATE; if (hpusbscsi->state != HP_STATE_PREMATURE) { - if (u->status < 0) + if (u->status < 0) { handle_usb_error(hpusbscsi); - else - hpusbscsi->state = HP_STATE_WAIT; + } else { + if (hpusbscsi->state != HP_STATE_ERROR) { + hpusbscsi->state = HP_STATE_WAIT; + } else { + issue_request_sense(hpusbscsi); + } TRACE_STATE; + } } else { if (hpusbscsi->scallback != NULL) hpusbscsi->scallback(hpusbscsi->srb); @@ -541,8 +564,25 @@ handle_usb_error(hpusbscsi); return; } - if (hpusbscsi->state != HP_STATE_PREMATURE) + if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR) hpusbscsi->state = HP_STATE_WORKING; } +static void issue_request_sense (struct hpusbscsi *hpusbscsi) +{ + FILL_BULK_URB( + &hpusbscsi->dataurb, + hpusbscsi->dev, + usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out), + &hpusbscsi->sense_command, + SENSE_COMMAND_SIZE, + request_sense_callback, + hpusbscsi + ); + + hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in); + if (0 > usb_submit_urb(&hpusbscsi->dataurb)) { + handle_usb_error(hpusbscsi); + } +} diff -Nru a/drivers/usb/hpusbscsi.h b/drivers/usb/hpusbscsi.h --- a/drivers/usb/hpusbscsi.h Fri Mar 22 15:47:42 2002 +++ b/drivers/usb/hpusbscsi.h Fri Mar 22 15:47:42 2002 @@ -4,9 +4,14 @@ /* large parts based on or taken from code by John Fremlin and Matt Dharm */ /* this file is licensed under the GPL */ +/* A big thanks to Jose for untiring testing */ + typedef void (*usb_urb_callback) (struct urb *); typedef void (*scsi_callback)(Scsi_Cmnd *); +#define SENSE_COMMAND_SIZE 6 +#define HPUSBSCSI_SENSE_LENGTH 0x16 + struct hpusbscsi { struct list_head lh; @@ -21,6 +26,7 @@ int number; scsi_callback scallback; Scsi_Cmnd *srb; + u8 sense_command[SENSE_COMMAND_SIZE]; int use_count; wait_queue_head_t pending; @@ -57,6 +63,7 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback); static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb); static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb); +static void issue_request_sense (struct hpusbscsi *hpusbscsi); static Scsi_Host_Template hpusbscsi_scsi_host_template = { name: "hpusbscsi",