Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb/input
In directory usw-pr-cvs1:/tmp/cvs-serv3731/drivers/usb/input
Modified Files:
hid-lg3dff.c
Log Message:
Fixed timer deletion.
Comments updated.
Index: hid-lg3dff.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/usb/input/hid-lg3dff.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- hid-lg3dff.c 26 Apr 2002 16:26:00 -0000 1.2
+++ hid-lg3dff.c 2 Jun 2002 17:34:22 -0000 1.3
@@ -37,10 +37,10 @@
#define RUN_AT(t) (jiffies + (t))
-/* Frequency at which the rendering is updated */
-#define FREQ (HZ/20)
+/* Periodicity of the update */
+#define PERIOD (HZ/10)
-/* Effect status */
+/* Effect status: lg3d_effect::flags */
#define EFFECT_STARTED 0 /* Effect is going to play after some time
(ff_replay.delay) */
#define EFFECT_PLAYING 1 /* Effect is being played */
@@ -66,6 +66,10 @@
unsigned long started_at; /* When the effect started to play */
};
+// For lg3d_device::flags
+#define DEVICE_USB_XMIT 0 /* An URB is being sent */
+#define DEVICE_CLOSING 1 /* The driver is being unitialised */
+
struct lg3d_device {
struct hid_device* hid;
@@ -80,6 +84,9 @@
struct timer_list timer;
unsigned long last_time; /* Last time the timer handler was
executed */
+
+ unsigned long flags[1]; /* Contains various information about the
+ state of the driver for this device */
};
static void hid_lg3d_ctrl_out(struct urb *urb);
@@ -138,6 +145,7 @@
printk(KERN_INFO "Force feedback for Logitech *3D devices by Johann Deneux <de...@if...>\n");
/* Start the update task */
+ private->timer.expires = RUN_AT(PERIOD);
add_timer(&private->timer); /*TODO: only run the timer when at least
one effect is playing */
@@ -147,6 +155,11 @@
static void hid_lg3d_exit(struct hid_device* hid)
{
struct lg3d_device *lg3d = hid->ff_private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lg3d->lock, flags);
+ set_bit(DEVICE_CLOSING, lg3d->flags);
+ spin_unlock_irqrestore(&lg3d->lock, flags);
del_timer_sync(&lg3d->timer);
@@ -154,6 +167,8 @@
usb_unlink_urb(lg3d->urbffout);
usb_free_urb(lg3d->urbffout);
}
+
+ kfree(lg3d);
}
static int hid_lg3d_event(struct hid_device *hid, struct input_dev* input,
@@ -247,7 +262,7 @@
int id;
unsigned long flags;
- dbg("ioctl rumble");
+ dbg("ioctl upload");
if (!test_bit(effect->type, input->ffbit)) return -EINVAL;
@@ -280,8 +295,6 @@
new.effect = *effect;
new.effect.replay = effect->replay;
- /* If we updated an effect that was being played, we need to remake
- the rumble effect */
if (test_bit(EFFECT_STARTED, lg3d->effects[id].flags)
|| test_bit(EFFECT_STARTED, lg3d->effects[id].flags)) {
@@ -306,10 +319,17 @@
static void hid_lg3d_ctrl_out(struct urb *urb)
{
struct hid_device *hid = urb->context;
+ struct lg3d_device *lg3d = hid->ff_private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lg3d->lock, flags);
if (urb->status)
warn("hid_irq_ffout status %d received", urb->status);
+ clear_bit(DEVICE_USB_XMIT, lg3d->flags);
+ dbg("xmit = 0");
+ spin_unlock_irqrestore(&lg3d->lock, flags);
}
static void hid_lg3d_timer(unsigned long timer_data)
@@ -325,6 +345,22 @@
y = 0;
spin_lock_irqsave(&lg3d->lock, flags);
+ if (test_bit(DEVICE_USB_XMIT, lg3d->flags)) {
+ if (lg3d->urbffout->status != -EINPROGRESS) {
+ warn("xmit *not* in progress");
+ }
+ else {
+ dbg("xmit in progress");
+ }
+
+ spin_unlock_irqrestore(&lg3d->lock, flags);
+
+ lg3d->timer.expires = RUN_AT(PERIOD);
+ add_timer(&lg3d->timer);
+
+ return;
+ }
+
for (i=0; i<N_EFFECTS; ++i) {
struct lg3d_effect* effect = lg3d->effects +i;
@@ -360,8 +396,6 @@
}
}
- spin_unlock_irqrestore(&lg3d->lock, flags);
-
lg3d->urbffout->pipe = usb_sndctrlpipe(hid->dev, 0);
lg3d->ffcr.bRequestType = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE;
lg3d->urbffout->transfer_buffer_length = lg3d->ffcr.wLength = 8;
@@ -379,6 +413,13 @@
if ((err=usb_submit_urb(lg3d->urbffout, GFP_ATOMIC)))
warn("usb_submit_urb returned %d", err);
+ else
+ set_bit(DEVICE_USB_XMIT, lg3d->flags);
- add_timer(&lg3d->timer);
+ if (!test_bit(DEVICE_CLOSING, lg3d->flags)) {
+ lg3d->timer.expires = RUN_AT(PERIOD);
+ add_timer(&lg3d->timer);
+ }
+
+ spin_unlock_irqrestore(&lg3d->lock, flags);
}
|