<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># 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   -&gt; 1.227  
#	drivers/usb/hpusbscsi.h	1.2     -&gt; 1.3    
#	drivers/usb/hpusbscsi.c	1.3     -&gt; 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, &amp;(new-&gt;ctempl)))
 		goto err_out;
 
+	new-&gt;sense_command[0] = REQUEST_SENSE;
+	new-&gt;sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
+
 	/* adding to list for module unload */
 	list_add (&amp;hpusbscsi_devices, &amp;new-&gt;lh);
 
@@ -163,7 +166,6 @@
 	int result;
 
 	INIT_LIST_HEAD (&amp;hpusbscsi_devices);
-	DEBUG ("Driver loaded\n");
 
 	if ((result = usb_register (&amp;hpusbscsi_usb_driver)) &lt; 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-&gt;context;
+	u8 scsi_state;
 
 DEBUG("Getting status byte %d \n",hpusbscsi-&gt;scsi_state_byte);
 	if(u-&gt;status &lt; 0) {
@@ -378,10 +381,23 @@
                         handle_usb_error(hpusbscsi);
 		return;
 	}
-	hpusbscsi-&gt;srb-&gt;result &amp;= SCSI_ERR_MASK;
-	hpusbscsi-&gt;srb-&gt;result |= hpusbscsi-&gt;scsi_state_byte;
 
-	if (hpusbscsi-&gt;scallback != NULL &amp;&amp; hpusbscsi-&gt;state == HP_STATE_WAIT)
+	scsi_state = hpusbscsi-&gt;scsi_state_byte;
+        if (hpusbscsi-&gt;state != HP_STATE_ERROR) {
+                hpusbscsi-&gt;srb-&gt;result &amp;= SCSI_ERR_MASK;
+                hpusbscsi-&gt;srb-&gt;result |= scsi_state;
+        }
+
+	if (scsi_state == CHECK_CONDITION &lt;&lt; 1) {
+		if (hpusbscsi-&gt;state == HP_STATE_WAIT) {
+			issue_request_sense(hpusbscsi);
+		} else {
+			/* we request sense after an eventual data transfer */
+			hpusbscsi-&gt;state = HP_STATE_ERROR;
+		}
+	}
+
+	if (hpusbscsi-&gt;scallback != NULL &amp;&amp; hpusbscsi-&gt;state == HP_STATE_WAIT &amp;&amp; scsi_state != CHECK_CONDITION &lt;&lt;1)
 		/* we do a callback to the scsi layer if and only if all data has been transfered */
 		hpusbscsi-&gt;scallback(hpusbscsi-&gt;srb);
 
@@ -396,6 +412,8 @@
 		hpusbscsi-&gt;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-&gt;state != HP_STATE_PREMATURE) {
-		if (u-&gt;status &lt; 0)
+		if (u-&gt;status &lt; 0) {
 			handle_usb_error(hpusbscsi);
-		else
-			hpusbscsi-&gt;state = HP_STATE_WAIT;
+		} else {
+			if (hpusbscsi-&gt;state != HP_STATE_ERROR) {
+				hpusbscsi-&gt;state = HP_STATE_WAIT;
+			} else {
+				issue_request_sense(hpusbscsi);
+			}
 		TRACE_STATE;
+		}
 	} else {
 		if (hpusbscsi-&gt;scallback != NULL)
 			hpusbscsi-&gt;scallback(hpusbscsi-&gt;srb);
@@ -541,8 +564,25 @@
 		handle_usb_error(hpusbscsi);
 		return;
 	}
-	if (hpusbscsi-&gt;state != HP_STATE_PREMATURE)
+	if (hpusbscsi-&gt;state != HP_STATE_PREMATURE &amp;&amp; hpusbscsi-&gt;state != HP_STATE_ERROR)
 		hpusbscsi-&gt;state = HP_STATE_WORKING;
 }
 
+static void issue_request_sense (struct hpusbscsi *hpusbscsi)
+{
+	FILL_BULK_URB(
+		&amp;hpusbscsi-&gt;dataurb,
+		hpusbscsi-&gt;dev,
+		usb_sndbulkpipe(hpusbscsi-&gt;dev, hpusbscsi-&gt;ep_out),
+		&amp;hpusbscsi-&gt;sense_command,
+		SENSE_COMMAND_SIZE,
+		request_sense_callback,
+		hpusbscsi
+	);
+
+	hpusbscsi-&gt;current_data_pipe = usb_rcvbulkpipe(hpusbscsi-&gt;dev, hpusbscsi-&gt;ep_in);
 
+	if (0 &gt; usb_submit_urb(&amp;hpusbscsi-&gt;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",
</pre></body></html>