Commit 4f5a8104 authored by Jiri Kosina's avatar Jiri Kosina

Merge branches 'for-3.10/appleir', 'for-3.10/hid-debug',...

Merge branches 'for-3.10/appleir', 'for-3.10/hid-debug', 'for-3.10/hid-driver-transport-cleanups', 'for-3.10/i2c-hid' and 'for-3.10/logitech' into for-linus
This diff is collapsed.
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include "hid-ids.h" #include "hid-ids.h"
......
...@@ -29,14 +29,12 @@ ...@@ -29,14 +29,12 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include "hid-ids.h" #include "hid-ids.h"
#ifdef CONFIG_HID_ACRUX_FF #ifdef CONFIG_HID_ACRUX_FF
#include "usbhid/usbhid.h"
struct axff_device { struct axff_device {
struct hid_report *report; struct hid_report *report;
...@@ -68,7 +66,7 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect ...@@ -68,7 +66,7 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect
} }
dbg_hid("running with 0x%02x 0x%02x", left, right); dbg_hid("running with 0x%02x 0x%02x", left, right);
usbhid_submit_report(hid, axff->report, USB_DIR_OUT); hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -114,7 +112,7 @@ static int axff_init(struct hid_device *hid) ...@@ -114,7 +112,7 @@ static int axff_init(struct hid_device *hid)
goto err_free_mem; goto err_free_mem;
axff->report = report; axff->report = report;
usbhid_submit_report(hid, axff->report, USB_DIR_OUT); hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n"); hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n");
......
...@@ -728,8 +728,7 @@ static int hid_scan_report(struct hid_device *hid) ...@@ -728,8 +728,7 @@ static int hid_scan_report(struct hid_device *hid)
} else if (page == HID_UP_SENSOR && } else if (page == HID_UP_SENSOR &&
item.type == HID_ITEM_TYPE_MAIN && item.type == HID_ITEM_TYPE_MAIN &&
item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION && item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
(item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL && (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL)
(hid->bus == BUS_USB || hid->bus == BUS_I2C))
hid->group = HID_GROUP_SENSOR_HUB; hid->group = HID_GROUP_SENSOR_HUB;
} }
...@@ -1260,14 +1259,12 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i ...@@ -1260,14 +1259,12 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
struct hid_report_enum *report_enum; struct hid_report_enum *report_enum;
struct hid_driver *hdrv; struct hid_driver *hdrv;
struct hid_report *report; struct hid_report *report;
char *buf;
unsigned int i;
int ret = 0; int ret = 0;
if (!hid) if (!hid)
return -ENODEV; return -ENODEV;
if (down_trylock(&hid->driver_lock)) if (down_trylock(&hid->driver_input_lock))
return -EBUSY; return -EBUSY;
if (!hid->driver) { if (!hid->driver) {
...@@ -1284,28 +1281,9 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i ...@@ -1284,28 +1281,9 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
} }
/* Avoid unnecessary overhead if debugfs is disabled */ /* Avoid unnecessary overhead if debugfs is disabled */
if (list_empty(&hid->debug_list)) if (!list_empty(&hid->debug_list))
goto nomem; hid_dump_report(hid, type, data, size);
buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
if (!buf)
goto nomem;
/* dump the report */
snprintf(buf, HID_DEBUG_BUFSIZE - 1,
"\nreport (size %u) (%snumbered) = ", size, report_enum->numbered ? "" : "un");
hid_debug_event(hid, buf);
for (i = 0; i < size; i++) {
snprintf(buf, HID_DEBUG_BUFSIZE - 1,
" %02x", data[i]);
hid_debug_event(hid, buf);
}
hid_debug_event(hid, "\n");
kfree(buf);
nomem:
report = hid_get_report(report_enum, data); report = hid_get_report(report_enum, data);
if (!report) { if (!report) {
...@@ -1324,7 +1302,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i ...@@ -1324,7 +1302,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
ret = hid_report_raw_event(hid, type, data, size, interrupt); ret = hid_report_raw_event(hid, type, data, size, interrupt);
unlock: unlock:
up(&hid->driver_lock); up(&hid->driver_input_lock);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(hid_input_report); EXPORT_SYMBOL_GPL(hid_input_report);
...@@ -1848,6 +1826,11 @@ static int hid_device_probe(struct device *dev) ...@@ -1848,6 +1826,11 @@ static int hid_device_probe(struct device *dev)
if (down_interruptible(&hdev->driver_lock)) if (down_interruptible(&hdev->driver_lock))
return -EINTR; return -EINTR;
if (down_interruptible(&hdev->driver_input_lock)) {
ret = -EINTR;
goto unlock_driver_lock;
}
hdev->io_started = false;
if (!hdev->driver) { if (!hdev->driver) {
id = hid_match_device(hdev, hdrv); id = hid_match_device(hdev, hdrv);
...@@ -1870,6 +1853,9 @@ static int hid_device_probe(struct device *dev) ...@@ -1870,6 +1853,9 @@ static int hid_device_probe(struct device *dev)
} }
} }
unlock: unlock:
if (!hdev->io_started)
up(&hdev->driver_input_lock);
unlock_driver_lock:
up(&hdev->driver_lock); up(&hdev->driver_lock);
return ret; return ret;
} }
...@@ -1878,9 +1864,15 @@ static int hid_device_remove(struct device *dev) ...@@ -1878,9 +1864,15 @@ static int hid_device_remove(struct device *dev)
{ {
struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct hid_driver *hdrv; struct hid_driver *hdrv;
int ret = 0;
if (down_interruptible(&hdev->driver_lock)) if (down_interruptible(&hdev->driver_lock))
return -EINTR; return -EINTR;
if (down_interruptible(&hdev->driver_input_lock)) {
ret = -EINTR;
goto unlock_driver_lock;
}
hdev->io_started = false;
hdrv = hdev->driver; hdrv = hdev->driver;
if (hdrv) { if (hdrv) {
...@@ -1892,8 +1884,11 @@ static int hid_device_remove(struct device *dev) ...@@ -1892,8 +1884,11 @@ static int hid_device_remove(struct device *dev)
hdev->driver = NULL; hdev->driver = NULL;
} }
if (!hdev->io_started)
up(&hdev->driver_input_lock);
unlock_driver_lock:
up(&hdev->driver_lock); up(&hdev->driver_lock);
return 0; return ret;
} }
static ssize_t modalias_show(struct device *dev, struct device_attribute *a, static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
...@@ -2343,7 +2338,9 @@ struct hid_device *hid_allocate_device(void) ...@@ -2343,7 +2338,9 @@ struct hid_device *hid_allocate_device(void)
init_waitqueue_head(&hdev->debug_wait); init_waitqueue_head(&hdev->debug_wait);
INIT_LIST_HEAD(&hdev->debug_list); INIT_LIST_HEAD(&hdev->debug_list);
mutex_init(&hdev->debug_list_lock);
sema_init(&hdev->driver_lock, 1); sema_init(&hdev->driver_lock, 1);
sema_init(&hdev->driver_input_lock, 1);
return hdev; return hdev;
} }
......
...@@ -580,17 +580,49 @@ void hid_debug_event(struct hid_device *hdev, char *buf) ...@@ -580,17 +580,49 @@ void hid_debug_event(struct hid_device *hdev, char *buf)
int i; int i;
struct hid_debug_list *list; struct hid_debug_list *list;
mutex_lock(&hdev->debug_list_lock);
list_for_each_entry(list, &hdev->debug_list, node) { list_for_each_entry(list, &hdev->debug_list, node) {
for (i = 0; i < strlen(buf); i++) for (i = 0; i < strlen(buf); i++)
list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
buf[i]; buf[i];
list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
} }
mutex_unlock(&hdev->debug_list_lock);
wake_up_interruptible(&hdev->debug_wait); wake_up_interruptible(&hdev->debug_wait);
} }
EXPORT_SYMBOL_GPL(hid_debug_event); EXPORT_SYMBOL_GPL(hid_debug_event);
void hid_dump_report(struct hid_device *hid, int type, u8 *data,
int size)
{
struct hid_report_enum *report_enum;
char *buf;
unsigned int i;
buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
if (!buf)
return;
report_enum = hid->report_enum + type;
/* dump the report */
snprintf(buf, HID_DEBUG_BUFSIZE - 1,
"\nreport (size %u) (%snumbered) = ", size,
report_enum->numbered ? "" : "un");
hid_debug_event(hid, buf);
for (i = 0; i < size; i++) {
snprintf(buf, HID_DEBUG_BUFSIZE - 1,
" %02x", data[i]);
hid_debug_event(hid, buf);
}
hid_debug_event(hid, "\n");
kfree(buf);
}
EXPORT_SYMBOL_GPL(hid_dump_report);
void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value) void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value)
{ {
char *buf; char *buf;
...@@ -960,7 +992,9 @@ static int hid_debug_events_open(struct inode *inode, struct file *file) ...@@ -960,7 +992,9 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
file->private_data = list; file->private_data = list;
mutex_init(&list->read_mutex); mutex_init(&list->read_mutex);
mutex_lock(&list->hdev->debug_list_lock);
list_add_tail(&list->node, &list->hdev->debug_list); list_add_tail(&list->node, &list->hdev->debug_list);
mutex_unlock(&list->hdev->debug_list_lock);
out: out:
return err; return err;
...@@ -1055,7 +1089,9 @@ static int hid_debug_events_release(struct inode *inode, struct file *file) ...@@ -1055,7 +1089,9 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
{ {
struct hid_debug_list *list = file->private_data; struct hid_debug_list *list = file->private_data;
mutex_lock(&list->hdev->debug_list_lock);
list_del(&list->node); list_del(&list->node);
mutex_unlock(&list->hdev->debug_list_lock);
kfree(list->hid_debug_buf); kfree(list->hid_debug_buf);
kfree(list); kfree(list);
......
...@@ -29,14 +29,12 @@ ...@@ -29,14 +29,12 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include "hid-ids.h" #include "hid-ids.h"
#ifdef CONFIG_DRAGONRISE_FF #ifdef CONFIG_DRAGONRISE_FF
#include "usbhid/usbhid.h"
struct drff_device { struct drff_device {
struct hid_report *report; struct hid_report *report;
...@@ -68,7 +66,7 @@ static int drff_play(struct input_dev *dev, void *data, ...@@ -68,7 +66,7 @@ static int drff_play(struct input_dev *dev, void *data,
drff->report->field[0]->value[1] = 0x00; drff->report->field[0]->value[1] = 0x00;
drff->report->field[0]->value[2] = weak; drff->report->field[0]->value[2] = weak;
drff->report->field[0]->value[4] = strong; drff->report->field[0]->value[4] = strong;
usbhid_submit_report(hid, drff->report, USB_DIR_OUT); hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
drff->report->field[0]->value[0] = 0xfa; drff->report->field[0]->value[0] = 0xfa;
drff->report->field[0]->value[1] = 0xfe; drff->report->field[0]->value[1] = 0xfe;
...@@ -80,7 +78,7 @@ static int drff_play(struct input_dev *dev, void *data, ...@@ -80,7 +78,7 @@ static int drff_play(struct input_dev *dev, void *data,
drff->report->field[0]->value[2] = 0x00; drff->report->field[0]->value[2] = 0x00;
drff->report->field[0]->value[4] = 0x00; drff->report->field[0]->value[4] = 0x00;
dbg_hid("running with 0x%02x 0x%02x", strong, weak); dbg_hid("running with 0x%02x 0x%02x", strong, weak);
usbhid_submit_report(hid, drff->report, USB_DIR_OUT); hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -132,7 +130,7 @@ static int drff_init(struct hid_device *hid) ...@@ -132,7 +130,7 @@ static int drff_init(struct hid_device *hid)
drff->report->field[0]->value[4] = 0x00; drff->report->field[0]->value[4] = 0x00;
drff->report->field[0]->value[5] = 0x00; drff->report->field[0]->value[5] = 0x00;
drff->report->field[0]->value[6] = 0x00; drff->report->field[0]->value[6] = 0x00;
usbhid_submit_report(hid, drff->report, USB_DIR_OUT); hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
hid_info(hid, "Force Feedback for DragonRise Inc. " hid_info(hid, "Force Feedback for DragonRise Inc. "
"game controllers by Richard Walmsley <richwalm@gmail.com>\n"); "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
......
...@@ -23,11 +23,9 @@ ...@@ -23,11 +23,9 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/usb.h>
#include <linux/module.h> #include <linux/module.h>
#include "hid-ids.h" #include "hid-ids.h"
#include "usbhid/usbhid.h"
struct emsff_device { struct emsff_device {
struct hid_report *report; struct hid_report *report;
...@@ -52,7 +50,7 @@ static int emsff_play(struct input_dev *dev, void *data, ...@@ -52,7 +50,7 @@ static int emsff_play(struct input_dev *dev, void *data,
emsff->report->field[0]->value[2] = strong; emsff->report->field[0]->value[2] = strong;
dbg_hid("running with 0x%02x 0x%02x\n", strong, weak); dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -104,7 +102,7 @@ static int emsff_init(struct hid_device *hid) ...@@ -104,7 +102,7 @@ static int emsff_init(struct hid_device *hid)
emsff->report->field[0]->value[4] = 0x00; emsff->report->field[0]->value[4] = 0x00;
emsff->report->field[0]->value[5] = 0x00; emsff->report->field[0]->value[5] = 0x00;
emsff->report->field[0]->value[6] = 0x00; emsff->report->field[0]->value[6] = 0x00;
usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n"); hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n");
......
...@@ -29,13 +29,11 @@ ...@@ -29,13 +29,11 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include "hid-ids.h" #include "hid-ids.h"
#ifdef CONFIG_GREENASIA_FF #ifdef CONFIG_GREENASIA_FF
#include "usbhid/usbhid.h"
struct gaff_device { struct gaff_device {
struct hid_report *report; struct hid_report *report;
...@@ -63,14 +61,14 @@ static int hid_gaff_play(struct input_dev *dev, void *data, ...@@ -63,14 +61,14 @@ static int hid_gaff_play(struct input_dev *dev, void *data,
gaff->report->field[0]->value[4] = left; gaff->report->field[0]->value[4] = left;
gaff->report->field[0]->value[5] = 0; gaff->report->field[0]->value[5] = 0;
dbg_hid("running with 0x%02x 0x%02x", left, right); dbg_hid("running with 0x%02x 0x%02x", left, right);
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
gaff->report->field[0]->value[0] = 0xfa; gaff->report->field[0]->value[0] = 0xfa;
gaff->report->field[0]->value[1] = 0xfe; gaff->report->field[0]->value[1] = 0xfe;
gaff->report->field[0]->value[2] = 0x0; gaff->report->field[0]->value[2] = 0x0;
gaff->report->field[0]->value[4] = 0x0; gaff->report->field[0]->value[4] = 0x0;
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -122,12 +120,12 @@ static int gaff_init(struct hid_device *hid) ...@@ -122,12 +120,12 @@ static int gaff_init(struct hid_device *hid)
gaff->report->field[0]->value[1] = 0x00; gaff->report->field[0]->value[1] = 0x00;
gaff->report->field[0]->value[2] = 0x00; gaff->report->field[0]->value[2] = 0x00;
gaff->report->field[0]->value[3] = 0x00; gaff->report->field[0]->value[3] = 0x00;
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
gaff->report->field[0]->value[0] = 0xfa; gaff->report->field[0]->value[0] = 0xfa;
gaff->report->field[0]->value[1] = 0xfe; gaff->report->field[0]->value[1] = 0xfe;
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n"); hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
......
...@@ -27,12 +27,10 @@ ...@@ -27,12 +27,10 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include "hid-ids.h" #include "hid-ids.h"
#ifdef CONFIG_HOLTEK_FF #ifdef CONFIG_HOLTEK_FF
#include "usbhid/usbhid.h"
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>"); MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
...@@ -102,7 +100,7 @@ static void holtekff_send(struct holtekff_device *holtekff, ...@@ -102,7 +100,7 @@ static void holtekff_send(struct holtekff_device *holtekff,
dbg_hid("sending %*ph\n", 7, data); dbg_hid("sending %*ph\n", 7, data);
usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT); hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT);
} }
static int holtekff_play(struct input_dev *dev, void *data, static int holtekff_play(struct input_dev *dev, void *data,
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h" #include "hid-ids.h"
...@@ -361,7 +359,7 @@ static int kye_tablet_enable(struct hid_device *hdev) ...@@ -361,7 +359,7 @@ static int kye_tablet_enable(struct hid_device *hdev)
value[4] = 0x00; value[4] = 0x00;
value[5] = 0x00; value[5] = 0x00;
value[6] = 0x00; value[6] = 0x00;
usbhid_submit_report(hdev, report, USB_DIR_OUT); hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
......
...@@ -68,7 +68,7 @@ static int tpkbd_features_set(struct hid_device *hdev) ...@@ -68,7 +68,7 @@ static int tpkbd_features_set(struct hid_device *hdev)
report->field[2]->value[0] = data_pointer->sensitivity; report->field[2]->value[0] = data_pointer->sensitivity;
report->field[3]->value[0] = data_pointer->press_speed; report->field[3]->value[0] = data_pointer->press_speed;
usbhid_submit_report(hdev, report, USB_DIR_OUT); hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -332,7 +332,7 @@ static void tpkbd_led_brightness_set(struct led_classdev *led_cdev, ...@@ -332,7 +332,7 @@ static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
usbhid_submit_report(hdev, report, USB_DIR_OUT); hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
} }
static int tpkbd_probe_tp(struct hid_device *hdev) static int tpkbd_probe_tp(struct hid_device *hdev)
......
...@@ -23,10 +23,8 @@ ...@@ -23,10 +23,8 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid/usbhid.h"
#include "hid-lg.h" #include "hid-lg.h"
struct lg2ff_device { struct lg2ff_device {
...@@ -56,7 +54,7 @@ static int play_effect(struct input_dev *dev, void *data, ...@@ -56,7 +54,7 @@ static int play_effect(struct input_dev *dev, void *data,
lg2ff->report->field[0]->value[4] = 0x00; lg2ff->report->field[0]->value[4] = 0x00;
} }
usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT); hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -108,7 +106,7 @@ int lg2ff_init(struct hid_device *hid) ...@@ -108,7 +106,7 @@ int lg2ff_init(struct hid_device *hid)
report->field[0]->value[5] = 0x00; report->field[0]->value[5] = 0x00;
report->field[0]->value[6] = 0x00; report->field[0]->value[6] = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n"); hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n");
......
...@@ -22,10 +22,8 @@ ...@@ -22,10 +22,8 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid/usbhid.h"
#include "hid-lg.h" #include "hid-lg.h"
/* /*
...@@ -92,7 +90,7 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, ...@@ -92,7 +90,7 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data,
report->field[0]->value[1] = (unsigned char)(-x); report->field[0]->value[1] = (unsigned char)(-x);
report->field[0]->value[31] = (unsigned char)(-y); report->field[0]->value[31] = (unsigned char)(-y);
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break; break;
} }
return 0; return 0;
...@@ -118,7 +116,7 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude) ...@@ -118,7 +116,7 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
report->field[0]->value[33] = 0x7F; report->field[0]->value[33] = 0x7F;
report->field[0]->value[34] = 0x7F; report->field[0]->value[34] = 0x7F;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define DFGT_REV_MAJ 0x13 #define DFGT_REV_MAJ 0x13
#define DFGT_REV_MIN 0x22 #define DFGT_REV_MIN 0x22
#define DFGT2_REV_MIN 0x26
#define DFP_REV_MAJ 0x11 #define DFP_REV_MAJ 0x11
#define DFP_REV_MIN 0x06 #define DFP_REV_MIN 0x06
#define FFEX_REV_MAJ 0x21 #define FFEX_REV_MAJ 0x21
...@@ -125,6 +126,7 @@ static const struct lg4ff_native_cmd native_g27 = { ...@@ -125,6 +126,7 @@ static const struct lg4ff_native_cmd native_g27 = {
static const struct lg4ff_usb_revision lg4ff_revs[] = { static const struct lg4ff_usb_revision lg4ff_revs[] = {
{DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */ {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */
{DFGT_REV_MAJ, DFGT2_REV_MIN, &native_dfgt}, /* Driving Force GT v2 */
{DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */ {DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */
{G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */ {G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */
{G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */ {G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */
...@@ -202,7 +204,7 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e ...@@ -202,7 +204,7 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e
value[5] = 0x00; value[5] = 0x00;
value[6] = 0x00; value[6] = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break; break;
} }
return 0; return 0;
...@@ -225,7 +227,7 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud ...@@ -225,7 +227,7 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
value[5] = 0x00; value[5] = 0x00;
value[6] = 0x00; value[6] = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
/* Sends autocentering command compatible with Formula Force EX */ /* Sends autocentering command compatible with Formula Force EX */
...@@ -245,7 +247,7 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) ...@@ -245,7 +247,7 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
value[5] = 0x00; value[5] = 0x00;
value[6] = 0x00; value[6] = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
/* Sends command to set range compatible with G25/G27/Driving Force GT */ /* Sends command to set range compatible with G25/G27/Driving Force GT */
...@@ -265,7 +267,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) ...@@ -265,7 +267,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
value[5] = 0x00; value[5] = 0x00;
value[6] = 0x00; value[6] = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
/* Sends commands to set range compatible with Driving Force Pro wheel */ /* Sends commands to set range compatible with Driving Force Pro wheel */
...@@ -294,7 +296,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) ...@@ -294,7 +296,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
report->field[0]->value[1] = 0x02; report->field[0]->value[1] = 0x02;
full_range = 200; full_range = 200;
} }
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
/* Prepare "fine" limit command */ /* Prepare "fine" limit command */
value[0] = 0x81; value[0] = 0x81;
...@@ -306,7 +308,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) ...@@ -306,7 +308,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
value[6] = 0x00; value[6] = 0x00;
if (range == 200 || range == 900) { /* Do not apply any fine limit */ if (range == 200 || range == 900) { /* Do not apply any fine limit */
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
return; return;
} }
...@@ -320,7 +322,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) ...@@ -320,7 +322,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
value[6] = 0xff; value[6] = 0xff;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd) static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
...@@ -334,7 +336,7 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n ...@@ -334,7 +336,7 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
report->field[0]->value[i] = cmd->cmd[j++]; report->field[0]->value[i] = cmd->cmd[j++];
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
} }
...@@ -410,7 +412,7 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds) ...@@ -410,7 +412,7 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
value[4] = 0x00; value[4] = 0x00;
value[5] = 0x00; value[5] = 0x00;
value[6] = 0x00; value[6] = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
......
...@@ -30,10 +30,8 @@ ...@@ -30,10 +30,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/input.h> #include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid/usbhid.h"
#include "hid-lg.h" #include "hid-lg.h"
struct dev_type { struct dev_type {
...@@ -89,7 +87,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef ...@@ -89,7 +87,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[2] = x; report->field[0]->value[2] = x;
report->field[0]->value[3] = y; report->field[0]->value[3] = y;
dbg_hid("(x, y)=(%04x, %04x)\n", x, y); dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break; break;
case FF_RUMBLE: case FF_RUMBLE:
...@@ -104,7 +102,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef ...@@ -104,7 +102,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[2] = left; report->field[0]->value[2] = left;
report->field[0]->value[3] = right; report->field[0]->value[3] = right;
dbg_hid("(left, right)=(%04x, %04x)\n", left, right); dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break; break;
} }
return 0; return 0;
...@@ -124,7 +122,7 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) ...@@ -124,7 +122,7 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
*value++ = 0x80; *value++ = 0x80;
*value++ = 0x00; *value++ = 0x00;
*value = 0x00; *value = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
} }
int lgff_init(struct hid_device* hid) int lgff_init(struct hid_device* hid)
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h" #include "hid-ids.h"
#include "hid-logitech-dj.h" #include "hid-logitech-dj.h"
...@@ -193,7 +192,6 @@ static struct hid_ll_driver logi_dj_ll_driver; ...@@ -193,7 +192,6 @@ static struct hid_ll_driver logi_dj_ll_driver;
static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
size_t count, size_t count,
unsigned char report_type); unsigned char report_type);
static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
struct dj_report *dj_report) struct dj_report *dj_report)
...@@ -234,7 +232,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, ...@@ -234,7 +232,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
SPFUNCTION_DEVICE_LIST_EMPTY) { SPFUNCTION_DEVICE_LIST_EMPTY) {
dbg_hid("%s: device list is empty\n", __func__); dbg_hid("%s: device list is empty\n", __func__);
djrcv_dev->querying_devices = false;
return; return;
} }
...@@ -245,12 +242,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, ...@@ -245,12 +242,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
return; return;
} }
if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
/* The device is already known. No need to reallocate it. */
dbg_hid("%s: device is already known\n", __func__);
return;
}
dj_hiddev = hid_allocate_device(); dj_hiddev = hid_allocate_device();
if (IS_ERR(dj_hiddev)) { if (IS_ERR(dj_hiddev)) {
dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
...@@ -314,7 +305,6 @@ static void delayedwork_callback(struct work_struct *work) ...@@ -314,7 +305,6 @@ static void delayedwork_callback(struct work_struct *work)
struct dj_report dj_report; struct dj_report dj_report;
unsigned long flags; unsigned long flags;
int count; int count;
int retval;
dbg_hid("%s\n", __func__); dbg_hid("%s\n", __func__);
...@@ -347,25 +337,6 @@ static void delayedwork_callback(struct work_struct *work) ...@@ -347,25 +337,6 @@ static void delayedwork_callback(struct work_struct *work)
logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
break; break;
default: default:
/* A normal report (i. e. not belonging to a pair/unpair notification)
* arriving here, means that the report arrived but we did not have a
* paired dj_device associated to the report's device_index, this
* means that the original "device paired" notification corresponding
* to this dj_device never arrived to this driver. The reason is that
* hid-core discards all packets coming from a device while probe() is
* executing. */
if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
/* ok, we don't know the device, just re-ask the
* receiver for the list of connected devices. */
retval = logi_dj_recv_query_paired_devices(djrcv_dev);
if (!retval) {
/* everything went fine, so just leave */
break;
}
dev_err(&djrcv_dev->hdev->dev,
"%s:logi_dj_recv_query_paired_devices "
"error:%d\n", __func__, retval);
}
dbg_hid("%s: unexpected report type\n", __func__); dbg_hid("%s: unexpected report type\n", __func__);
} }
} }
...@@ -396,12 +367,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, ...@@ -396,12 +367,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
if (!djdev) { if (!djdev) {
dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
" is NULL, index %d\n", dj_report->device_index); " is NULL, index %d\n", dj_report->device_index);
kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
if (schedule_work(&djrcv_dev->work) == 0) {
dbg_hid("%s: did not schedule the work item, was already "
"queued\n", __func__);
}
return; return;
} }
...@@ -432,12 +397,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, ...@@ -432,12 +397,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
if (dj_device == NULL) { if (dj_device == NULL) {
dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
" is NULL, index %d\n", dj_report->device_index); " is NULL, index %d\n", dj_report->device_index);
kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
if (schedule_work(&djrcv_dev->work) == 0) {
dbg_hid("%s: did not schedule the work item, was already "
"queued\n", __func__);
}
return; return;
} }
...@@ -475,7 +434,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, ...@@ -475,7 +434,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
for (i = 0; i < report->field[0]->report_count; i++) for (i = 0; i < report->field[0]->report_count; i++)
report->field[0]->value[i] = data[i]; report->field[0]->value[i] = data[i];
usbhid_submit_report(hdev, report, USB_DIR_OUT); hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -485,10 +444,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) ...@@ -485,10 +444,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
struct dj_report *dj_report; struct dj_report *dj_report;
int retval; int retval;
/* no need to protect djrcv_dev->querying_devices */
if (djrcv_dev->querying_devices)
return 0;
dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
if (!dj_report) if (!dj_report)
return -ENOMEM; return -ENOMEM;
...@@ -500,7 +455,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) ...@@ -500,7 +455,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
return retval; return retval;
} }
static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
unsigned timeout) unsigned timeout)
{ {
...@@ -644,7 +598,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, ...@@ -644,7 +598,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS); hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
hid_set_field(report->field[0], 2, data[1]); hid_set_field(report->field[0], 2, data[1]);
usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT); hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
return 0; return 0;
...@@ -809,6 +763,9 @@ static int logi_dj_probe(struct hid_device *hdev, ...@@ -809,6 +763,9 @@ static int logi_dj_probe(struct hid_device *hdev,
goto llopen_failed; goto llopen_failed;
} }
/* Allow incoming packets to arrive: */
hid_device_io_start(hdev);
retval = logi_dj_recv_query_paired_devices(djrcv_dev); retval = logi_dj_recv_query_paired_devices(djrcv_dev);
if (retval < 0) { if (retval < 0) {
dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices " dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
......
...@@ -101,7 +101,6 @@ struct dj_receiver_dev { ...@@ -101,7 +101,6 @@ struct dj_receiver_dev {
struct work_struct work; struct work_struct work;
struct kfifo notif_fifo; struct kfifo notif_fifo;
spinlock_t lock; spinlock_t lock;
bool querying_devices;
}; };
struct dj_device { struct dj_device {
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include "hid-ids.h" #include "hid-ids.h"
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
* HID driver for multitouch panels * HID driver for multitouch panels
* *
* Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr> * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
* Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com> * Copyright (c) 2010-2013 Benjamin Tissoires <benjamin.tissoires@gmail.com>
* Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France * Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
* Copyright (c) 2012-2013 Red Hat, Inc
* *
* This code is partly based on hid-egalax.c: * This code is partly based on hid-egalax.c:
* *
...@@ -26,13 +27,23 @@ ...@@ -26,13 +27,23 @@
* any later version. * any later version.
*/ */
/*
* This driver is regularly tested thanks to the tool hid-test[1].
* This tool relies on hid-replay[2] and a database of hid devices[3].
* Please run these regression tests before patching this module so that
* your patch won't break existing known devices.
*
* [1] https://github.com/bentiss/hid-test
* [2] https://github.com/bentiss/hid-replay
* [3] https://github.com/bentiss/hid-devices
*/
#include <linux/device.h> #include <linux/device.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include "usbhid/usbhid.h"
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
...@@ -740,7 +751,7 @@ static void mt_set_input_mode(struct hid_device *hdev) ...@@ -740,7 +751,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
r = re->report_id_hash[td->inputmode]; r = re->report_id_hash[td->inputmode];
if (r) { if (r) {
r->field[0]->value[td->inputmode_index] = 0x02; r->field[0]->value[td->inputmode_index] = 0x02;
usbhid_submit_report(hdev, r, USB_DIR_OUT); hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
} }
} }
...@@ -765,7 +776,7 @@ static void mt_set_maxcontacts(struct hid_device *hdev) ...@@ -765,7 +776,7 @@ static void mt_set_maxcontacts(struct hid_device *hdev)
max = min(fieldmax, max); max = min(fieldmax, max);
if (r->field[0]->value[0] != max) { if (r->field[0]->value[0] != max) {
r->field[0]->value[0] = max; r->field[0]->value[0] = max;
usbhid_submit_report(hdev, r, USB_DIR_OUT); hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
} }
} }
} }
...@@ -902,26 +913,11 @@ static int mt_reset_resume(struct hid_device *hdev) ...@@ -902,26 +913,11 @@ static int mt_reset_resume(struct hid_device *hdev)
static int mt_resume(struct hid_device *hdev) static int mt_resume(struct hid_device *hdev)
{ {
struct usb_interface *intf;
struct usb_host_interface *interface;
struct usb_device *dev;
if (hdev->bus != BUS_USB)
return 0;
intf = to_usb_interface(hdev->dev.parent);
interface = intf->cur_altsetting;
dev = hid_to_usb_dev(hdev);
/* Some Elan legacy devices require SET_IDLE to be set on resume. /* Some Elan legacy devices require SET_IDLE to be set on resume.
* It should be safe to send it to other devices too. * It should be safe to send it to other devices too.
* Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */ * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
usb_control_msg(dev, usb_sndctrlpipe(dev, 0), hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
HID_REQ_SET_IDLE,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, interface->desc.bInterfaceNumber,
NULL, 0, USB_CTRL_SET_TIMEOUT);
return 0; return 0;
} }
......
...@@ -118,8 +118,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev) ...@@ -118,8 +118,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev)
if (!report) if (!report)
return -EINVAL; return -EINVAL;
usbhid_submit_report(hdev, report, USB_DIR_IN); hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
usbhid_wait_io(hdev); hid_hw_wait(hdev);
return (int)report->field[0]->value[0]; return (int)report->field[0]->value[0];
} }
...@@ -137,7 +137,7 @@ static inline void ntrig_set_mode(struct hid_device *hdev, const int mode) ...@@ -137,7 +137,7 @@ static inline void ntrig_set_mode(struct hid_device *hdev, const int mode)
if (!report) if (!report)
return; return;
usbhid_submit_report(hdev, report, USB_DIR_IN); hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
} }
static void ntrig_report_version(struct hid_device *hdev) static void ntrig_report_version(struct hid_device *hdev)
...@@ -937,8 +937,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -937,8 +937,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (report) { if (report) {
/* Let the device settle to ensure the wakeup message gets /* Let the device settle to ensure the wakeup message gets
* through */ * through */
usbhid_wait_io(hdev); hid_hw_wait(hdev);
usbhid_submit_report(hdev, report, USB_DIR_IN); hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
/* /*
* Sanity check: if the current mode is invalid reset it to * Sanity check: if the current mode is invalid reset it to
......
...@@ -142,10 +142,10 @@ struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir); ...@@ -142,10 +142,10 @@ struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
void picolcd_debug_out_report(struct picolcd_data *data, void picolcd_debug_out_report(struct picolcd_data *data,
struct hid_device *hdev, struct hid_report *report); struct hid_device *hdev, struct hid_report *report);
#define usbhid_submit_report(a, b, c) \ #define hid_hw_request(a, b, c) \
do { \ do { \
picolcd_debug_out_report(hid_get_drvdata(a), a, b); \ picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
usbhid_submit_report(a, b, c); \ hid_hw_request(a, b, c); \
} while (0) } while (0)
void picolcd_debug_raw_event(struct picolcd_data *data, void picolcd_debug_raw_event(struct picolcd_data *data,
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
***************************************************************************/ ***************************************************************************/
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/backlight.h> #include <linux/backlight.h>
...@@ -46,7 +44,7 @@ static int picolcd_set_brightness(struct backlight_device *bdev) ...@@ -46,7 +44,7 @@ static int picolcd_set_brightness(struct backlight_device *bdev)
spin_lock_irqsave(&data->lock, flags); spin_lock_irqsave(&data->lock, flags);
hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0); hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
if (!(data->status & PICOLCD_FAILED)) if (!(data->status & PICOLCD_FAILED))
usbhid_submit_report(data->hdev, report, USB_DIR_OUT); hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
return 0; return 0;
} }
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
#include <linux/hid-debug.h> #include <linux/hid-debug.h>
#include <linux/input.h> #include <linux/input.h>
#include "hid-ids.h" #include "hid-ids.h"
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
#include <linux/hid-debug.h> #include <linux/hid-debug.h>
#include <linux/input.h> #include <linux/input.h>
#include "hid-ids.h" #include "hid-ids.h"
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
...@@ -110,7 +108,7 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, ...@@ -110,7 +108,7 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
work = NULL; work = NULL;
} else { } else {
data->pending = work; data->pending = work;
usbhid_submit_report(data->hdev, report, USB_DIR_OUT); hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
wait_for_completion_interruptible_timeout(&work->ready, HZ*2); wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
spin_lock_irqsave(&data->lock, flags); spin_lock_irqsave(&data->lock, flags);
...@@ -244,7 +242,7 @@ int picolcd_reset(struct hid_device *hdev) ...@@ -244,7 +242,7 @@ int picolcd_reset(struct hid_device *hdev)
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
return -ENODEV; return -ENODEV;
} }
usbhid_submit_report(hdev, report, USB_DIR_OUT); hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
error = picolcd_check_version(hdev); error = picolcd_check_version(hdev);
...@@ -303,7 +301,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, ...@@ -303,7 +301,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
spin_lock_irqsave(&data->lock, flags); spin_lock_irqsave(&data->lock, flags);
hid_set_field(report->field[0], 0, timeout & 0xff); hid_set_field(report->field[0], 0, timeout & 0xff);
hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
usbhid_submit_report(data->hdev, report, USB_DIR_OUT); hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
return count; return count;
} }
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/hid-debug.h> #include <linux/hid-debug.h>
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -143,8 +141,8 @@ static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap, ...@@ -143,8 +141,8 @@ static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap,
else else
hid_set_field(report2->field[0], 4 + i - 32, tdata[i]); hid_set_field(report2->field[0], 4 + i - 32, tdata[i]);
usbhid_submit_report(data->hdev, report1, USB_DIR_OUT); hid_hw_request(data->hdev, report1, HID_REQ_SET_REPORT);
usbhid_submit_report(data->hdev, report2, USB_DIR_OUT); hid_hw_request(data->hdev, report2, HID_REQ_SET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
return 0; return 0;
} }
...@@ -214,7 +212,7 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear) ...@@ -214,7 +212,7 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear)
hid_set_field(report->field[0], j, mapcmd[j]); hid_set_field(report->field[0], j, mapcmd[j]);
else else
hid_set_field(report->field[0], j, 0); hid_set_field(report->field[0], j, 0);
usbhid_submit_report(data->hdev, report, USB_DIR_OUT); hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
} }
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
...@@ -270,7 +268,7 @@ static void picolcd_fb_update(struct fb_info *info) ...@@ -270,7 +268,7 @@ static void picolcd_fb_update(struct fb_info *info)
mutex_unlock(&info->lock); mutex_unlock(&info->lock);
if (!data) if (!data)
return; return;
usbhid_wait_io(data->hdev); hid_hw_wait(data->hdev);
mutex_lock(&info->lock); mutex_lock(&info->lock);
n = 0; n = 0;
} }
...@@ -288,7 +286,7 @@ static void picolcd_fb_update(struct fb_info *info) ...@@ -288,7 +286,7 @@ static void picolcd_fb_update(struct fb_info *info)
spin_unlock_irqrestore(&fbdata->lock, flags); spin_unlock_irqrestore(&fbdata->lock, flags);
mutex_unlock(&info->lock); mutex_unlock(&info->lock);
if (data) if (data)
usbhid_wait_io(data->hdev); hid_hw_wait(data->hdev);
return; return;
} }
out: out:
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
***************************************************************************/ ***************************************************************************/
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/lcd.h> #include <linux/lcd.h>
...@@ -48,7 +46,7 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast) ...@@ -48,7 +46,7 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
spin_lock_irqsave(&data->lock, flags); spin_lock_irqsave(&data->lock, flags);
hid_set_field(report->field[0], 0, data->lcd_contrast); hid_set_field(report->field[0], 0, data->lcd_contrast);
if (!(data->status & PICOLCD_FAILED)) if (!(data->status & PICOLCD_FAILED))
usbhid_submit_report(data->hdev, report, USB_DIR_OUT); hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
return 0; return 0;
} }
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
#include <linux/hid-debug.h> #include <linux/hid-debug.h>
#include <linux/input.h> #include <linux/input.h>
#include "hid-ids.h" #include "hid-ids.h"
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
...@@ -55,7 +53,7 @@ void picolcd_leds_set(struct picolcd_data *data) ...@@ -55,7 +53,7 @@ void picolcd_leds_set(struct picolcd_data *data)
spin_lock_irqsave(&data->lock, flags); spin_lock_irqsave(&data->lock, flags);
hid_set_field(report->field[0], 0, data->led_state); hid_set_field(report->field[0], 0, data->led_state);
if (!(data->status & PICOLCD_FAILED)) if (!(data->status & PICOLCD_FAILED))
usbhid_submit_report(data->hdev, report, USB_DIR_OUT); hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
} }
......
...@@ -43,13 +43,11 @@ ...@@ -43,13 +43,11 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include "hid-ids.h" #include "hid-ids.h"
#ifdef CONFIG_PANTHERLORD_FF #ifdef CONFIG_PANTHERLORD_FF
#include "usbhid/usbhid.h"
struct plff_device { struct plff_device {
struct hid_report *report; struct hid_report *report;
...@@ -75,7 +73,7 @@ static int hid_plff_play(struct input_dev *dev, void *data, ...@@ -75,7 +73,7 @@ static int hid_plff_play(struct input_dev *dev, void *data,
*plff->strong = left; *plff->strong = left;
*plff->weak = right; *plff->weak = right;
debug("running with 0x%02x 0x%02x", left, right); debug("running with 0x%02x 0x%02x", left, right);
usbhid_submit_report(hid, plff->report, USB_DIR_OUT); hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -169,7 +167,7 @@ static int plff_init(struct hid_device *hid) ...@@ -169,7 +167,7 @@ static int plff_init(struct hid_device *hid)
*strong = 0x00; *strong = 0x00;
*weak = 0x00; *weak = 0x00;
usbhid_submit_report(hid, plff->report, USB_DIR_OUT); hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT);
} }
hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <sound/core.h> #include <sound/core.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/rawmidi.h> #include <sound/rawmidi.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h" #include "hid-ids.h"
...@@ -306,7 +305,7 @@ static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state) ...@@ -306,7 +305,7 @@ static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state)
report->field[0]->value[0] = 0x01; report->field[0]->value[0] = 0x01;
report->field[0]->value[1] = state; report->field[0]->value[1] = state;
usbhid_submit_report(hdev, report, USB_DIR_OUT); hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
} }
static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data) static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data)
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
*/ */
#include <linux/device.h> #include <linux/device.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/usb.h>
#include "usbhid/usbhid.h"
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
...@@ -204,8 +202,8 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, ...@@ -204,8 +202,8 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
goto done_proc; goto done_proc;
} }
hid_set_field(report->field[field_index], 0, value); hid_set_field(report->field[field_index], 0, value);
usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT); hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
usbhid_wait_io(hsdev->hdev); hid_hw_wait(hsdev->hdev);
done_proc: done_proc:
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
...@@ -227,8 +225,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, ...@@ -227,8 +225,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
ret = -EINVAL; ret = -EINVAL;
goto done_proc; goto done_proc;
} }
usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
usbhid_wait_io(hsdev->hdev); hid_hw_wait(hsdev->hdev);
*value = report->field[field_index]->value[0]; *value = report->field[field_index]->value[0];
done_proc: done_proc:
...@@ -262,7 +260,7 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, ...@@ -262,7 +260,7 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
goto err_free; goto err_free;
} }
usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5); wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
switch (data->pending.raw_size) { switch (data->pending.raw_size) {
......
...@@ -28,13 +28,11 @@ ...@@ -28,13 +28,11 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include "hid-ids.h" #include "hid-ids.h"
#ifdef CONFIG_SMARTJOYPLUS_FF #ifdef CONFIG_SMARTJOYPLUS_FF
#include "usbhid/usbhid.h"
struct sjoyff_device { struct sjoyff_device {
struct hid_report *report; struct hid_report *report;
...@@ -57,7 +55,7 @@ static int hid_sjoyff_play(struct input_dev *dev, void *data, ...@@ -57,7 +55,7 @@ static int hid_sjoyff_play(struct input_dev *dev, void *data,
sjoyff->report->field[0]->value[1] = right; sjoyff->report->field[0]->value[1] = right;
sjoyff->report->field[0]->value[2] = left; sjoyff->report->field[0]->value[2] = left;
dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right); dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -115,7 +113,7 @@ static int sjoyff_init(struct hid_device *hid) ...@@ -115,7 +113,7 @@ static int sjoyff_init(struct hid_device *hid)
sjoyff->report->field[0]->value[0] = 0x01; sjoyff->report->field[0]->value[0] = 0x01;
sjoyff->report->field[0]->value[1] = 0x00; sjoyff->report->field[0]->value[1] = 0x00;
sjoyff->report->field[0]->value[2] = 0x00; sjoyff->report->field[0]->value[2] = 0x00;
usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
} }
hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
......
...@@ -16,10 +16,8 @@ ...@@ -16,10 +16,8 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h>
#include "hid-ids.h" #include "hid-ids.h"
#include "usbhid/usbhid.h"
static const struct hid_device_id speedlink_devices[] = { static const struct hid_device_id speedlink_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)}, { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)},
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/module.h> #include <linux/module.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h" #include "hid-ids.h"
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
...@@ -132,7 +131,7 @@ static void steelseries_srws1_set_leds(struct hid_device *hdev, __u16 leds) ...@@ -132,7 +131,7 @@ static void steelseries_srws1_set_leds(struct hid_device *hdev, __u16 leds)
value[14] = 0x00; value[14] = 0x00;
value[15] = 0x00; value[15] = 0x00;
usbhid_submit_report(hdev, report, USB_DIR_OUT); hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
/* Note: LED change does not show on device until the device is read/polled */ /* Note: LED change does not show on device until the device is read/polled */
} }
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h>
#include "hid-ids.h" #include "hid-ids.h"
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include <linux/module.h> #include <linux/module.h>
#include "hid-ids.h" #include "hid-ids.h"
...@@ -46,7 +45,6 @@ static const signed short ff_joystick[] = { ...@@ -46,7 +45,6 @@ static const signed short ff_joystick[] = {
}; };
#ifdef CONFIG_THRUSTMASTER_FF #ifdef CONFIG_THRUSTMASTER_FF
#include "usbhid/usbhid.h"
/* Usages for thrustmaster devices I know about */ /* Usages for thrustmaster devices I know about */
#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb) #define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb)
...@@ -103,7 +101,7 @@ static int tmff_play(struct input_dev *dev, void *data, ...@@ -103,7 +101,7 @@ static int tmff_play(struct input_dev *dev, void *data,
dbg_hid("(x, y)=(%04x, %04x)\n", x, y); dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
ff_field->value[0] = x; ff_field->value[0] = x;
ff_field->value[1] = y; ff_field->value[1] = y;
usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
break; break;
case FF_RUMBLE: case FF_RUMBLE:
...@@ -117,7 +115,7 @@ static int tmff_play(struct input_dev *dev, void *data, ...@@ -117,7 +115,7 @@ static int tmff_play(struct input_dev *dev, void *data,
dbg_hid("(left,right)=(%08x, %08x)\n", left, right); dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
ff_field->value[0] = left; ff_field->value[0] = left;
ff_field->value[1] = right; ff_field->value[1] = right;
usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
break; break;
} }
return 0; return 0;
......
...@@ -24,13 +24,11 @@ ...@@ -24,13 +24,11 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h>
#include <linux/module.h> #include <linux/module.h>
#include "hid-ids.h" #include "hid-ids.h"
#ifdef CONFIG_ZEROPLUS_FF #ifdef CONFIG_ZEROPLUS_FF
#include "usbhid/usbhid.h"
struct zpff_device { struct zpff_device {
struct hid_report *report; struct hid_report *report;
...@@ -59,7 +57,7 @@ static int zpff_play(struct input_dev *dev, void *data, ...@@ -59,7 +57,7 @@ static int zpff_play(struct input_dev *dev, void *data,
zpff->report->field[2]->value[0] = left; zpff->report->field[2]->value[0] = left;
zpff->report->field[3]->value[0] = right; zpff->report->field[3]->value[0] = right;
dbg_hid("running with 0x%02x 0x%02x\n", left, right); dbg_hid("running with 0x%02x 0x%02x\n", left, right);
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);
return 0; return 0;
} }
...@@ -104,7 +102,7 @@ static int zpff_init(struct hid_device *hid) ...@@ -104,7 +102,7 @@ static int zpff_init(struct hid_device *hid)
zpff->report->field[1]->value[0] = 0x02; zpff->report->field[1]->value[0] = 0x02;
zpff->report->field[2]->value[0] = 0x00; zpff->report->field[2]->value[0] = 0x00;
zpff->report->field[3]->value[0] = 0x00; zpff->report->field[3]->value[0] = 0x00;
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);
hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
......
...@@ -563,6 +563,36 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, ...@@ -563,6 +563,36 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
return ret; return ret;
} }
static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
int reqtype)
{
struct i2c_client *client = hid->driver_data;
char *buf;
int ret;
int len = i2c_hid_get_report_length(rep) - 2;
buf = kzalloc(len, GFP_KERNEL);
if (!buf)
return;
switch (reqtype) {
case HID_REQ_GET_REPORT:
ret = i2c_hid_get_raw_report(hid, rep->id, buf, len, rep->type);
if (ret < 0)
dev_err(&client->dev, "%s: unable to get report: %d\n",
__func__, ret);
else
hid_input_report(hid, rep->type, buf, ret, 0);
break;
case HID_REQ_SET_REPORT:
hid_output_report(rep, buf);
i2c_hid_output_raw_report(hid, buf, len, rep->type);
break;
}
kfree(buf);
}
static int i2c_hid_parse(struct hid_device *hid) static int i2c_hid_parse(struct hid_device *hid)
{ {
struct i2c_client *client = hid->driver_data; struct i2c_client *client = hid->driver_data;
...@@ -742,6 +772,7 @@ static struct hid_ll_driver i2c_hid_ll_driver = { ...@@ -742,6 +772,7 @@ static struct hid_ll_driver i2c_hid_ll_driver = {
.open = i2c_hid_open, .open = i2c_hid_open,
.close = i2c_hid_close, .close = i2c_hid_close,
.power = i2c_hid_power, .power = i2c_hid_power,
.request = i2c_hid_request,
.hidinput_input_event = i2c_hid_hidinput_input_event, .hidinput_input_event = i2c_hid_hidinput_input_event,
}; };
......
...@@ -639,7 +639,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re ...@@ -639,7 +639,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
} }
} }
void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) static void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
{ {
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
unsigned long flags; unsigned long flags;
...@@ -648,7 +648,6 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns ...@@ -648,7 +648,6 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
__usbhid_submit_report(hid, report, dir); __usbhid_submit_report(hid, report, dir);
spin_unlock_irqrestore(&usbhid->lock, flags); spin_unlock_irqrestore(&usbhid->lock, flags);
} }
EXPORT_SYMBOL_GPL(usbhid_submit_report);
/* Workqueue routine to send requests to change LEDs */ /* Workqueue routine to send requests to change LEDs */
static void hid_led(struct work_struct *work) static void hid_led(struct work_struct *work)
...@@ -706,7 +705,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un ...@@ -706,7 +705,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un
return 0; return 0;
} }
int usbhid_wait_io(struct hid_device *hid) static int usbhid_wait_io(struct hid_device *hid)
{ {
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
...@@ -720,7 +719,6 @@ int usbhid_wait_io(struct hid_device *hid) ...@@ -720,7 +719,6 @@ int usbhid_wait_io(struct hid_device *hid)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(usbhid_wait_io);
static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
{ {
...@@ -1243,6 +1241,32 @@ static int usbhid_power(struct hid_device *hid, int lvl) ...@@ -1243,6 +1241,32 @@ static int usbhid_power(struct hid_device *hid, int lvl)
return r; return r;
} }
static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int reqtype)
{
switch (reqtype) {
case HID_REQ_GET_REPORT:
usbhid_submit_report(hid, rep, USB_DIR_IN);
break;
case HID_REQ_SET_REPORT:
usbhid_submit_report(hid, rep, USB_DIR_OUT);
break;
}
}
static int usbhid_idle(struct hid_device *hid, int report, int idle,
int reqtype)
{
struct usb_device *dev = hid_to_usb_dev(hid);
struct usb_interface *intf = to_usb_interface(hid->dev.parent);
struct usb_host_interface *interface = intf->cur_altsetting;
int ifnum = interface->desc.bInterfaceNumber;
if (reqtype != HID_REQ_SET_IDLE)
return -EINVAL;
return hid_set_idle(dev, ifnum, report, idle);
}
static struct hid_ll_driver usb_hid_driver = { static struct hid_ll_driver usb_hid_driver = {
.parse = usbhid_parse, .parse = usbhid_parse,
.start = usbhid_start, .start = usbhid_start,
...@@ -1251,6 +1275,9 @@ static struct hid_ll_driver usb_hid_driver = { ...@@ -1251,6 +1275,9 @@ static struct hid_ll_driver usb_hid_driver = {
.close = usbhid_close, .close = usbhid_close,
.power = usbhid_power, .power = usbhid_power,
.hidinput_input_event = usb_hidinput_input_event, .hidinput_input_event = usb_hidinput_input_event,
.request = usbhid_request,
.wait = usbhid_wait_io,
.idle = usbhid_idle,
}; };
static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id)
......
...@@ -263,8 +263,8 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, ...@@ -263,8 +263,8 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
envelope->attack_level, envelope->attack_level,
pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
/* /*
...@@ -290,8 +290,8 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff, ...@@ -290,8 +290,8 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
effect->u.constant.level); effect->u.constant.level);
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
/* /*
...@@ -325,8 +325,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff, ...@@ -325,8 +325,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
pidff->effect_direction); pidff->effect_direction);
pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
/* /*
...@@ -357,8 +357,8 @@ static void pidff_set_periodic_report(struct pidff_device *pidff, ...@@ -357,8 +357,8 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
...@@ -399,8 +399,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff, ...@@ -399,8 +399,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
effect->u.condition[i].left_saturation); effect->u.condition[i].left_saturation);
pidff_set(&pidff->set_condition[PID_DEAD_BAND], pidff_set(&pidff->set_condition[PID_DEAD_BAND],
effect->u.condition[i].deadband); effect->u.condition[i].deadband);
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
} }
...@@ -440,8 +440,8 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff, ...@@ -440,8 +440,8 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
effect->u.ramp.start_level); effect->u.ramp.start_level);
pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
effect->u.ramp.end_level); effect->u.ramp.end_level);
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
/* /*
...@@ -465,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) ...@@ -465,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
int j; int j;
pidff->create_new_effect_type->value[0] = efnum; pidff->create_new_effect_type->value[0] = efnum;
usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
USB_DIR_OUT); HID_REQ_SET_REPORT);
hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum); hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
pidff->block_load_status->value[0] = 0; pidff->block_load_status->value[0] = 0;
usbhid_wait_io(pidff->hid); hid_hw_wait(pidff->hid);
for (j = 0; j < 60; j++) { for (j = 0; j < 60; j++) {
hid_dbg(pidff->hid, "pid_block_load requested\n"); hid_dbg(pidff->hid, "pid_block_load requested\n");
usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
USB_DIR_IN); HID_REQ_GET_REPORT);
usbhid_wait_io(pidff->hid); hid_hw_wait(pidff->hid);
if (pidff->block_load_status->value[0] == if (pidff->block_load_status->value[0] ==
pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
hid_dbg(pidff->hid, "device reported free memory: %d bytes\n", hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
...@@ -513,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) ...@@ -513,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
} }
usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
/** /**
...@@ -535,8 +535,8 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value) ...@@ -535,8 +535,8 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
{ {
pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
/* /*
...@@ -551,7 +551,7 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id) ...@@ -551,7 +551,7 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
effect_id, pidff->pid_id[effect_id]); effect_id, pidff->pid_id[effect_id]);
/* Wait for the queue to clear. We do not want a full fifo to /* Wait for the queue to clear. We do not want a full fifo to
prevent the effect removal. */ prevent the effect removal. */
usbhid_wait_io(pidff->hid); hid_hw_wait(pidff->hid);
pidff_playback_pid(pidff, pid_id, 0); pidff_playback_pid(pidff, pid_id, 0);
pidff_erase_pid(pidff, pid_id); pidff_erase_pid(pidff, pid_id);
...@@ -718,8 +718,8 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain) ...@@ -718,8 +718,8 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain)
struct pidff_device *pidff = dev->ff->private; struct pidff_device *pidff = dev->ff->private;
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
...@@ -744,8 +744,8 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) ...@@ -744,8 +744,8 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
pidff->set_effect[PID_START_DELAY].value[0] = 0; pidff->set_effect[PID_START_DELAY].value[0] = 0;
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
/* /*
...@@ -1158,19 +1158,19 @@ static void pidff_reset(struct pidff_device *pidff) ...@@ -1158,19 +1158,19 @@ static void pidff_reset(struct pidff_device *pidff)
pidff->device_control->value[0] = pidff->control_id[PID_RESET]; pidff->device_control->value[0] = pidff->control_id[PID_RESET];
/* We reset twice as sometimes hid_wait_io isn't waiting long enough */ /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
usbhid_wait_io(hid); hid_hw_wait(hid);
usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
usbhid_wait_io(hid); hid_hw_wait(hid);
pidff->device_control->value[0] = pidff->device_control->value[0] =
pidff->control_id[PID_ENABLE_ACTUATORS]; pidff->control_id[PID_ENABLE_ACTUATORS];
usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
usbhid_wait_io(hid); hid_hw_wait(hid);
/* pool report is sometimes messed up, refetch it */ /* pool report is sometimes messed up, refetch it */
usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
usbhid_wait_io(hid); hid_hw_wait(hid);
if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
...@@ -1181,9 +1181,9 @@ static void pidff_reset(struct pidff_device *pidff) ...@@ -1181,9 +1181,9 @@ static void pidff_reset(struct pidff_device *pidff)
break; break;
} }
hid_dbg(pidff->hid, "pid_pool requested again\n"); hid_dbg(pidff->hid, "pid_pool requested again\n");
usbhid_submit_report(hid, pidff->reports[PID_POOL], hid_hw_request(hid, pidff->reports[PID_POOL],
USB_DIR_IN); HID_REQ_GET_REPORT);
usbhid_wait_io(hid); hid_hw_wait(hid);
} }
} }
} }
...@@ -1269,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid) ...@@ -1269,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid)
if (test_bit(FF_GAIN, dev->ffbit)) { if (test_bit(FF_GAIN, dev->ffbit)) {
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN], hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
USB_DIR_OUT); HID_REQ_SET_REPORT);
} }
error = pidff_check_autocenter(pidff, dev); error = pidff_check_autocenter(pidff, dev);
......
...@@ -705,8 +705,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -705,8 +705,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (report == NULL) if (report == NULL)
break; break;
usbhid_submit_report(hid, report, USB_DIR_IN); hid_hw_request(hid, report, HID_REQ_GET_REPORT);
usbhid_wait_io(hid); hid_hw_wait(hid);
r = 0; r = 0;
break; break;
...@@ -724,8 +724,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -724,8 +724,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (report == NULL) if (report == NULL)
break; break;
usbhid_submit_report(hid, report, USB_DIR_OUT); hid_hw_request(hid, report, HID_REQ_SET_REPORT);
usbhid_wait_io(hid); hid_hw_wait(hid);
r = 0; r = 0;
break; break;
......
...@@ -34,12 +34,9 @@ ...@@ -34,12 +34,9 @@
#include <linux/input.h> #include <linux/input.h>
/* API provided by hid-core.c for USB HID drivers */ /* API provided by hid-core.c for USB HID drivers */
int usbhid_wait_io(struct hid_device* hid);
void usbhid_close(struct hid_device *hid); void usbhid_close(struct hid_device *hid);
int usbhid_open(struct hid_device *hid); int usbhid_open(struct hid_device *hid);
void usbhid_init_reports(struct hid_device *hid); void usbhid_init_reports(struct hid_device *hid);
void usbhid_submit_report
(struct hid_device *hid, struct hid_report *report, unsigned char dir);
int usbhid_get_power(struct hid_device *hid); int usbhid_get_power(struct hid_device *hid);
void usbhid_put_power(struct hid_device *hid); void usbhid_put_power(struct hid_device *hid);
struct usb_interface *usbhid_find_interface(int minor); struct usb_interface *usbhid_find_interface(int minor);
......
...@@ -22,11 +22,12 @@ ...@@ -22,11 +22,12 @@
* *
*/ */
#define HID_DEBUG_BUFSIZE 512
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
#define HID_DEBUG_BUFSIZE 512
void hid_dump_input(struct hid_device *, struct hid_usage *, __s32); void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
void hid_dump_report(struct hid_device *, int , u8 *, int);
void hid_dump_device(struct hid_device *, struct seq_file *); void hid_dump_device(struct hid_device *, struct seq_file *);
void hid_dump_field(struct hid_field *, int, struct seq_file *); void hid_dump_field(struct hid_field *, int, struct seq_file *);
char *hid_resolv_usage(unsigned, struct seq_file *); char *hid_resolv_usage(unsigned, struct seq_file *);
...@@ -50,6 +51,7 @@ struct hid_debug_list { ...@@ -50,6 +51,7 @@ struct hid_debug_list {
#else #else
#define hid_dump_input(a,b,c) do { } while (0) #define hid_dump_input(a,b,c) do { } while (0)
#define hid_dump_report(a,b,c,d) do { } while (0)
#define hid_dump_device(a,b) do { } while (0) #define hid_dump_device(a,b) do { } while (0)
#define hid_dump_field(a,b,c) do { } while (0) #define hid_dump_field(a,b,c) do { } while (0)
#define hid_resolv_usage(a,b) do { } while (0) #define hid_resolv_usage(a,b) do { } while (0)
......
...@@ -456,7 +456,8 @@ struct hid_device { /* device report descriptor */ ...@@ -456,7 +456,8 @@ struct hid_device { /* device report descriptor */
unsigned country; /* HID country */ unsigned country; /* HID country */
struct hid_report_enum report_enum[HID_REPORT_TYPES]; struct hid_report_enum report_enum[HID_REPORT_TYPES];
struct semaphore driver_lock; /* protects the current driver */ struct semaphore driver_lock; /* protects the current driver, except during input */
struct semaphore driver_input_lock; /* protects the current driver */
struct device dev; /* device */ struct device dev; /* device */
struct hid_driver *driver; struct hid_driver *driver;
struct hid_ll_driver *ll_driver; struct hid_ll_driver *ll_driver;
...@@ -477,6 +478,7 @@ struct hid_device { /* device report descriptor */ ...@@ -477,6 +478,7 @@ struct hid_device { /* device report descriptor */
unsigned int status; /* see STAT flags above */ unsigned int status; /* see STAT flags above */
unsigned claimed; /* Claimed by hidinput, hiddev? */ unsigned claimed; /* Claimed by hidinput, hiddev? */
unsigned quirks; /* Various quirks the device can pull on us */ unsigned quirks; /* Various quirks the device can pull on us */
bool io_started; /* Protected by driver_lock. If IO has started */
struct list_head inputs; /* The list of inputs */ struct list_head inputs; /* The list of inputs */
void *hiddev; /* The hiddev structure */ void *hiddev; /* The hiddev structure */
...@@ -512,6 +514,7 @@ struct hid_device { /* device report descriptor */ ...@@ -512,6 +514,7 @@ struct hid_device { /* device report descriptor */
struct dentry *debug_rdesc; struct dentry *debug_rdesc;
struct dentry *debug_events; struct dentry *debug_events;
struct list_head debug_list; struct list_head debug_list;
struct mutex debug_list_lock;
wait_queue_head_t debug_wait; wait_queue_head_t debug_wait;
}; };
...@@ -599,6 +602,10 @@ struct hid_usage_id { ...@@ -599,6 +602,10 @@ struct hid_usage_id {
* @resume: invoked on resume if device was not reset (NULL means nop) * @resume: invoked on resume if device was not reset (NULL means nop)
* @reset_resume: invoked on resume if device was reset (NULL means nop) * @reset_resume: invoked on resume if device was reset (NULL means nop)
* *
* probe should return -errno on error, or 0 on success. During probe,
* input will not be passed to raw_event unless hid_device_io_start is
* called.
*
* raw_event and event should return 0 on no action performed, 1 when no * raw_event and event should return 0 on no action performed, 1 when no
* further processing should be done and negative on error * further processing should be done and negative on error
* *
...@@ -662,6 +669,9 @@ struct hid_driver { ...@@ -662,6 +669,9 @@ struct hid_driver {
* @hidinput_input_event: event input event (e.g. ff or leds) * @hidinput_input_event: event input event (e.g. ff or leds)
* @parse: this method is called only once to parse the device data, * @parse: this method is called only once to parse the device data,
* shouldn't allocate anything to not leak memory * shouldn't allocate anything to not leak memory
* @request: send report request to device (e.g. feature report)
* @wait: wait for buffered io to complete (send/recv reports)
* @idle: send idle request to device
*/ */
struct hid_ll_driver { struct hid_ll_driver {
int (*start)(struct hid_device *hdev); int (*start)(struct hid_device *hdev);
...@@ -676,6 +686,13 @@ struct hid_ll_driver { ...@@ -676,6 +686,13 @@ struct hid_ll_driver {
unsigned int code, int value); unsigned int code, int value);
int (*parse)(struct hid_device *hdev); int (*parse)(struct hid_device *hdev);
void (*request)(struct hid_device *hdev,
struct hid_report *report, int reqtype);
int (*wait)(struct hid_device *hdev);
int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
}; };
#define PM_HINT_FULLON 1<<5 #define PM_HINT_FULLON 1<<5
...@@ -737,6 +754,44 @@ const struct hid_device_id *hid_match_id(struct hid_device *hdev, ...@@ -737,6 +754,44 @@ const struct hid_device_id *hid_match_id(struct hid_device *hdev,
const struct hid_device_id *id); const struct hid_device_id *id);
s32 hid_snto32(__u32 value, unsigned n); s32 hid_snto32(__u32 value, unsigned n);
/**
* hid_device_io_start - enable HID input during probe, remove
*
* @hid - the device
*
* This should only be called during probe or remove and only be
* called by the thread calling probe or remove. It will allow
* incoming packets to be delivered to the driver.
*/
static inline void hid_device_io_start(struct hid_device *hid) {
if (hid->io_started) {
dev_warn(&hid->dev, "io already started");
return;
}
hid->io_started = true;
up(&hid->driver_input_lock);
}
/**
* hid_device_io_stop - disable HID input during probe, remove
*
* @hid - the device
*
* Should only be called after hid_device_io_start. It will prevent
* incoming packets from going to the driver for the duration of
* probe, remove. If called during probe, packets will still go to the
* driver after probe is complete. This function should only be called
* by the thread calling probe or remove.
*/
static inline void hid_device_io_stop(struct hid_device *hid) {
if (!hid->io_started) {
dev_warn(&hid->dev, "io already stopped");
return;
}
hid->io_started = false;
down(&hid->driver_input_lock);
}
/** /**
* hid_map_usage - map usage input bits * hid_map_usage - map usage input bits
* *
...@@ -883,6 +938,49 @@ static inline int hid_hw_power(struct hid_device *hdev, int level) ...@@ -883,6 +938,49 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0; return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
} }
/**
* hid_hw_request - send report request to device
*
* @hdev: hid device
* @report: report to send
* @reqtype: hid request type
*/
static inline void hid_hw_request(struct hid_device *hdev,
struct hid_report *report, int reqtype)
{
if (hdev->ll_driver->request)
hdev->ll_driver->request(hdev, report, reqtype);
}
/**
* hid_hw_idle - send idle request to device
*
* @hdev: hid device
* @report: report to control
* @idle: idle state
* @reqtype: hid request type
*/
static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle,
int reqtype)
{
if (hdev->ll_driver->idle)
return hdev->ll_driver->idle(hdev, report, idle, reqtype);
return 0;
}
/**
* hid_hw_wait - wait for buffered io to complete
*
* @hdev: hid device
*/
static inline void hid_hw_wait(struct hid_device *hdev)
{
if (hdev->ll_driver->wait)
hdev->ll_driver->wait(hdev);
}
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
int interrupt); int interrupt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment