On Mon, Dec 15, 2003 at 11:35:33PM +0000, Johann Deneux wrote:
Attached is a patch doing two things:
hid-lgff.c: Fixes an obvious list handling issue.
hid-core.c: - Use INT out urbs instead of bulk out urbs. That's the way it should be
- Remove some report->id magic.
IMPORTANT NOTE: You probably do not want to apply this patch yet. I do not understand what the report->id thing is supposed to do, but I know it prevents my driver to work (no complaint from usb_submit_urb, but my device just won't react to it)
What does the HID descriptor for this device look like?
If the device has multiple reports, the first byte in the data buffer must contain the report ID. Probably some of the magic constants in hid-lgff are report IDs - they must be placed in the 'id' field in your copied hid_report structures and removed from the value.
Indeed, you were right. Corrected patch against 2.6.0-test9 attached:
hid-lgff.c:
- Fixes an obvious list handling issue.
- The first value in the "rumble" report was actually the report's id. Removed it, since hid-core.c takes care of it.
- Email address update
hid-core.c: - Use INT out urbs instead of bulk out urbs. That's the way it should be. - Print out the error code when usb_submit_urb() fails in hid_submit_out().
-- Johann Deneux
diff -u linux-2.6.0-test9-old/drivers/usb/input/hid-core.c linux-2.6.0-test9-new/drivers/usb/input/hid-core.c --- linux-2.6.0-test9-old/drivers/usb/input/hid-core.c 2003-12-15 23:26:55.000000000 +0000 +++ linux-2.6.0-test9-new/drivers/usb/input/hid-core.c 2003-12-17 20:33:35.000000000 +0000 @@ -1046,6 +1046,7 @@ static int hid_submit_out(struct hid_device *hid) { struct hid_report *report; + int err; report = hid->out[hid->outtail]; @@ -1053,10 +1054,10 @@ hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); hid->urbout->dev = hid->dev; - dbg("submitting out urb"); + dbg("submitting out urb with size %d", hid->urbout->transfer_buffer_length); - if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) { - err("usb_submit_urb(out) failed"); + if ((err = usb_submit_urb(hid->urbout, GFP_ATOMIC))) { + err("usb_submit_urb(out) failed (%d)", err); return -1; } @@ -1521,9 +1522,9 @@ continue; if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL))) goto fail; - pipe = usb_sndbulkpipe(dev, endpoint->bEndpointAddress); - usb_fill_bulk_urb(hid->urbout, dev, pipe, hid->outbuf, 0, - hid_irq_out, hid); + pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); + usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0, + hid_irq_out, hid, 1); hid->urbout->transfer_dma = hid->outbuf_dma; hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; } diff -u linux-2.6.0-test9-old/drivers/usb/input/hid-lgff.c linux-2.6.0-test9-new/drivers/usb/input/hid-lgff.c --- linux-2.6.0-test9-old/drivers/usb/input/hid-lgff.c 2003-12-15 23:26:55.000000000 +0000 +++ linux-2.6.0-test9-new/drivers/usb/input/hid-lgff.c 2003-12-17 20:38:57.000000000 +0000 @@ -6,7 +6,7 @@ * - WingMan Cordless RumblePad * - WingMan Force 3D * - * Copyright (c) 2002 Johann Deneux + * Copyright (c) 2002,2003 Johann Deneux */ /* @@ -25,13 +25,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so by - * e-mail - mail your message to <[EMAIL PROTECTED]> + * e-mail - mail your message to <[EMAIL PROTECTED]> */ #include <linux/input.h> #include <linux/sched.h> -#define DEBUG +//#define DEBUG #include <linux/usb.h> #include <linux/circ_buf.h> @@ -179,8 +179,7 @@ kfree(private); return -1; } - private->rumble->field[0]->value[0] = 0x03; - private->rumble->field[0]->value[1] = 0x42; + private->rumble->field[0]->value[0] = 0x42; private->condition = hid_lgff_duplicate_report(report); @@ -207,7 +206,7 @@ add_timer(&private->timer); /*TODO: only run the timer when at least one effect is playing */ - printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <[EMAIL PROTECTED]>\n"); + printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <[EMAIL PROTECTED]>\n"); return 0; } @@ -254,7 +253,7 @@ signed short* ff; u16 idVendor = hid->dev->descriptor.idVendor; u16 idProduct = hid->dev->descriptor.idProduct; - struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct)) dev++; @@ -511,10 +510,10 @@ hid_submit_report(hid, lgff->constant, USB_DIR_OUT); } - if (left != lgff->rumble->field[0]->value[3] - || right != lgff->rumble->field[0]->value[4]) { - lgff->rumble->field[0]->value[3] = left; - lgff->rumble->field[0]->value[4] = right; + if (left != lgff->rumble->field[0]->value[2] + || right != lgff->rumble->field[0]->value[3]) { + lgff->rumble->field[0]->value[2] = left; + lgff->rumble->field[0]->value[3] = right; dbg("(left,right)=(%04x, %04x)", left, right); hid_submit_report(hid, lgff->rumble, USB_DIR_OUT); }