Hello
The attached patch fixes a bug in my driver :
When i unplug the camera during transfer, the camera is marked as
unplugged.
If this happens during a user program is within the read function, it
can happen
that the camera is marked as ready again. (Very bad mistake)
This might be a the reason for some Kernel oops ?!.
I have testet the driver with 2.3.99-pre4 :
OHCI running ( and fastest )
( OPTi Inc. 82C861 (rev 10) PCI Card )
Both UHCI running
( Intel Corporation 82371AB PIIX4 USB (rev 01) )
and didn't get any errors.
Randy: Please apply .. (patch is against pre6-3 )
Henning
--- linux/drivers/usb/mdc800.c.orig Sat Apr 15 18:13:49 2000
+++ linux/drivers/usb/mdc800.c Sat Apr 15 18:13:59 2000
@@ -30,6 +30,12 @@
*
* The driver supports only one camera.
*
+ * version 0.7.3
+ * bugfix : The mdc800->state field gets set to READY after the
+ * the diconnect function sets it to NOT_CONNECTED. This makes the
+ * driver running like the camera is connected and causes some
+ * hang ups.
+ *
* version 0.7.1
* MOD_INC and MOD_DEC are changed in usb_probe to prevent load/unload
* problems when compiled as Module.
@@ -73,8 +79,8 @@
#include <linux/usb.h>
-#define VERSION "0.7.1"
-#define RELEASE_DATE "(26/03/2000)"
+#define VERSION "0.7.3"
+#define RELEASE_DATE "(15/04/2000)"
/* Vendor and Product Information */
#define MDC800_VENDOR_ID 0x055f
@@ -110,29 +116,29 @@
unsigned int endpoint [4];
- purb_t irq_urb;
+ purb_t irq_urb;
wait_queue_head_t irq_wait;
- char* irq_urb_buffer;
+ char* irq_urb_buffer;
- int camera_busy; // is camera busy ?
+ int camera_busy; // is camera busy ?
int camera_request_ready; // Status to synchronize with irq
char camera_response [8]; // last Bytes send after busy
- purb_t write_urb;
- char* write_urb_buffer;
+ purb_t write_urb;
+ char* write_urb_buffer;
wait_queue_head_t write_wait;
purb_t download_urb;
- char* download_urb_buffer;
+ char* download_urb_buffer;
wait_queue_head_t download_wait;
- int download_left; // Bytes left to download ?
+ int download_left; // Bytes left to
+download ?
/* Device Data */
- char out [64]; // Answer Buffer
+ char out [64]; // Answer Buffer
int out_ptr; // Index to the first not
readen byte
- int out_count; // Bytes in the buffer
+ int out_count; // Bytes in the buffer
int open; // Camera device open ?
int rw_lock; // Block read <-> write
@@ -284,9 +290,17 @@
{
mdc800->camera_request_ready=0;
err ("timeout waiting for camera.");
- return 0;
+ return -1;
}
- return 1;
+
+ if (mdc800->state == NOT_CONNECTED)
+ {
+ warn ("Camera gets disconnected during waiting for irq.");
+ mdc800->camera_request_ready=0;
+ return -2;
+ }
+
+ return 0;
}
@@ -301,7 +315,10 @@
{
err ("writing command fails (status=%i)", urb->status);
}
- mdc800->state=READY;
+ else
+ {
+ mdc800->state=READY;
+ }
wake_up_interruptible (&mdc800->write_wait);
}
@@ -328,7 +345,6 @@
else
{
err ("request bytes fails (status:%i)", urb->status);
- mdc800->state=READY;
}
wake_up_interruptible (&mdc800->download_wait);
}
@@ -416,6 +432,8 @@
mdc800->dev=dev;
mdc800->state=READY;
+ mdc800->open=0;
+ mdc800->rw_lock=0;
/* Setup URB Structs */
FILL_INT_URB (
@@ -464,10 +482,8 @@
if (mdc800->state == NOT_CONNECTED)
return;
-
+
mdc800->state=NOT_CONNECTED;
- mdc800->open=0;
- mdc800->rw_lock=0;
usb_unlink_urb (mdc800->irq_urb);
usb_unlink_urb (mdc800->write_urb);
@@ -599,6 +615,12 @@
if (mdc800->state == NOT_CONNECTED)
return -EBUSY;
+ if (mdc800->state == WORKING)
+ {
+ warn ("Illegal State \"working\" reached during read ?!");
+ return -EBUSY;
+ }
+
if (!mdc800->open || mdc800->rw_lock)
return -EBUSY;
mdc800->rw_lock=1;
@@ -624,15 +646,13 @@
if (usb_submit_urb (mdc800->download_urb))
{
err ("Can't submit download urb
(status=%i)",mdc800->download_urb->status);
- mdc800->state=READY;
mdc800->rw_lock=0;
return len-left;
}
interruptible_sleep_on_timeout
(&mdc800->download_wait, TO_DOWNLOAD_GET_READY*HZ/1000);
if (mdc800->download_urb->status != 0)
{
- err ("requesting bytes fails
(status=%i)",mdc800->download_urb->status);
- mdc800->state=READY;
+ err ("request download-bytes fails
+(status=%i)",mdc800->download_urb->status);
mdc800->rw_lock=0;
return len-left;
}
@@ -710,7 +730,12 @@
{
int answersize;
- mdc800_usb_waitForIRQ (0,TO_GET_READY);
+ if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
+ {
+ err ("Camera didn't get ready.\n");
+ mdc800->rw_lock=0;
+ return -EIO;
+ }
answersize=mdc800_getAnswerSize (mdc800->in[1]);
@@ -720,14 +745,12 @@
{
err ("submitting write urb fails (status=%i)",
mdc800->write_urb->status);
mdc800->rw_lock=0;
- mdc800->state=READY;
return -EIO;
}
interruptible_sleep_on_timeout (&mdc800->write_wait,
TO_DEFAULT_COMMAND*HZ/1000);
if (mdc800->state == WORKING)
{
usb_unlink_urb (mdc800->write_urb);
- mdc800->state=READY;
mdc800->rw_lock=0;
return -EIO;
}
@@ -756,10 +779,9 @@
if (answersize)
{
- if (!mdc800_usb_waitForIRQ
(1,TO_READ_FROM_IRQ))
+ if (mdc800_usb_waitForIRQ
+(1,TO_READ_FROM_IRQ))
{
err ("requesting answer from
irq fails");
- mdc800->state=READY;
mdc800->rw_lock=0;
return -EIO;
}
@@ -785,11 +807,10 @@
}
else
{
- if (!mdc800_usb_waitForIRQ
(0,TO_DEFAULT_COMMAND))
+ if (mdc800_usb_waitForIRQ
+(0,TO_DEFAULT_COMMAND))
{
err ("Command Timeout.");
mdc800->rw_lock=0;
- mdc800->state=READY;
return -EIO;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]