diff options
Diffstat (limited to 'drivers/hid')
63 files changed, 2825 insertions, 1298 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 3052e2969ad..24cca2f69df 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -150,11 +150,22 @@ config DRAGONRISE_FF Say Y here if you want to enable force feedback support for DragonRise Inc. game controllers. +config HID_EMS_FF + tristate "EMS Production Inc. force feedback support" + depends on USB_HID + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you want to enable force feedback support for devices by + EMS Production Ltd. + Currently the following devices are known to be supported: + - Trio Linker Plus II + config HID_EGALAX tristate "eGalax multi-touch panel" depends on USB_HID ---help--- - Support for the eGalax dual-touch panel. + Support for the eGalax dual-touch panels, including the + Joojoo and Wetab tablets. config HID_ELECOM tristate "ELECOM BM084 bluetooth mouse" @@ -284,6 +295,23 @@ config HID_MONTEREY ---help--- Support for Monterey Genius KB29E. +config HID_MULTITOUCH + tristate "HID Multitouch panels" + depends on USB_HID + ---help--- + Generic support for HID multitouch panels. + + Say Y here if you have one of the following devices: + - Cypress TrueTouch panels + - Hanvon dual touch panels + - Pixcir dual touch panels + - 'Sensing Win7-TwoFinger' panel by GeneralTouch + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called hid-multitouch. + config HID_NTRIG tristate "N-Trig touch screen" depends on USB_HID @@ -396,6 +424,13 @@ config HID_ROCCAT_KONE ---help--- Support for Roccat Kone mouse. +config HID_ROCCAT_KONEPLUS + tristate "Roccat Kone[+] mouse support" + depends on USB_HID + select HID_ROCCAT + ---help--- + Support for Roccat Kone[+] mouse. + config HID_ROCCAT_PYRA tristate "Roccat Pyra mouse support" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index c335605b920..6efc2a0370a 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -1,7 +1,7 @@ # # Makefile for the HID driver # -hid-objs := hid-core.o hid-input.o +hid-y := hid-core.o hid-input.o ifdef CONFIG_DEBUG_FS hid-objs += hid-debug.o @@ -11,18 +11,18 @@ obj-$(CONFIG_HID) += hid.o hid-$(CONFIG_HIDRAW) += hidraw.o -hid-logitech-objs := hid-lg.o +hid-logitech-y := hid-lg.o ifdef CONFIG_LOGITECH_FF - hid-logitech-objs += hid-lgff.o + hid-logitech-y += hid-lgff.o endif ifdef CONFIG_LOGIRUMBLEPAD2_FF - hid-logitech-objs += hid-lg2ff.o + hid-logitech-y += hid-lg2ff.o endif ifdef CONFIG_LOGIG940_FF - hid-logitech-objs += hid-lg3ff.o + hid-logitech-y += hid-lg3ff.o endif ifdef CONFIG_LOGIWII_FF - hid-logitech-objs += hid-lg4ff.o + hid-logitech-y += hid-lg4ff.o endif obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o @@ -35,6 +35,7 @@ obj-$(CONFIG_HID_CHERRY) += hid-cherry.o obj-$(CONFIG_HID_CHICONY) += hid-chicony.o obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o +obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o obj-$(CONFIG_HID_EGALAX) += hid-egalax.o obj-$(CONFIG_HID_ELECOM) += hid-elecom.o obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o @@ -46,6 +47,7 @@ obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MOSART) += hid-mosart.o +obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o obj-$(CONFIG_HID_ORTEK) += hid-ortek.o obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o @@ -55,6 +57,7 @@ obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o +obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c index 02d8cd3b1b1..5243ae2d373 100644 --- a/drivers/hid/hid-3m-pct.c +++ b/drivers/hid/hid-3m-pct.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/usb.h> +#include <linux/input/mt.h> MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); MODULE_DESCRIPTION("3M PCT multitouch panels"); @@ -27,8 +28,6 @@ MODULE_LICENSE("GPL"); #include "hid-ids.h" #define MAX_SLOTS 60 -#define MAX_TRKID USHRT_MAX -#define MAX_EVENTS 360 /* estimated signal-to-noise ratios */ #define SN_MOVE 2048 @@ -36,14 +35,11 @@ MODULE_LICENSE("GPL"); struct mmm_finger { __s32 x, y, w, h; - __u16 id; - bool prev_touch; bool touch, valid; }; struct mmm_data { struct mmm_finger f[MAX_SLOTS]; - __u16 id; __u8 curid; __u8 nexp, nreal; bool touch, valid; @@ -117,14 +113,7 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, 0, 1, 0, 0); return 1; case HID_DG_CONTACTID: - field->logical_maximum = MAX_TRKID; - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - input_set_abs_params(hi->input, ABS_MT_TRACKING_ID, - 0, MAX_TRKID, 0, 0); - if (!hi->input->mt) - input_mt_create_slots(hi->input, MAX_SLOTS); - input_set_events_per_packet(hi->input, MAX_EVENTS); + input_mt_init_slots(hi->input, MAX_SLOTS); return 1; } /* let hid-input decide for the others */ @@ -154,7 +143,6 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, */ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) { - struct mmm_finger *oldest = 0; int i; for (i = 0; i < MAX_SLOTS; ++i) { struct mmm_finger *f = &md->f[i]; @@ -163,6 +151,7 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) continue; } input_mt_slot(input, i); + input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch); if (f->touch) { /* this finger is on the screen */ int wide = (f->w > f->h); @@ -170,33 +159,16 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) int major = max(f->w, f->h) >> 1; int minor = min(f->w, f->h) >> 1; - if (!f->prev_touch) - f->id = md->id++; - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id); input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); - /* touchscreen emulation: pick the oldest contact */ - if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1))) - oldest = f; - } else { - /* this finger took off the screen */ - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1); } - f->prev_touch = f->touch; f->valid = 0; } - /* touchscreen emulation */ - if (oldest) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - input_event(input, EV_ABS, ABS_X, oldest->x); - input_event(input, EV_ABS, ABS_Y, oldest->y); - } else { - input_event(input, EV_KEY, BTN_TOUCH, 0); - } + input_mt_report_pointer_emulation(input, true); input_sync(input); } @@ -274,7 +246,7 @@ static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id) md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); if (!md) { - dev_err(&hdev->dev, "cannot allocate 3M data\n"); + hid_err(hdev, "cannot allocate 3M data\n"); return -ENOMEM; } hid_set_drvdata(hdev, md); diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c index 1666c1684e7..902d1dfeb1b 100644 --- a/drivers/hid/hid-a4tech.c +++ b/drivers/hid/hid-a4tech.c @@ -93,7 +93,7 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id) a4 = kzalloc(sizeof(*a4), GFP_KERNEL); if (a4 == NULL) { - dev_err(&hdev->dev, "can't alloc device descriptor\n"); + hid_err(hdev, "can't alloc device descriptor\n"); ret = -ENOMEM; goto err_free; } @@ -104,13 +104,13 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index eaeca564a8d..61aa7123339 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -16,6 +16,8 @@ * any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/device.h> #include <linux/hid.h> #include <linux/module.h> @@ -59,6 +61,27 @@ struct apple_key_translation { u8 flags; }; +static const struct apple_key_translation macbookair_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, + { KEY_ENTER, KEY_INSERT }, + { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, + { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, + { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, + { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, + { KEY_F6, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, + { KEY_F7, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, + { KEY_F8, KEY_NEXTSONG, APPLE_FLAG_FKEY }, + { KEY_F9, KEY_MUTE, APPLE_FLAG_FKEY }, + { KEY_F10, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, + { KEY_F11, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, + { KEY_F12, KEY_EJECTCD, APPLE_FLAG_FKEY }, + { KEY_UP, KEY_PAGEUP }, + { KEY_DOWN, KEY_PAGEDOWN }, + { KEY_LEFT, KEY_HOME }, + { KEY_RIGHT, KEY_END }, + { } +}; + static const struct apple_key_translation apple_fn_keys[] = { { KEY_BACKSPACE, KEY_DELETE }, { KEY_ENTER, KEY_INSERT }, @@ -146,7 +169,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, struct hid_usage *usage, __s32 value) { struct apple_sc *asc = hid_get_drvdata(hid); - const struct apple_key_translation *trans; + const struct apple_key_translation *trans, *table; if (usage->code == KEY_FN) { asc->fn_on = !!value; @@ -157,10 +180,16 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, if (fnmode) { int do_translate; - trans = apple_find_translation((hid->product < 0x21d || - hid->product >= 0x300) ? - powerbook_fn_keys : apple_fn_keys, - usage->code); + if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) + table = macbookair_fn_keys; + else if (hid->product < 0x21d || hid->product >= 0x300) + table = powerbook_fn_keys; + else + table = apple_fn_keys; + + trans = apple_find_translation (table, usage->code); + if (trans) { if (test_bit(usage->code, asc->pressed_fn)) do_translate = 1; @@ -253,8 +282,8 @@ static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && rdesc[53] == 0x65 && rdesc[59] == 0x65) { - dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report " - "descriptor\n"); + hid_info(hdev, + "fixing up MacBook JIS keyboard report descriptor\n"); rdesc[53] = rdesc[59] = 0xe7; } return rdesc; @@ -324,7 +353,7 @@ static int apple_probe(struct hid_device *hdev, asc = kzalloc(sizeof(*asc), GFP_KERNEL); if (asc == NULL) { - dev_err(&hdev->dev, "can't alloc apple descriptor\n"); + hid_err(hdev, "can't alloc apple descriptor\n"); return -ENOMEM; } @@ -334,7 +363,7 @@ static int apple_probe(struct hid_device *hdev, ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } @@ -345,7 +374,7 @@ static int apple_probe(struct hid_device *hdev, ret = hid_hw_start(hdev, connect_mask); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } @@ -440,6 +469,18 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), @@ -473,7 +514,7 @@ static int __init apple_init(void) ret = hid_register_driver(&apple_driver); if (ret) - printk(KERN_ERR "can't register apple driver\n"); + pr_err("can't register apple driver\n"); return ret; } diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index f42ee140738..e5b961d6ff2 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c @@ -73,14 +73,14 @@ static int axff_init(struct hid_device *hid) int error; if (list_empty(report_list)) { - dev_err(&hid->dev, "no output reports found\n"); + hid_err(hid, "no output reports found\n"); return -ENODEV; } report = list_first_entry(report_list, struct hid_report, list); if (report->maxfield < 4) { - dev_err(&hid->dev, "no fields in the report: %d\n", report->maxfield); + hid_err(hid, "no fields in the report: %d\n", report->maxfield); return -ENODEV; } @@ -101,7 +101,7 @@ static int axff_init(struct hid_device *hid) axff->report->field[3]->value[0] = 0x00; usbhid_submit_report(hid, axff->report, USB_DIR_OUT); - dev_info(&hid->dev, "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"); return 0; @@ -114,17 +114,17 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) { int error; - dev_dbg(&hdev->dev, "ACRUX HID hardware probe..."); + dev_dbg(&hdev->dev, "ACRUX HID hardware probe...\n"); error = hid_parse(hdev); if (error) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); return error; } error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (error) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); return error; } @@ -134,7 +134,7 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) * Do not fail device initialization completely as device * may still be partially operable, just warn. */ - dev_warn(&hdev->dev, + hid_warn(hdev, "Failed to enable force feedback support, error: %d\n", error); } diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c index 4ce7aa3a519..a1a765a5b08 100644 --- a/drivers/hid/hid-belkin.c +++ b/drivers/hid/hid-belkin.c @@ -56,14 +56,14 @@ static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0)); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c index 5925bdcd417..1ea066c5520 100644 --- a/drivers/hid/hid-cando.c +++ b/drivers/hid/hid-cando.c @@ -207,7 +207,7 @@ static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id) td = kmalloc(sizeof(struct cando_data), GFP_KERNEL); if (!td) { - dev_err(&hdev->dev, "cannot allocate Cando Touch data\n"); + hid_err(hdev, "cannot allocate Cando Touch data\n"); return -ENOMEM; } hid_set_drvdata(hdev, td); @@ -236,6 +236,8 @@ static const struct hid_device_id cando_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, + USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index e880086c231..888ece68a47 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c @@ -30,8 +30,7 @@ static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { - dev_info(&hdev->dev, "fixing up Cherry Cymotion report " - "descriptor\n"); + hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n"); rdesc[11] = rdesc[16] = 0xff; rdesc[12] = rdesc[17] = 0x03; } diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 88cb04e7962..d678cf3d33d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -14,6 +14,8 @@ * any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> @@ -59,7 +61,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, if (report_enum->report_id_hash[id]) return report_enum->report_id_hash[id]; - if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL))) + report = kzalloc(sizeof(struct hid_report), GFP_KERNEL); + if (!report) return NULL; if (id != 0) @@ -90,8 +93,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned return NULL; } - if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) - + values * sizeof(unsigned), GFP_KERNEL))) return NULL; + field = kzalloc((sizeof(struct hid_field) + + usages * sizeof(struct hid_usage) + + values * sizeof(unsigned)), GFP_KERNEL); + if (!field) + return NULL; field->index = report->maxfield++; report->field[field->index] = field; @@ -172,10 +178,14 @@ static int close_collection(struct hid_parser *parser) static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) { + struct hid_collection *collection = parser->device->collection; int n; - for (n = parser->collection_stack_ptr - 1; n >= 0; n--) - if (parser->device->collection[parser->collection_stack[n]].type == type) - return parser->device->collection[parser->collection_stack[n]].usage; + + for (n = parser->collection_stack_ptr - 1; n >= 0; n--) { + unsigned index = parser->collection_stack[n]; + if (collection[index].type == type) + return collection[index].usage; + } return 0; /* we know nothing about this usage type */ } @@ -209,7 +219,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign unsigned offset; int i; - if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { + report = hid_register_report(parser->device, report_type, parser->global.report_id); + if (!report) { dbg_hid("hid_register_report failed\n"); return -1; } @@ -227,7 +238,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign usages = max_t(int, parser->local.usage_index, parser->global.report_count); - if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) + field = hid_register_field(report, usages, parser->global.report_count); + if (!field) return 0; field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); @@ -652,13 +664,12 @@ int hid_parse_report(struct hid_device *device, __u8 *start, return -ENOMEM; device->rsize = size; - parser = vmalloc(sizeof(struct hid_parser)); + parser = vzalloc(sizeof(struct hid_parser)); if (!parser) { ret = -ENOMEM; goto err; } - memset(parser, 0, sizeof(struct hid_parser)); parser->device = device; end = start + size; @@ -672,7 +683,8 @@ int hid_parse_report(struct hid_device *device, __u8 *start, if (dispatch_type[item.type](parser, &item)) { dbg_hid("item %u %u %u %u parsing failed\n", - item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); + item.format, (unsigned)item.size, + (unsigned)item.type, (unsigned)item.tag); goto err; } @@ -737,13 +749,14 @@ static u32 s32ton(__s32 value, unsigned n) * Search linux-kernel and linux-usb-devel archives for "hid-core extract". */ -static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) +static __u32 extract(const struct hid_device *hid, __u8 *report, + unsigned offset, unsigned n) { u64 x; if (n > 32) - printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n", - n, current->comm); + hid_warn(hid, "extract() called with n (%d) > 32! (%s)\n", + n, current->comm); report += offset >> 3; /* adjust byte index */ offset &= 7; /* now only need bit offset into one byte */ @@ -760,18 +773,19 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) * endianness of register values by considering a register * a "cached" copy of the little endiad bit stream. */ -static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) +static void implement(const struct hid_device *hid, __u8 *report, + unsigned offset, unsigned n, __u32 value) { u64 x; u64 m = (1ULL << n) - 1; if (n > 32) - printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n", - n, current->comm); + hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", + __func__, n, current->comm); if (value > m) - printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n", - value, current->comm); + hid_warn(hid, "%s() called with too large value %d! (%s)\n", + __func__, value, current->comm); WARN_ON(value > m); value &= m; @@ -788,7 +802,7 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3 * Search an array for a value. */ -static __inline__ int search(__s32 *array, __s32 value, unsigned n) +static int search(__s32 *array, __s32 value, unsigned n) { while (n--) { if (*array++ == value) @@ -887,18 +901,22 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __s32 max = field->logical_maximum; __s32 *value; - if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC))) + value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC); + if (!value) return; for (n = 0; n < count; n++) { - value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : - extract(data, offset + n * size, size); + value[n] = min < 0 ? + snto32(extract(hid, data, offset + n * size, size), + size) : + extract(hid, data, offset + n * size, size); - if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */ - && value[n] >= min && value[n] <= max - && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) - goto exit; + /* Ignore report if ErrorRollOver */ + if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && + value[n] >= min && value[n] <= max && + field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) + goto exit; } for (n = 0; n < count; n++) { @@ -928,7 +946,8 @@ exit: * Output the field into the report. */ -static void hid_output_field(struct hid_field *field, __u8 *data) +static void hid_output_field(const struct hid_device *hid, + struct hid_field *field, __u8 *data) { unsigned count = field->report_count; unsigned offset = field->report_offset; @@ -937,9 +956,11 @@ static void hid_output_field(struct hid_field *field, __u8 *data) for (n = 0; n < count; n++) { if (field->logical_minimum < 0) /* signed values */ - implement(data, offset + n * size, size, s32ton(field->value[n], size)); + implement(hid, data, offset + n * size, size, + s32ton(field->value[n], size)); else /* unsigned values */ - implement(data, offset + n * size, size, field->value[n]); + implement(hid, data, offset + n * size, size, + field->value[n]); } } @@ -956,7 +977,7 @@ void hid_output_report(struct hid_report *report, __u8 *data) memset(data, 0, ((report->size - 1) >> 3) + 1); for (n = 0; n < report->maxfield; n++) - hid_output_field(report->field[n], data); + hid_output_field(report->device, report->field[n], data); } EXPORT_SYMBOL_GPL(hid_output_report); @@ -1169,8 +1190,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) hdev->claimed |= HID_CLAIMED_HIDRAW; if (!hdev->claimed) { - dev_err(&hdev->dev, "claimed by neither input, hiddev nor " - "hidraw\n"); + hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n"); return -ENODEV; } @@ -1210,9 +1230,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) bus = "<UNKNOWN>"; } - dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n", - buf, bus, hdev->version >> 8, hdev->version & 0xff, - type, hdev->name, hdev->phys); + hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n", + buf, bus, hdev->version >> 8, hdev->version & 0xff, + type, hdev->name, hdev->phys); return 0; } @@ -1230,7 +1250,7 @@ void hid_disconnect(struct hid_device *hdev) EXPORT_SYMBOL_GPL(hid_disconnect); /* a list of devices for which there is a specialized driver on HID bus */ -static const struct hid_device_id hid_blacklist[] = { +static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, @@ -1276,6 +1296,12 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -1286,29 +1312,39 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, + { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, @@ -1369,6 +1405,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, @@ -1390,6 +1427,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, @@ -1496,9 +1534,9 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv) if (!hid_match_device(hdev, hdrv)) return 0; - /* generic wants all non-blacklisted */ + /* generic wants all that don't have specialized driver */ if (!strncmp(hdrv->name, "generic-", 8)) - return !hid_match_id(hdev, hid_blacklist); + return !hid_match_id(hdev, hid_have_special_driver); return 1; } @@ -1604,10 +1642,10 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, @@ -1757,6 +1795,12 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } @@ -1948,12 +1992,12 @@ static int __init hid_init(void) int ret; if (hid_debug) - printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n" - "HID: debugfs is now used for inspecting the device (report descriptor, reports)\n"); + pr_warn("hid_debug is now used solely for parser and driver debugging.\n" + "debugfs is now used for inspecting the device (report descriptor, reports)\n"); ret = bus_register(&hid_bus_type); if (ret) { - printk(KERN_ERR "HID: can't register hid bus\n"); + pr_err("can't register hid bus\n"); goto err; } diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 4cd0e234599..2f0be4c66af 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -107,13 +107,13 @@ static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 75c5e23d09d..555382fc741 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -26,6 +26,8 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/sched.h> @@ -393,7 +395,7 @@ char *hid_resolv_usage(unsigned usage, struct seq_file *f) { buf = resolv_usage_page(usage >> 16, f); if (IS_ERR(buf)) { - printk(KERN_ERR "error allocating HID debug buffer\n"); + pr_err("error allocating HID debug buffer\n"); return NULL; } diff --git a/drivers/hid/hid-drff.c b/drivers/hid/hid-drff.c index 968b04f9b79..afcf3d67eb0 100644 --- a/drivers/hid/hid-drff.c +++ b/drivers/hid/hid-drff.c @@ -96,18 +96,18 @@ static int drff_init(struct hid_device *hid) int error; if (list_empty(report_list)) { - dev_err(&hid->dev, "no output reports found\n"); + hid_err(hid, "no output reports found\n"); return -ENODEV; } report = list_first_entry(report_list, struct hid_report, list); if (report->maxfield < 1) { - dev_err(&hid->dev, "no fields in the report\n"); + hid_err(hid, "no fields in the report\n"); return -ENODEV; } if (report->field[0]->report_count < 7) { - dev_err(&hid->dev, "not enough values in the field\n"); + hid_err(hid, "not enough values in the field\n"); return -ENODEV; } @@ -133,8 +133,8 @@ static int drff_init(struct hid_device *hid) drff->report->field[0]->value[6] = 0x00; usbhid_submit_report(hid, drff->report, USB_DIR_OUT); - dev_info(&hid->dev, "Force Feedback for DragonRise Inc. game " - "controllers by Richard Walmsley <richwalm@gmail.com>\n"); + hid_info(hid, "Force Feedback for DragonRise Inc. " + "game controllers by Richard Walmsley <richwalm@gmail.com>\n"); return 0; } @@ -153,13 +153,13 @@ static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err; } diff --git a/drivers/hid/hid-egalax.c b/drivers/hid/hid-egalax.c index 5a1b52e0eb8..03bee1970d7 100644 --- a/drivers/hid/hid-egalax.c +++ b/drivers/hid/hid-egalax.c @@ -2,6 +2,8 @@ * HID driver for eGalax dual-touch panels * * Copyright (c) 2010 Stephane Chatty <chatty@enac.fr> + * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> + * Copyright (c) 2010 Canonical, Ltd. * */ @@ -16,6 +18,7 @@ #include <linux/hid.h> #include <linux/module.h> #include <linux/usb.h> +#include <linux/input/mt.h> #include <linux/slab.h> #include "usbhid/usbhid.h" @@ -25,38 +28,53 @@ MODULE_LICENSE("GPL"); #include "hid-ids.h" +#define MAX_SLOTS 2 + +/* estimated signal-to-noise ratios */ +#define SN_MOVE 4096 +#define SN_PRESSURE 32 + struct egalax_data { - __u16 x, y, z; - __u8 id; - bool first; /* is this the first finger in the frame? */ - bool valid; /* valid finger data, or just placeholder? */ - bool activity; /* at least one active finger previously? */ - __u16 lastx, lasty, lastz; /* latest valid (x, y, z) in the frame */ + int valid; + int slot; + int touch; + int x, y, z; }; +static void set_abs(struct input_dev *input, unsigned int code, + struct hid_field *field, int snratio) +{ + int fmin = field->logical_minimum; + int fmax = field->logical_maximum; + int fuzz = snratio ? (fmax - fmin) / snratio : 0; + input_set_abs_params(input, code, fmin, fmax, fuzz, 0); +} + static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { + struct input_dev *input = hi->input; + switch (usage->hid & HID_USAGE_PAGE) { case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: + field->logical_maximum = 32760; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_X); + set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE); /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); + set_abs(input, ABS_X, field, SN_MOVE); return 1; case HID_GD_Y: + field->logical_maximum = 32760; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_Y); + set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE); /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); + set_abs(input, ABS_Y, field, SN_MOVE); return 1; } return 0; @@ -66,6 +84,7 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_DG_TIPSWITCH: /* touchscreen emulation */ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); + input_set_capability(input, EV_KEY, BTN_TOUCH); return 1; case HID_DG_INRANGE: case HID_DG_CONFIDENCE: @@ -73,16 +92,15 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_DG_CONTACTMAX: return -1; case HID_DG_CONTACTID: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); + input_mt_init_slots(input, MAX_SLOTS); return 1; case HID_DG_TIPPRESSURE: + field->logical_minimum = 0; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE); + set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE); /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_PRESSURE, - field->logical_minimum, - field->logical_maximum, 0, 0); + set_abs(input, ABS_PRESSURE, field, SN_PRESSURE); return 1; } return 0; @@ -96,10 +114,10 @@ static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { + /* tell hid-input to skip setup of these event types */ if (usage->type == EV_KEY || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; + set_bit(usage->type, hi->input->evbit); + return -1; } /* @@ -108,58 +126,16 @@ static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi, */ static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) { - td->first = !td->first; /* touchscreen emulation */ - - if (td->valid) { - /* emit multitouch events */ - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); - input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3); + input_mt_slot(input, td->slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch); + if (td->touch) { + input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); + input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z); - - input_mt_sync(input); - - /* - * touchscreen emulation: store (x, y) as - * the last valid values in this frame - */ - td->lastx = td->x; - td->lasty = td->y; - td->lastz = td->z; - } - - /* - * touchscreen emulation: if this is the second finger and at least - * one in this frame is valid, the latest valid in the frame is - * the oldest on the panel, the one we want for single touch - */ - if (!td->first && td->activity) { - input_event(input, EV_ABS, ABS_X, td->lastx >> 3); - input_event(input, EV_ABS, ABS_Y, td->lasty >> 3); - input_event(input, EV_ABS, ABS_PRESSURE, td->lastz); - } - - if (!td->valid) { - /* - * touchscreen emulation: if the first finger is invalid - * and there previously was finger activity, this is a release - */ - if (td->first && td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 0); - td->activity = false; - } - return; - } - - - /* touchscreen emulation: if no previous activity, emit touch event */ - if (!td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - td->activity = true; } + input_mt_report_pointer_emulation(input, true); } - static int egalax_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { @@ -169,25 +145,26 @@ static int egalax_event(struct hid_device *hid, struct hid_field *field, * uses a standard parallel multitouch protocol (product ID == * 48xx). The second is capacitive and uses an unusual "serial" * protocol with a different message for each multitouch finger - * (product ID == 72xx). We do not yet generate a correct event - * sequence for the capacitive/serial protocol. + * (product ID == 72xx). */ if (hid->claimed & HID_CLAIMED_INPUT) { struct input_dev *input = field->hidinput->input; switch (usage->hid) { case HID_DG_INRANGE: + td->valid = value; + break; case HID_DG_CONFIDENCE: /* avoid interference from generic hidinput handling */ break; case HID_DG_TIPSWITCH: - td->valid = value; + td->touch = value; break; case HID_DG_TIPPRESSURE: td->z = value; break; case HID_DG_CONTACTID: - td->id = value; + td->slot = clamp_val(value, 0, MAX_SLOTS - 1); break; case HID_GD_X: td->x = value; @@ -195,11 +172,11 @@ static int egalax_event(struct hid_device *hid, struct hid_field *field, case HID_GD_Y: td->y = value; /* this is the last field in a finger */ - egalax_filter_event(td, input); + if (td->valid) + egalax_filter_event(td, input); break; case HID_DG_CONTACTCOUNT: /* touch emulation: this is the last field in a frame */ - td->first = false; break; default: @@ -223,7 +200,7 @@ static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id) td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL); if (!td) { - dev_err(&hdev->dev, "cannot allocate eGalax data\n"); + hid_err(hdev, "cannot allocate eGalax data\n"); return -ENOMEM; } hid_set_drvdata(hdev, td); @@ -261,6 +238,12 @@ static const struct hid_device_id egalax_devices[] = { USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, { } }; MODULE_DEVICE_TABLE(hid, egalax_devices); diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index 6e31f305397..79d0c61e721 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c @@ -24,8 +24,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { - dev_info(&hdev->dev, "Fixing up Elecom BM084 " - "report descriptor.\n"); + hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); rdesc[47] = 0x00; } return rdesc; diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c new file mode 100644 index 00000000000..81877c67cae --- /dev/null +++ b/drivers/hid/hid-emsff.c @@ -0,0 +1,161 @@ +/* + * Force feedback support for EMS Trio Linker Plus II + * + * Copyright (c) 2010 Ignaz Forster <ignaz.forster@gmx.de> + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include <linux/hid.h> +#include <linux/input.h> +#include <linux/usb.h> + +#include "hid-ids.h" +#include "usbhid/usbhid.h" + +struct emsff_device { + struct hid_report *report; +}; + +static int emsff_play(struct input_dev *dev, void *data, + struct ff_effect *effect) +{ + struct hid_device *hid = input_get_drvdata(dev); + struct emsff_device *emsff = data; + int weak, strong; + + weak = effect->u.rumble.weak_magnitude; + strong = effect->u.rumble.strong_magnitude; + + dbg_hid("called with 0x%04x 0x%04x\n", strong, weak); + + weak = weak * 0xff / 0xffff; + strong = strong * 0xff / 0xffff; + + emsff->report->field[0]->value[1] = weak; + emsff->report->field[0]->value[2] = strong; + + dbg_hid("running with 0x%02x 0x%02x\n", strong, weak); + usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); + + return 0; +} + +static int emsff_init(struct hid_device *hid) +{ + struct emsff_device *emsff; + struct hid_report *report; + struct hid_input *hidinput = list_first_entry(&hid->inputs, + struct hid_input, list); + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; + int error; + + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; + } + + report = list_first_entry(report_list, struct hid_report, list); + if (report->maxfield < 1) { + hid_err(hid, "no fields in the report\n"); + return -ENODEV; + } + + if (report->field[0]->report_count < 7) { + hid_err(hid, "not enough values in the field\n"); + return -ENODEV; + } + + emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL); + if (!emsff) + return -ENOMEM; + + set_bit(FF_RUMBLE, dev->ffbit); + + error = input_ff_create_memless(dev, emsff, emsff_play); + if (error) { + kfree(emsff); + return error; + } + + emsff->report = report; + emsff->report->field[0]->value[0] = 0x01; + emsff->report->field[0]->value[1] = 0x00; + emsff->report->field[0]->value[2] = 0x00; + emsff->report->field[0]->value[3] = 0x00; + emsff->report->field[0]->value[4] = 0x00; + emsff->report->field[0]->value[5] = 0x00; + emsff->report->field[0]->value[6] = 0x00; + usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); + + hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n"); + + return 0; +} + +static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); + goto err; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto err; + } + + emsff_init(hdev); + + return 0; +err: + return ret; +} + +static const struct hid_device_id ems_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_EMS, 0x118) }, + { } +}; +MODULE_DEVICE_TABLE(hid, ems_devices); + +static struct hid_driver ems_driver = { + .name = "hkems", + .id_table = ems_devices, + .probe = ems_probe, +}; + +static int ems_init(void) +{ + return hid_register_driver(&ems_driver); +} + +static void ems_exit(void) +{ + hid_unregister_driver(&ems_driver); +} + +module_init(ems_init); +module_exit(ems_exit); +MODULE_LICENSE("GPL"); + diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c index 88dfcf49a5d..279ba530003 100644 --- a/drivers/hid/hid-gaff.c +++ b/drivers/hid/hid-gaff.c @@ -87,7 +87,7 @@ static int gaff_init(struct hid_device *hid) int error; if (list_empty(report_list)) { - dev_err(&hid->dev, "no output reports found\n"); + hid_err(hid, "no output reports found\n"); return -ENODEV; } @@ -95,12 +95,12 @@ static int gaff_init(struct hid_device *hid) report = list_entry(report_ptr, struct hid_report, list); if (report->maxfield < 1) { - dev_err(&hid->dev, "no fields in the report\n"); + hid_err(hid, "no fields in the report\n"); return -ENODEV; } if (report->field[0]->report_count < 6) { - dev_err(&hid->dev, "not enough values in the field\n"); + hid_err(hid, "not enough values in the field\n"); return -ENODEV; } @@ -128,8 +128,7 @@ static int gaff_init(struct hid_device *hid) usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); - dev_info(&hid->dev, "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"); return 0; } @@ -148,13 +147,13 @@ static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err; } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 3341baa86a3..92a0d61a737 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -97,6 +97,12 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f +#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 +#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 +#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b @@ -134,7 +140,9 @@ #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 #define USB_VENDOR_ID_CANDO 0x2087 +#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 +#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 0x0a02 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 @@ -156,6 +164,7 @@ #define USB_VENDOR_ID_CHICONY 0x04f2 #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d +#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 #define USB_VENDOR_ID_CIDC 0x1677 @@ -179,6 +188,7 @@ #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 +#define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a @@ -196,13 +206,21 @@ #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1 +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b #define USB_VENDOR_ID_ELECOM 0x056e #define USB_DEVICE_ID_ELECOM_BM084 0x0061 +#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 + #define USB_VENDOR_ID_ELO 0x04E7 #define USB_DEVICE_ID_ELO_TS2700 0x0020 +#define USB_VENDOR_ID_EMS 0x2006 +#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118 + #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 @@ -221,6 +239,7 @@ #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 @@ -303,6 +322,9 @@ #define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 #define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff +#define USB_VENDOR_ID_HANVON 0x20b3 +#define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 + #define USB_VENDOR_ID_HAPP 0x078b #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 #define USB_DEVICE_ID_UGCI_FLYING 0x0020 @@ -475,6 +497,7 @@ #define USB_VENDOR_ID_ROCCAT 0x1e7d #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced +#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d8d372bae3c..7f552bfad32 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -290,6 +290,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel goto ignore; } + if (field->report_type == HID_FEATURE_REPORT) { + if (device->driver->feature_mapping) { + device->driver->feature_mapping(device, hidinput, field, + usage); + } + goto ignore; + } + if (device->driver->input_mapping) { int ret = device->driver->input_mapping(device, hidinput, field, usage, &bit, &max); @@ -319,21 +327,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel switch (field->application) { case HID_GD_MOUSE: - case HID_GD_POINTER: code += 0x110; break; + case HID_GD_POINTER: code += BTN_MOUSE; break; case HID_GD_JOYSTICK: if (code <= 0xf) code += BTN_JOYSTICK; else code += BTN_TRIGGER_HAPPY; break; - case HID_GD_GAMEPAD: code += 0x130; break; + case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break; default: switch (field->physical) { case HID_GD_MOUSE: - case HID_GD_POINTER: code += 0x110; break; - case HID_GD_JOYSTICK: code += 0x120; break; - case HID_GD_GAMEPAD: code += 0x130; break; - default: code += 0x100; + case HID_GD_POINTER: code += BTN_MOUSE; break; + case HID_GD_JOYSTICK: code += BTN_JOYSTICK; break; + case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break; + default: code += BTN_MISC; } } @@ -817,14 +825,14 @@ static int hidinput_open(struct input_dev *dev) { struct hid_device *hid = input_get_drvdata(dev); - return hid->ll_driver->open(hid); + return hid_hw_open(hid); } static void hidinput_close(struct input_dev *dev) { struct hid_device *hid = input_get_drvdata(dev); - hid->ll_driver->close(hid); + hid_hw_close(hid); } /* @@ -839,7 +847,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) struct hid_input *hidinput = NULL; struct input_dev *input_dev; int i, j, k; - int max_report_type = HID_OUTPUT_REPORT; INIT_LIST_HEAD(&hid->inputs); @@ -856,10 +863,11 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) return -1; } - if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) - max_report_type = HID_INPUT_REPORT; + for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) { + if (k == HID_OUTPUT_REPORT && + hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) + continue; - for (k = HID_INPUT_REPORT; k <= max_report_type; k++) list_for_each_entry(report, &hid->report_enum[k].report_list, list) { if (!report->maxfield) @@ -871,7 +879,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) if (!hidinput || !input_dev) { kfree(hidinput); input_free_device(input_dev); - err_hid("Out of memory during hid input probe"); + hid_err(hid, "Out of memory during hid input probe\n"); goto out_unwind; } @@ -912,6 +920,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) hidinput = NULL; } } + } if (hidinput && input_register_device(hidinput->input)) goto out_cleanup; diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index 817247ee006..f2ba9efc3a5 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c @@ -32,8 +32,8 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[65] == 0x29 && rdesc[66] == 0x0f && rdesc[71] == 0x75 && rdesc[72] == 0x08 && rdesc[73] == 0x95 && rdesc[74] == 0x01) { - dev_info(&hdev->dev, "fixing up Kye/Genius Ergo Mouse report " - "descriptor\n"); + hid_info(hdev, + "fixing up Kye/Genius Ergo Mouse report descriptor\n"); rdesc[62] = 0x09; rdesc[64] = 0x04; rdesc[66] = 0x07; diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index b629fba5a05..aef4104da14 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -53,23 +53,22 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && rdesc[84] == 0x8c && rdesc[85] == 0x02) { - dev_info(&hdev->dev, "fixing up Logitech keyboard report " - "descriptor\n"); + hid_info(hdev, + "fixing up Logitech keyboard report descriptor\n"); rdesc[84] = rdesc[89] = 0x4d; rdesc[85] = rdesc[90] = 0x10; } if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && rdesc[32] == 0x81 && rdesc[33] == 0x06 && rdesc[49] == 0x81 && rdesc[50] == 0x06) { - dev_info(&hdev->dev, "fixing up rel/abs in Logitech " - "report descriptor\n"); + hid_info(hdev, + "fixing up rel/abs in Logitech report descriptor\n"); rdesc[33] = rdesc[50] = 0x02; } if ((quirks & LG_FF4) && *rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B && rdesc[47] == 0x05 && rdesc[48] == 0x09) { - dev_info(&hdev->dev, "fixing up Logitech Speed Force Wireless " - "button descriptor\n"); + hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n"); rdesc[41] = 0x05; rdesc[42] = 0x09; rdesc[47] = 0x95; @@ -288,7 +287,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } @@ -297,7 +296,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_hw_start(hdev, connect_mask); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index 4258253c36b..3c31bc650e5 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -72,18 +72,18 @@ int lg2ff_init(struct hid_device *hid) int error; if (list_empty(report_list)) { - dev_err(&hid->dev, "no output report found\n"); + hid_err(hid, "no output report found\n"); return -ENODEV; } report = list_entry(report_list->next, struct hid_report, list); if (report->maxfield < 1) { - dev_err(&hid->dev, "output report is empty\n"); + hid_err(hid, "output report is empty\n"); return -ENODEV; } if (report->field[0]->report_count < 7) { - dev_err(&hid->dev, "not enough values in the field\n"); + hid_err(hid, "not enough values in the field\n"); return -ENODEV; } @@ -110,8 +110,7 @@ int lg2ff_init(struct hid_device *hid) usbhid_submit_report(hid, report, USB_DIR_OUT); - dev_info(&hid->dev, "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"); return 0; } diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index 4002832ee4a..f98644c26c1 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c @@ -141,20 +141,20 @@ int lg3ff_init(struct hid_device *hid) /* Find the report to use */ if (list_empty(report_list)) { - err_hid("No output report found"); + hid_err(hid, "No output report found\n"); return -1; } /* Check that the report looks ok */ report = list_entry(report_list->next, struct hid_report, list); if (!report) { - err_hid("NULL output report"); + hid_err(hid, "NULL output report\n"); return -1; } field = report->field[0]; if (!field) { - err_hid("NULL field"); + hid_err(hid, "NULL field\n"); return -1; } @@ -169,8 +169,7 @@ int lg3ff_init(struct hid_device *hid) if (test_bit(FF_AUTOCENTER, dev->ffbit)) dev->ff->set_autocenter = hid_lg3ff_set_autocenter; - dev_info(&hid->dev, "Force feedback for Logitech Flight System G940 by " - "Gary Stein <LordCnidarian@gmail.com>\n"); + hid_info(hid, "Force feedback for Logitech Flight System G940 by Gary Stein <LordCnidarian@gmail.com>\n"); return 0; } diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 7eef5a2ce94..fa550c8e1d1 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -101,20 +101,20 @@ int lg4ff_init(struct hid_device *hid) /* Find the report to use */ if (list_empty(report_list)) { - err_hid("No output report found"); + hid_err(hid, "No output report found\n"); return -1; } /* Check that the report looks ok */ report = list_entry(report_list->next, struct hid_report, list); if (!report) { - err_hid("NULL output report"); + hid_err(hid, "NULL output report\n"); return -1; } field = report->field[0]; if (!field) { - err_hid("NULL field"); + hid_err(hid, "NULL field\n"); return -1; } @@ -129,8 +129,7 @@ int lg4ff_init(struct hid_device *hid) if (test_bit(FF_AUTOCENTER, dev->ffbit)) dev->ff->set_autocenter = hid_lg4ff_set_autocenter; - dev_info(&hid->dev, "Force feedback for Logitech Speed Force Wireless by " - "Simon Wood <simon@mungewell.org>\n"); + hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n"); return 0; } diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 61142b76a9b..90d0ef2c92b 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -27,6 +27,8 @@ * e-mail - mail your message to <johann.deneux@it.uu.se> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/input.h> #include <linux/usb.h> #include <linux/hid.h> @@ -146,7 +148,7 @@ int lgff_init(struct hid_device* hid) /* Find the report to use */ if (list_empty(report_list)) { - err_hid("No output report found"); + hid_err(hid, "No output report found\n"); return -1; } @@ -154,7 +156,7 @@ int lgff_init(struct hid_device* hid) report = list_entry(report_list->next, struct hid_report, list); field = report->field[0]; if (!field) { - err_hid("NULL field"); + hid_err(hid, "NULL field\n"); return -1; } @@ -176,7 +178,7 @@ int lgff_init(struct hid_device* hid) if ( test_bit(FF_AUTOCENTER, dev->ffbit) ) dev->ff->set_autocenter = hid_lgff_set_autocenter; - printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); + pr_info("Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); return 0; } diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index e6dc1517166..698e6459fd0 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -12,6 +12,8 @@ * any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/device.h> #include <linux/hid.h> #include <linux/module.h> @@ -433,6 +435,11 @@ static int magicmouse_input_mapping(struct hid_device *hdev, if (!msc->input) msc->input = hi->input; + /* Magic Trackpad does not give relative data after switching to MT */ + if (hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD && + field->flags & HID_MAIN_ITEM_RELATIVE) + return -1; + return 0; } @@ -446,7 +453,7 @@ static int magicmouse_probe(struct hid_device *hdev, msc = kzalloc(sizeof(*msc), GFP_KERNEL); if (msc == NULL) { - dev_err(&hdev->dev, "can't alloc magicmouse descriptor\n"); + hid_err(hdev, "can't alloc magicmouse descriptor\n"); return -ENOMEM; } @@ -459,13 +466,13 @@ static int magicmouse_probe(struct hid_device *hdev, ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "magicmouse hid parse failed\n"); + hid_err(hdev, "magicmouse hid parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { - dev_err(&hdev->dev, "magicmouse hw start failed\n"); + hid_err(hdev, "magicmouse hw start failed\n"); goto err_free; } @@ -486,7 +493,7 @@ static int magicmouse_probe(struct hid_device *hdev, } if (!report) { - dev_err(&hdev->dev, "unable to register touch report\n"); + hid_err(hdev, "unable to register touch report\n"); ret = -ENOMEM; goto err_stop_hw; } @@ -495,8 +502,7 @@ static int magicmouse_probe(struct hid_device *hdev, ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), HID_FEATURE_REPORT); if (ret != sizeof(feature)) { - dev_err(&hdev->dev, "unable to request touch data (%d)\n", - ret); + hid_err(hdev, "unable to request touch data (%d)\n", ret); goto err_stop_hw; } @@ -540,7 +546,7 @@ static int __init magicmouse_init(void) ret = hid_register_driver(&magicmouse_driver); if (ret) - printk(KERN_ERR "can't register magicmouse driver\n"); + pr_err("can't register magicmouse driver\n"); return ret; } diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index dc618c33d0a..0f6fc54dc19 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -40,8 +40,7 @@ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { - dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver " - "Model 1028 report descriptor\n"); + hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } @@ -155,14 +154,14 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ? HID_CONNECT_HIDINPUT_FORCE : 0)); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index c95c31e2d86..dedf757781a 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c @@ -26,8 +26,7 @@ static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { - dev_info(&hdev->dev, "fixing up button/consumer in HID report " - "descriptor\n"); + hid_info(hdev, "fixing up button/consumer in HID report descriptor\n"); rdesc[30] = 0x0c; } return rdesc; diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c index ac5421d568f..aed7ffe3628 100644 --- a/drivers/hid/hid-mosart.c +++ b/drivers/hid/hid-mosart.c @@ -90,6 +90,10 @@ static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi, case 0xff000000: /* ignore HID features */ return -1; + + case HID_UP_BUTTON: + /* ignore buttons */ + return -1; } return 0; @@ -199,7 +203,7 @@ static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id) td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL); if (!td) { - dev_err(&hdev->dev, "cannot allocate MosArt data\n"); + hid_err(hdev, "cannot allocate MosArt data\n"); return -ENOMEM; } td->valid = false; @@ -230,6 +234,19 @@ static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id) return ret; } +#ifdef CONFIG_PM +static int mosart_reset_resume(struct hid_device *hdev) +{ + struct hid_report_enum *re = hdev->report_enum + + HID_FEATURE_REPORT; + struct hid_report *r = re->report_id_hash[7]; + + r->field[0]->value[0] = 0x02; + usbhid_submit_report(hdev, r, USB_DIR_OUT); + return 0; +} +#endif + static void mosart_remove(struct hid_device *hdev) { hid_hw_stop(hdev); @@ -240,6 +257,7 @@ static void mosart_remove(struct hid_device *hdev) static const struct hid_device_id mosart_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, { } }; MODULE_DEVICE_TABLE(hid, mosart_devices); @@ -258,6 +276,9 @@ static struct hid_driver mosart_driver = { .input_mapped = mosart_input_mapped, .usage_table = mosart_grabbed_usages, .event = mosart_event, +#ifdef CONFIG_PM + .reset_resume = mosart_reset_resume, +#endif }; static int __init mosart_init(void) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c new file mode 100644 index 00000000000..07d3183fdde --- /dev/null +++ b/drivers/hid/hid-multitouch.c @@ -0,0 +1,516 @@ +/* + * HID driver for multitouch panels + * + * Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr> + * Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com> + * Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France + * + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include <linux/device.h> +#include <linux/hid.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/usb.h> +#include <linux/input/mt.h> +#include "usbhid/usbhid.h" + + +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); +MODULE_DESCRIPTION("HID multitouch panels"); +MODULE_LICENSE("GPL"); + +#include "hid-ids.h" + +/* quirks to control the device */ +#define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0) +#define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) +#define MT_QUIRK_CYPRESS (1 << 2) +#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) +#define MT_QUIRK_VALID_IS_INRANGE (1 << 4) +#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5) + +struct mt_slot { + __s32 x, y, p, w, h; + __s32 contactid; /* the device ContactID assigned to this slot */ + bool touch_state; /* is the touch valid? */ + bool seen_in_this_frame;/* has this slot been updated */ +}; + +struct mt_device { + struct mt_slot curdata; /* placeholder of incoming data */ + struct mt_class *mtclass; /* our mt device class */ + unsigned last_field_index; /* last field index of the report */ + unsigned last_slot_field; /* the last field of a slot */ + __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ + __u8 num_received; /* how many contacts we received */ + __u8 num_expected; /* expected last contact index */ + bool curvalid; /* is the current contact valid? */ + struct mt_slot slots[0]; /* first slot */ +}; + +struct mt_class { + __s32 name; /* MT_CLS */ + __s32 quirks; + __s32 sn_move; /* Signal/noise ratio for move events */ + __s32 sn_pressure; /* Signal/noise ratio for pressure events */ + __u8 maxcontacts; +}; + +/* classes of device behavior */ +#define MT_CLS_DEFAULT 1 +#define MT_CLS_DUAL1 2 +#define MT_CLS_DUAL2 3 +#define MT_CLS_CYPRESS 4 + +/* + * these device-dependent functions determine what slot corresponds + * to a valid contact that was just read. + */ + +static int cypress_compute_slot(struct mt_device *td) +{ + if (td->curdata.contactid != 0 || td->num_received == 0) + return td->curdata.contactid; + else + return -1; +} + +static int find_slot_from_contactid(struct mt_device *td) +{ + int i; + for (i = 0; i < td->mtclass->maxcontacts; ++i) { + if (td->slots[i].contactid == td->curdata.contactid && + td->slots[i].touch_state) + return i; + } + for (i = 0; i < td->mtclass->maxcontacts; ++i) { + if (!td->slots[i].seen_in_this_frame && + !td->slots[i].touch_state) + return i; + } + /* should not occurs. If this happens that means + * that the device sent more touches that it says + * in the report descriptor. It is ignored then. */ + return -1; +} + +struct mt_class mt_classes[] = { + { .name = MT_CLS_DEFAULT, + .quirks = MT_QUIRK_VALID_IS_INRANGE, + .maxcontacts = 10 }, + { .name = MT_CLS_DUAL1, + .quirks = MT_QUIRK_VALID_IS_INRANGE | + MT_QUIRK_SLOT_IS_CONTACTID, + .maxcontacts = 2 }, + { .name = MT_CLS_DUAL2, + .quirks = MT_QUIRK_VALID_IS_INRANGE | + MT_QUIRK_SLOT_IS_CONTACTNUMBER, + .maxcontacts = 2 }, + { .name = MT_CLS_CYPRESS, + .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | + MT_QUIRK_CYPRESS, + .maxcontacts = 10 }, + + { } +}; + +static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage) +{ + if (usage->hid == HID_DG_INPUTMODE) { + struct mt_device *td = hid_get_drvdata(hdev); + td->inputmode = field->report->id; + } +} + +static void set_abs(struct input_dev *input, unsigned int code, + struct hid_field *field, int snratio) +{ + int fmin = field->logical_minimum; + int fmax = field->logical_maximum; + int fuzz = snratio ? (fmax - fmin) / snratio : 0; + input_set_abs_params(input, code, fmin, fmax, fuzz, 0); +} + +static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + struct mt_device *td = hid_get_drvdata(hdev); + struct mt_class *cls = td->mtclass; + switch (usage->hid & HID_USAGE_PAGE) { + + case HID_UP_GENDESK: + switch (usage->hid) { + case HID_GD_X: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_POSITION_X); + set_abs(hi->input, ABS_MT_POSITION_X, field, + cls->sn_move); + /* touchscreen emulation */ + set_abs(hi->input, ABS_X, field, cls->sn_move); + td->last_slot_field = usage->hid; + return 1; + case HID_GD_Y: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_POSITION_Y); + set_abs(hi->input, ABS_MT_POSITION_Y, field, + cls->sn_move); + /* touchscreen emulation */ + set_abs(hi->input, ABS_Y, field, cls->sn_move); + td->last_slot_field = usage->hid; + return 1; + } + return 0; + + case HID_UP_DIGITIZER: + switch (usage->hid) { + case HID_DG_INRANGE: + td->last_slot_field = usage->hid; + return 1; + case HID_DG_CONFIDENCE: + td->last_slot_field = usage->hid; + return 1; + case HID_DG_TIPSWITCH: + hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); + input_set_capability(hi->input, EV_KEY, BTN_TOUCH); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_CONTACTID: + input_mt_init_slots(hi->input, + td->mtclass->maxcontacts); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_WIDTH: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TOUCH_MAJOR); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_HEIGHT: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TOUCH_MINOR); + field->logical_maximum = 1; + field->logical_minimum = 0; + set_abs(hi->input, ABS_MT_ORIENTATION, field, 0); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_TIPPRESSURE: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_PRESSURE); + set_abs(hi->input, ABS_MT_PRESSURE, field, + cls->sn_pressure); + /* touchscreen emulation */ + set_abs(hi->input, ABS_PRESSURE, field, + cls->sn_pressure); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_CONTACTCOUNT: + td->last_field_index = field->report->maxfield - 1; + return 1; + case HID_DG_CONTACTMAX: + /* we don't set td->last_slot_field as contactcount and + * contact max are global to the report */ + return -1; + } + /* let hid-input decide for the others */ + return 0; + + case 0xff000000: + /* we do not want to map these: no input-oriented meaning */ + return -1; + } + + return 0; +} + +static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + if (usage->type == EV_KEY || usage->type == EV_ABS) + set_bit(usage->type, hi->input->evbit); + + return -1; +} + +static int mt_compute_slot(struct mt_device *td) +{ + __s32 quirks = td->mtclass->quirks; + + if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) + return td->curdata.contactid; + + if (quirks & MT_QUIRK_CYPRESS) + return cypress_compute_slot(td); + + if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER) + return td->num_received; + + return find_slot_from_contactid(td); +} + +/* + * this function is called when a whole contact has been processed, + * so that it can assign it to a slot and store the data there + */ +static void mt_complete_slot(struct mt_device *td) +{ + td->curdata.seen_in_this_frame = true; + if (td->curvalid) { + int slotnum = mt_compute_slot(td); + + if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts) + td->slots[slotnum] = td->curdata; + } + td->num_received++; +} + + +/* + * this function is called when a whole packet has been received and processed, + * so that it can decide what to send to the input layer. + */ +static void mt_emit_event(struct mt_device *td, struct input_dev *input) +{ + int i; + + for (i = 0; i < td->mtclass->maxcontacts; ++i) { + struct mt_slot *s = &(td->slots[i]); + if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && + !s->seen_in_this_frame) { + s->touch_state = false; + } + + input_mt_slot(input, i); + input_mt_report_slot_state(input, MT_TOOL_FINGER, + s->touch_state); + if (s->touch_state) { + input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); + input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); + input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); + input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w); + input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h); + } + s->seen_in_this_frame = false; + + } + + input_mt_report_pointer_emulation(input, true); + input_sync(input); + td->num_received = 0; +} + + + +static int mt_event(struct hid_device *hid, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + struct mt_device *td = hid_get_drvdata(hid); + __s32 quirks = td->mtclass->quirks; + + if (hid->claimed & HID_CLAIMED_INPUT) { + switch (usage->hid) { + case HID_DG_INRANGE: + if (quirks & MT_QUIRK_VALID_IS_INRANGE) + td->curvalid = value; + break; + case HID_DG_TIPSWITCH: + if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) + td->curvalid = value; + td->curdata.touch_state = value; + break; + case HID_DG_CONFIDENCE: + if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE) + td->curvalid = value; + break; + case HID_DG_CONTACTID: + td->curdata.contactid = value; + break; + case HID_DG_TIPPRESSURE: + td->curdata.p = value; + break; + case HID_GD_X: + td->curdata.x = value; + break; + case HID_GD_Y: + td->curdata.y = value; + break; + case HID_DG_WIDTH: + td->curdata.w = value; + break; + case HID_DG_HEIGHT: + td->curdata.h = value; + break; + case HID_DG_CONTACTCOUNT: + /* + * Includes multi-packet support where subsequent + * packets are sent with zero contactcount. + */ + if (value) + td->num_expected = value; + break; + + default: + /* fallback to the generic hidinput handling */ + return 0; + } + + if (usage->hid == td->last_slot_field) + mt_complete_slot(td); + + if (field->index == td->last_field_index + && td->num_received >= td->num_expected) + mt_emit_event(td, field->hidinput->input); + + } + + /* we have handled the hidinput part, now remains hiddev */ + if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) + hid->hiddev_hid_event(hid, field, usage, value); + + return 1; +} + +static void mt_set_input_mode(struct hid_device *hdev) +{ + struct mt_device *td = hid_get_drvdata(hdev); + struct hid_report *r; + struct hid_report_enum *re; + + if (td->inputmode < 0) + return; + + re = &(hdev->report_enum[HID_FEATURE_REPORT]); + r = re->report_id_hash[td->inputmode]; + if (r) { + r->field[0]->value[0] = 0x02; + usbhid_submit_report(hdev, r, USB_DIR_OUT); + } +} + +static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret, i; + struct mt_device *td; + struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ + + for (i = 0; mt_classes[i].name ; i++) { + if (id->driver_data == mt_classes[i].name) { + mtclass = &(mt_classes[i]); + break; + } + } + + /* This allows the driver to correctly support devices + * that emit events over several HID messages. + */ + hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; + + td = kzalloc(sizeof(struct mt_device) + + mtclass->maxcontacts * sizeof(struct mt_slot), + GFP_KERNEL); + if (!td) { + dev_err(&hdev->dev, "cannot allocate multitouch data\n"); + return -ENOMEM; + } + td->mtclass = mtclass; + td->inputmode = -1; + hid_set_drvdata(hdev, td); + + ret = hid_parse(hdev); + if (ret != 0) + goto fail; + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) + goto fail; + + mt_set_input_mode(hdev); + + return 0; + +fail: + kfree(td); + return ret; +} + +#ifdef CONFIG_PM +static int mt_reset_resume(struct hid_device *hdev) +{ + mt_set_input_mode(hdev); + return 0; +} +#endif + +static void mt_remove(struct hid_device *hdev) +{ + struct mt_device *td = hid_get_drvdata(hdev); + hid_hw_stop(hdev); + kfree(td); + hid_set_drvdata(hdev, NULL); +} + +static const struct hid_device_id mt_devices[] = { + + /* Cypress panel */ + { .driver_data = MT_CLS_CYPRESS, + HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, + USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, + + /* GeneralTouch panel */ + { .driver_data = MT_CLS_DUAL2, + HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, + + /* PixCir-based panels */ + { .driver_data = MT_CLS_DUAL1, + HID_USB_DEVICE(USB_VENDOR_ID_HANVON, + USB_DEVICE_ID_HANVON_MULTITOUCH) }, + { .driver_data = MT_CLS_DUAL1, + HID_USB_DEVICE(USB_VENDOR_ID_CANDO, + USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, + + { } +}; +MODULE_DEVICE_TABLE(hid, mt_devices); + +static const struct hid_usage_id mt_grabbed_usages[] = { + { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, + { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} +}; + +static struct hid_driver mt_driver = { + .name = "hid-multitouch", + .id_table = mt_devices, + .probe = mt_probe, + .remove = mt_remove, + .input_mapping = mt_input_mapping, + .input_mapped = mt_input_mapped, + .feature_mapping = mt_feature_mapping, + .usage_table = mt_grabbed_usages, + .event = mt_event, +#ifdef CONFIG_PM + .reset_resume = mt_reset_resume, +#endif +}; + +static int __init mt_init(void) +{ + return hid_register_driver(&mt_driver); +} + +static void __exit mt_exit(void) +{ + hid_unregister_driver(&mt_driver); +} + +module_init(mt_init); +module_exit(mt_exit); diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 69169efa1e1..beb403421e7 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -130,8 +130,7 @@ static void ntrig_report_version(struct hid_device *hdev) if (ret == 8) { ret = ntrig_version_string(&data[2], buf); - dev_info(&hdev->dev, - "Firmware version: %s (%02x%02x %02x%02x)\n", + hid_info(hdev, "Firmware version: %s (%02x%02x %02x%02x)\n", buf, data[2], data[3], data[4], data[5]); } @@ -831,7 +830,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); if (!nd) { - dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); + hid_err(hdev, "cannot allocate N-Trig data\n"); return -ENOMEM; } @@ -850,13 +849,13 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c index 2e79716dca3..e90edfc6305 100644 --- a/drivers/hid/hid-ortek.c +++ b/drivers/hid/hid-ortek.c @@ -23,8 +23,7 @@ static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { - dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 " - "report descriptor.\n"); + hid_info(hdev, "Fixing up Ortek WKB-2000 report descriptor\n"); rdesc[55] = 0x92; } return rdesc; diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 308d6ae48a3..f1ea3ff8a98 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c @@ -29,8 +29,7 @@ static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && rdesc[41] == 0x00 && rdesc[59] == 0x26 && rdesc[60] == 0xf9 && rdesc[61] == 0x00) { - dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report " - "descriptor\n"); + hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n"); rdesc[60] = 0xfa; rdesc[40] = 0xfa; } @@ -77,13 +76,13 @@ static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index bc2e0774062..de9cf21b349 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c @@ -253,7 +253,7 @@ static struct hid_report *picolcd_report(int id, struct hid_device *hdev, int di if (report->id == id) return report; } - dev_warn(&hdev->dev, "No report with id 0x%x found\n", id); + hid_warn(hdev, "No report with id 0x%x found\n", id); return NULL; } @@ -1329,7 +1329,7 @@ static int picolcd_check_version(struct hid_device *hdev) verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); if (!verinfo) { - dev_err(&hdev->dev, "no version response from PicoLCD"); + hid_err(hdev, "no version response from PicoLCD\n"); return -ENODEV; } @@ -1337,14 +1337,14 @@ static int picolcd_check_version(struct hid_device *hdev) data->version[0] = verinfo->raw_data[1]; data->version[1] = verinfo->raw_data[0]; if (data->status & PICOLCD_BOOTLOADER) { - dev_info(&hdev->dev, "PicoLCD, bootloader version %d.%d\n", - verinfo->raw_data[1], verinfo->raw_data[0]); + hid_info(hdev, "PicoLCD, bootloader version %d.%d\n", + verinfo->raw_data[1], verinfo->raw_data[0]); } else { - dev_info(&hdev->dev, "PicoLCD, firmware version %d.%d\n", - verinfo->raw_data[1], verinfo->raw_data[0]); + hid_info(hdev, "PicoLCD, firmware version %d.%d\n", + verinfo->raw_data[1], verinfo->raw_data[0]); } } else { - dev_err(&hdev->dev, "confused, got unexpected version response from PicoLCD\n"); + hid_err(hdev, "confused, got unexpected version response from PicoLCD\n"); ret = -EINVAL; } kfree(verinfo); @@ -1544,7 +1544,7 @@ static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u, /* prepare buffer with info about what we want to read (addr & len) */ raw_data[0] = *off & 0xff; - raw_data[1] = (*off >> 8) && 0xff; + raw_data[1] = (*off >> 8) & 0xff; raw_data[2] = s < 20 ? s : 20; if (*off + raw_data[2] > 0xff) raw_data[2] = 0x100 - *off; @@ -1583,7 +1583,7 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, memset(raw_data, 0, sizeof(raw_data)); raw_data[0] = *off & 0xff; - raw_data[1] = (*off >> 8) && 0xff; + raw_data[1] = (*off >> 8) & 0xff; raw_data[2] = s < 20 ? s : 20; if (*off + raw_data[2] > 0xff) raw_data[2] = 0x100 - *off; @@ -1867,6 +1867,7 @@ static void picolcd_debug_out_report(struct picolcd_data *data, report->id, raw_size); hid_debug_event(hdev, buff); if (raw_size + 5 > sizeof(raw_data)) { + kfree(buff); hid_debug_event(hdev, " TOO BIG\n"); return; } else { @@ -2328,8 +2329,7 @@ static void picolcd_init_devfs(struct picolcd_data *data, (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0), hdev->debug_dir, data, &picolcd_debug_flash_fops); } else if (flash_r || flash_w) - dev_warn(&hdev->dev, "Unexpected FLASH access reports, " - "please submit rdesc for review\n"); + hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n"); } static void picolcd_exit_devfs(struct picolcd_data *data) @@ -2457,13 +2457,13 @@ static int picolcd_init_keys(struct picolcd_data *data, return -ENODEV; if (report->maxfield != 1 || report->field[0]->report_count != 2 || report->field[0]->report_size != 8) { - dev_err(&hdev->dev, "unsupported KEY_STATE report"); + hid_err(hdev, "unsupported KEY_STATE report\n"); return -EINVAL; } idev = input_allocate_device(); if (idev == NULL) { - dev_err(&hdev->dev, "failed to allocate input device"); + hid_err(hdev, "failed to allocate input device\n"); return -ENOMEM; } input_set_drvdata(idev, hdev); @@ -2485,7 +2485,7 @@ static int picolcd_init_keys(struct picolcd_data *data, input_set_capability(idev, EV_KEY, data->keycode[i]); error = input_register_device(idev); if (error) { - dev_err(&hdev->dev, "error registering the input device"); + hid_err(hdev, "error registering the input device\n"); input_free_device(idev); return error; } @@ -2522,9 +2522,8 @@ static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) return error; if (data->version[0] != 0 && data->version[1] != 3) - dev_info(&hdev->dev, "Device with untested firmware revision, " - "please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", - dev_name(&hdev->dev)); + hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", + dev_name(&hdev->dev)); /* Setup keypad input device */ error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); @@ -2581,9 +2580,8 @@ static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data return error; if (data->version[0] != 1 && data->version[1] != 0) - dev_info(&hdev->dev, "Device with untested bootloader revision, " - "please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", - dev_name(&hdev->dev)); + hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", + dev_name(&hdev->dev)); picolcd_init_devfs(data, NULL, NULL, picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), @@ -2605,7 +2603,7 @@ static int picolcd_probe(struct hid_device *hdev, */ data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL); if (data == NULL) { - dev_err(&hdev->dev, "can't allocate space for Minibox PicoLCD device data\n"); + hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n"); error = -ENOMEM; goto err_no_cleanup; } @@ -2621,7 +2619,7 @@ static int picolcd_probe(struct hid_device *hdev, /* Parse the device reports and start it up */ error = hid_parse(hdev); if (error) { - dev_err(&hdev->dev, "device report parse failed\n"); + hid_err(hdev, "device report parse failed\n"); goto err_cleanup_data; } @@ -2631,25 +2629,25 @@ static int picolcd_probe(struct hid_device *hdev, error = hid_hw_start(hdev, 0); hdev->claimed = 0; if (error) { - dev_err(&hdev->dev, "hardware start failed\n"); + hid_err(hdev, "hardware start failed\n"); goto err_cleanup_data; } - error = hdev->ll_driver->open(hdev); + error = hid_hw_open(hdev); if (error) { - dev_err(&hdev->dev, "failed to open input interrupt pipe for key and IR events\n"); + hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n"); goto err_cleanup_hid_hw; } error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); if (error) { - dev_err(&hdev->dev, "failed to create sysfs attributes\n"); + hid_err(hdev, "failed to create sysfs attributes\n"); goto err_cleanup_hid_ll; } error = device_create_file(&hdev->dev, &dev_attr_operation_mode); if (error) { - dev_err(&hdev->dev, "failed to create sysfs attributes\n"); + hid_err(hdev, "failed to create sysfs attributes\n"); goto err_cleanup_sysfs1; } @@ -2668,7 +2666,7 @@ err_cleanup_sysfs2: err_cleanup_sysfs1: device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); err_cleanup_hid_ll: - hdev->ll_driver->close(hdev); + hid_hw_close(hdev); err_cleanup_hid_hw: hid_hw_stop(hdev); err_cleanup_data: @@ -2699,7 +2697,7 @@ static void picolcd_remove(struct hid_device *hdev) picolcd_exit_devfs(data); device_remove_file(&hdev->dev, &dev_attr_operation_mode); device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); - hdev->ll_driver->close(hdev); + hid_hw_close(hdev); hid_hw_stop(hdev); hid_set_drvdata(hdev, NULL); @@ -2753,7 +2751,7 @@ static void __exit picolcd_exit(void) { hid_unregister_driver(&picolcd_driver); #ifdef CONFIG_HID_PICOLCD_FB - flush_scheduled_work(); + flush_work_sync(&picolcd_fb_cleanup); WARN_ON(fb_pending); #endif } diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 9f41e2bd848..06e5300d43d 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c @@ -103,7 +103,7 @@ static int plff_init(struct hid_device *hid) */ if (list_empty(report_list)) { - dev_err(&hid->dev, "no output reports found\n"); + hid_err(hid, "no output reports found\n"); return -ENODEV; } @@ -112,14 +112,13 @@ static int plff_init(struct hid_device *hid) report_ptr = report_ptr->next; if (report_ptr == report_list) { - dev_err(&hid->dev, "required output report is " - "missing\n"); + hid_err(hid, "required output report is missing\n"); return -ENODEV; } report = list_entry(report_ptr, struct hid_report, list); if (report->maxfield < 1) { - dev_err(&hid->dev, "no fields in the report\n"); + hid_err(hid, "no fields in the report\n"); return -ENODEV; } @@ -137,7 +136,7 @@ static int plff_init(struct hid_device *hid) weak = &report->field[3]->value[0]; debug("detected 4-field device"); } else { - dev_err(&hid->dev, "not enough fields or values\n"); + hid_err(hid, "not enough fields or values\n"); return -ENODEV; } @@ -164,8 +163,7 @@ static int plff_init(struct hid_device *hid) usbhid_submit_report(hid, plff->report, USB_DIR_OUT); } - dev_info(&hid->dev, "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"); return 0; } @@ -185,13 +183,13 @@ static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err; } diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 48eab84f53b..ab19f2905d2 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -16,6 +16,8 @@ * any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/device.h> #include <linux/module.h> #include <linux/usb.h> @@ -130,7 +132,7 @@ static ssize_t store_channel(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(channel, S_IRUGO | S_IWUGO, show_channel, +static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel, store_channel); static struct device_attribute *sysfs_device_attr_channel = { @@ -169,7 +171,7 @@ static ssize_t store_sustain(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(sustain, S_IRUGO | S_IWUGO, show_sustain, +static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain, store_sustain); static struct device_attribute *sysfs_device_attr_sustain = { @@ -207,7 +209,7 @@ static ssize_t store_octave(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(octave, S_IRUGO | S_IWUGO, show_octave, +static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave, store_octave); static struct device_attribute *sysfs_device_attr_octave = { @@ -285,11 +287,11 @@ static int pcmidi_get_output_report(struct pcmidi_snd *pm) continue; if (report->maxfield < 1) { - dev_err(&hdev->dev, "output report is empty\n"); + hid_err(hdev, "output report is empty\n"); break; } if (report->field[0]->report_count != 2) { - dev_err(&hdev->dev, "field count too low\n"); + hid_err(hdev, "field count too low\n"); break; } pm->pcmidi_report6 = report; @@ -746,8 +748,8 @@ static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == 178 && rdesc[111] == 0x06 && rdesc[112] == 0x00 && rdesc[113] == 0xff) { - dev_info(&hdev->dev, "fixing up pc-midi keyboard report " - "descriptor\n"); + hid_info(hdev, + "fixing up pc-midi keyboard report descriptor\n"); rdesc[144] = 0x18; /* report 4: was 0x10 report count */ } @@ -805,7 +807,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) pk = kzalloc(sizeof(*pk), GFP_KERNEL); if (pk == NULL) { - dev_err(&hdev->dev, "prodikeys: can't alloc descriptor\n"); + hid_err(hdev, "can't alloc descriptor\n"); return -ENOMEM; } @@ -813,8 +815,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) pm = kzalloc(sizeof(*pm), GFP_KERNEL); if (pm == NULL) { - dev_err(&hdev->dev, - "prodikeys: can't alloc descriptor\n"); + hid_err(hdev, "can't alloc descriptor\n"); ret = -ENOMEM; goto err_free; } @@ -827,7 +828,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "prodikeys: hid parse failed\n"); + hid_err(hdev, "hid parse failed\n"); goto err_free; } @@ -837,7 +838,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { - dev_err(&hdev->dev, "prodikeys: hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } @@ -896,7 +897,7 @@ static int pk_init(void) ret = hid_register_driver(&pk_driver); if (ret) - printk(KERN_ERR "can't register prodikeys driver\n"); + pr_err("can't register prodikeys driver\n"); return ret; } diff --git a/drivers/hid/hid-quanta.c b/drivers/hid/hid-quanta.c index 54d3db50605..87a54df4d4a 100644 --- a/drivers/hid/hid-quanta.c +++ b/drivers/hid/hid-quanta.c @@ -195,7 +195,7 @@ static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id) td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL); if (!td) { - dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n"); + hid_err(hdev, "cannot allocate Quanta Touch data\n"); return -ENOMEM; } td->valid = false; diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index f77695762cb..cbd8cc42e75 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -35,6 +35,11 @@ #include "hid-roccat.h" #include "hid-roccat-kone.h" +static uint profile_numbers[5] = {0, 1, 2, 3, 4}; + +/* kone_class is used for creating sysfs attributes via roccat char device */ +static struct class *kone_class; + static void kone_set_settings_checksum(struct kone_settings *settings) { uint16_t checksum = 0; @@ -90,8 +95,7 @@ static int kone_check_write(struct usb_device *usb_dev) kfree(data); return 0; } else { /* unknown answer */ - dev_err(&usb_dev->dev, "got retval %d when checking write\n", - *data); + hid_err(usb_dev, "got retval %d when checking write\n", *data); kfree(data); return -EIO; } @@ -262,7 +266,8 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); if (off >= sizeof(struct kone_settings)) @@ -286,7 +291,8 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval = 0, difference; @@ -319,10 +325,11 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, return sizeof(struct kone_settings); } -static ssize_t kone_sysfs_read_profilex(struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count, int number) { - struct device *dev = container_of(kobj, struct device, kobj); +static ssize_t kone_sysfs_read_profilex(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) { + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); if (off >= sizeof(struct kone_profile)) @@ -332,47 +339,18 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj, count = sizeof(struct kone_profile) - off; mutex_lock(&kone->kone_lock); - memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count); + memcpy(buf, ((char const *)&kone->profiles[*(uint *)(attr->private)]) + off, count); mutex_unlock(&kone->kone_lock); return count; } -static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1); -} - -static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2); -} - -static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3); -} - -static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4); -} - -static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5); -} - /* Writes data only if different to stored data */ -static ssize_t kone_sysfs_write_profilex(struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count, int number) { - struct device *dev = container_of(kobj, struct device, kobj); +static ssize_t kone_sysfs_write_profilex(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) { + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); struct kone_profile *profile; @@ -382,13 +360,14 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj, if (off != 0 || count != sizeof(struct kone_profile)) return -EINVAL; - profile = &kone->profiles[number - 1]; + profile = &kone->profiles[*(uint *)(attr->private)]; mutex_lock(&kone->kone_lock); difference = memcmp(buf, profile, sizeof(struct kone_profile)); if (difference) { retval = kone_set_profile(usb_dev, - (struct kone_profile const *)buf, number); + (struct kone_profile const *)buf, + *(uint *)(attr->private) + 1); if (!retval) memcpy(profile, buf, sizeof(struct kone_profile)); } @@ -400,47 +379,19 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj, return sizeof(struct kone_profile); } -static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1); -} - -static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2); -} - -static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3); -} - -static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4); -} - -static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5); -} - static ssize_t kone_sysfs_show_actual_profile(struct device *dev, struct device_attribute *attr, char *buf) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); + struct kone_device *kone = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile); } static ssize_t kone_sysfs_show_actual_dpi(struct device *dev, struct device_attribute *attr, char *buf) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); + struct kone_device *kone = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi); } @@ -448,11 +399,15 @@ static ssize_t kone_sysfs_show_actual_dpi(struct device *dev, static ssize_t kone_sysfs_show_weight(struct device *dev, struct device_attribute *attr, char *buf) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + struct kone_device *kone; + struct usb_device *usb_dev; int weight = 0; int retval; + dev = dev->parent->parent; + kone = hid_get_drvdata(dev_get_drvdata(dev)); + usb_dev = interface_to_usbdev(to_usb_interface(dev)); + mutex_lock(&kone->kone_lock); retval = kone_get_weight(usb_dev, &weight); mutex_unlock(&kone->kone_lock); @@ -465,14 +420,16 @@ static ssize_t kone_sysfs_show_weight(struct device *dev, static ssize_t kone_sysfs_show_firmware_version(struct device *dev, struct device_attribute *attr, char *buf) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); + struct kone_device *kone = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version); } static ssize_t kone_sysfs_show_tcu(struct device *dev, struct device_attribute *attr, char *buf) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); + struct kone_device *kone = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu); } @@ -504,11 +461,15 @@ static int kone_tcu_command(struct usb_device *usb_dev, int number) static ssize_t kone_sysfs_set_tcu(struct device *dev, struct device_attribute *attr, char const *buf, size_t size) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + struct kone_device *kone; + struct usb_device *usb_dev; int retval; unsigned long state; + dev = dev->parent->parent; + kone = hid_get_drvdata(dev_get_drvdata(dev)); + usb_dev = interface_to_usbdev(to_usb_interface(dev)); + retval = strict_strtoul(buf, 10, &state); if (retval) return retval; @@ -556,7 +517,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev, retval = kone_set_settings(usb_dev, &kone->settings); if (retval) { - dev_err(&usb_dev->dev, "couldn't set tcu state\n"); + hid_err(usb_dev, "couldn't set tcu state\n"); /* * try to reread valid settings into buffer overwriting * first error code @@ -570,7 +531,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev, retval = size; exit_no_settings: - dev_err(&usb_dev->dev, "couldn't read settings\n"); + hid_err(usb_dev, "couldn't read settings\n"); exit_unlock: mutex_unlock(&kone->kone_lock); return retval; @@ -579,18 +540,23 @@ exit_unlock: static ssize_t kone_sysfs_show_startup_profile(struct device *dev, struct device_attribute *attr, char *buf) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); + struct kone_device *kone = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile); } static ssize_t kone_sysfs_set_startup_profile(struct device *dev, struct device_attribute *attr, char const *buf, size_t size) { - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + struct kone_device *kone; + struct usb_device *usb_dev; int retval; unsigned long new_startup_profile; + dev = dev->parent->parent; + kone = hid_get_drvdata(dev_get_drvdata(dev)); + usb_dev = interface_to_usbdev(to_usb_interface(dev)); + retval = strict_strtoul(buf, 10, &new_startup_profile); if (retval) return retval; @@ -617,160 +583,92 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev, return size; } -/* - * Read actual dpi settings. - * Returns raw value for further processing. Refer to enum kone_polling_rates to - * get real value. - */ -static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL); - -static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL); - -/* - * The mouse can be equipped with one of four supplied weights from 5 to 20 - * grams which are recognized and its value can be read out. - * This returns the raw value reported by the mouse for easy evaluation by - * software. Refer to enum kone_weights to get corresponding real weight. - */ -static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL); - -/* - * Prints firmware version stored in mouse as integer. - * The raw value reported by the mouse is returned for easy evaluation, to get - * the real version number the decimal point has to be shifted 2 positions to - * the left. E.g. a value of 138 means 1.38. - */ -static DEVICE_ATTR(firmware_version, 0440, - kone_sysfs_show_firmware_version, NULL); - -/* - * Prints state of Tracking Control Unit as number where 0 = off and 1 = on - * Writing 0 deactivates tcu and writing 1 calibrates and activates the tcu - */ -static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu); - -/* Prints and takes the number of the profile the mouse starts with */ -static DEVICE_ATTR(startup_profile, 0660, - kone_sysfs_show_startup_profile, - kone_sysfs_set_startup_profile); - -static struct attribute *kone_attributes[] = { - &dev_attr_actual_dpi.attr, - &dev_attr_actual_profile.attr, - &dev_attr_weight.attr, - &dev_attr_firmware_version.attr, - &dev_attr_tcu.attr, - &dev_attr_startup_profile.attr, - NULL -}; - -static struct attribute_group kone_attribute_group = { - .attrs = kone_attributes -}; - -static struct bin_attribute kone_settings_attr = { - .attr = { .name = "settings", .mode = 0660 }, - .size = sizeof(struct kone_settings), - .read = kone_sysfs_read_settings, - .write = kone_sysfs_write_settings -}; +static struct device_attribute kone_attributes[] = { + /* + * Read actual dpi settings. + * Returns raw value for further processing. Refer to enum + * kone_polling_rates to get real value. + */ + __ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL), + __ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL), -static struct bin_attribute kone_profile1_attr = { - .attr = { .name = "profile1", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profile1, - .write = kone_sysfs_write_profile1 -}; + /* + * The mouse can be equipped with one of four supplied weights from 5 + * to 20 grams which are recognized and its value can be read out. + * This returns the raw value reported by the mouse for easy evaluation + * by software. Refer to enum kone_weights to get corresponding real + * weight. + */ + __ATTR(weight, 0440, kone_sysfs_show_weight, NULL), -static struct bin_attribute kone_profile2_attr = { - .attr = { .name = "profile2", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profile2, - .write = kone_sysfs_write_profile2 -}; + /* + * Prints firmware version stored in mouse as integer. + * The raw value reported by the mouse is returned for easy evaluation, + * to get the real version number the decimal point has to be shifted 2 + * positions to the left. E.g. a value of 138 means 1.38. + */ + __ATTR(firmware_version, 0440, + kone_sysfs_show_firmware_version, NULL), -static struct bin_attribute kone_profile3_attr = { - .attr = { .name = "profile3", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profile3, - .write = kone_sysfs_write_profile3 -}; + /* + * Prints state of Tracking Control Unit as number where 0 = off and + * 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and + * activates the tcu + */ + __ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu), -static struct bin_attribute kone_profile4_attr = { - .attr = { .name = "profile4", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profile4, - .write = kone_sysfs_write_profile4 + /* Prints and takes the number of the profile the mouse starts with */ + __ATTR(startup_profile, 0660, + kone_sysfs_show_startup_profile, + kone_sysfs_set_startup_profile), + __ATTR_NULL }; -static struct bin_attribute kone_profile5_attr = { - .attr = { .name = "profile5", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profile5, - .write = kone_sysfs_write_profile5 +static struct bin_attribute kone_bin_attributes[] = { + { + .attr = { .name = "settings", .mode = 0660 }, + .size = sizeof(struct kone_settings), + .read = kone_sysfs_read_settings, + .write = kone_sysfs_write_settings + }, + { + .attr = { .name = "profile1", .mode = 0660 }, + .size = sizeof(struct kone_profile), + .read = kone_sysfs_read_profilex, + .write = kone_sysfs_write_profilex, + .private = &profile_numbers[0] + }, + { + .attr = { .name = "profile2", .mode = 0660 }, + .size = sizeof(struct kone_profile), + .read = kone_sysfs_read_profilex, + .write = kone_sysfs_write_profilex, + .private = &profile_numbers[1] + }, + { + .attr = { .name = "profile3", .mode = 0660 }, + .size = sizeof(struct kone_profile), + .read = kone_sysfs_read_profilex, + .write = kone_sysfs_write_profilex, + .private = &profile_numbers[2] + }, + { + .attr = { .name = "profile4", .mode = 0660 }, + .size = sizeof(struct kone_profile), + .read = kone_sysfs_read_profilex, + .write = kone_sysfs_write_profilex, + .private = &profile_numbers[3] + }, + { + .attr = { .name = "profile5", .mode = 0660 }, + .size = sizeof(struct kone_profile), + .read = kone_sysfs_read_profilex, + .write = kone_sysfs_write_profilex, + .private = &profile_numbers[4] + }, + __ATTR_NULL }; -static int kone_create_sysfs_attributes(struct usb_interface *intf) -{ - int retval; - - retval = sysfs_create_group(&intf->dev.kobj, &kone_attribute_group); - if (retval) - goto exit_1; - - retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_settings_attr); - if (retval) - goto exit_2; - - retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile1_attr); - if (retval) - goto exit_3; - - retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile2_attr); - if (retval) - goto exit_4; - - retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile3_attr); - if (retval) - goto exit_5; - - retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile4_attr); - if (retval) - goto exit_6; - - retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile5_attr); - if (retval) - goto exit_7; - - return 0; - -exit_7: - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr); -exit_6: - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr); -exit_5: - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr); -exit_4: - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr); -exit_3: - sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr); -exit_2: - sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group); -exit_1: - return retval; -} - -static void kone_remove_sysfs_attributes(struct usb_interface *intf) -{ - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile5_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr); - sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group); -} - static int kone_init_kone_device_struct(struct usb_device *usb_dev, struct kone_device *kone) { @@ -818,32 +716,25 @@ static int kone_init_specials(struct hid_device *hdev) kone = kzalloc(sizeof(*kone), GFP_KERNEL); if (!kone) { - dev_err(&hdev->dev, "can't alloc device descriptor\n"); + hid_err(hdev, "can't alloc device descriptor\n"); return -ENOMEM; } hid_set_drvdata(hdev, kone); retval = kone_init_kone_device_struct(usb_dev, kone); if (retval) { - dev_err(&hdev->dev, - "couldn't init struct kone_device\n"); + hid_err(hdev, "couldn't init struct kone_device\n"); goto exit_free; } - retval = roccat_connect(hdev); + retval = roccat_connect(kone_class, hdev); if (retval < 0) { - dev_err(&hdev->dev, "couldn't init char dev\n"); + hid_err(hdev, "couldn't init char dev\n"); /* be tolerant about not getting chrdev */ } else { kone->roccat_claimed = 1; kone->chrdev_minor = retval; } - - retval = kone_create_sysfs_attributes(intf); - if (retval) { - dev_err(&hdev->dev, "cannot create sysfs files\n"); - goto exit_free; - } } else { hid_set_drvdata(hdev, NULL); } @@ -854,7 +745,6 @@ exit_free: return retval; } - static void kone_remove_specials(struct hid_device *hdev) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); @@ -862,7 +752,6 @@ static void kone_remove_specials(struct hid_device *hdev) if (intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) { - kone_remove_sysfs_attributes(intf); kone = hid_get_drvdata(hdev); if (kone->roccat_claimed) roccat_disconnect(kone->chrdev_minor); @@ -876,19 +765,19 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id) retval = hid_parse(hdev); if (retval) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto exit; } retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (retval) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto exit; } retval = kone_init_specials(hdev); if (retval) { - dev_err(&hdev->dev, "couldn't install mouse\n"); + hid_err(hdev, "couldn't install mouse\n"); goto exit_stop; } @@ -1006,11 +895,24 @@ static struct hid_driver kone_driver = { static int __init kone_init(void) { - return hid_register_driver(&kone_driver); + int retval; + + /* class name has to be same as driver name */ + kone_class = class_create(THIS_MODULE, "kone"); + if (IS_ERR(kone_class)) + return PTR_ERR(kone_class); + kone_class->dev_attrs = kone_attributes; + kone_class->dev_bin_attrs = kone_bin_attributes; + + retval = hid_register_driver(&kone_driver); + if (retval) + class_destroy(kone_class); + return retval; } static void __exit kone_exit(void) { + class_destroy(kone_class); hid_unregister_driver(&kone_driver); } diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 130d6566ea8..64abb5b8a59 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h @@ -14,14 +14,11 @@ #include <linux/types.h> -#pragma pack(push) -#pragma pack(1) - struct kone_keystroke { uint8_t key; uint8_t action; uint16_t period; /* in milliseconds */ -}; +} __attribute__ ((__packed__)); enum kone_keystroke_buttons { kone_keystroke_button_1 = 0xf0, /* left mouse button */ @@ -44,7 +41,7 @@ struct kone_button_info { uint8_t macro_name[16]; /* can be max 15 chars long */ uint8_t count; struct kone_keystroke keystrokes[20]; -}; +} __attribute__ ((__packed__)); enum kone_button_info_types { /* valid button types until firmware 1.32 */ @@ -95,7 +92,7 @@ struct kone_light_info { uint8_t red; /* range 0x00-0xff */ uint8_t green; /* range 0x00-0xff */ uint8_t blue; /* range 0x00-0xff */ -}; +} __attribute__ ((__packed__)); struct kone_profile { uint16_t size; /* always 975 */ @@ -130,7 +127,7 @@ struct kone_profile { struct kone_button_info button_infos[8]; uint16_t checksum; /* \brief holds checksum of struct */ -}; +} __attribute__ ((__packed__)); enum kone_polling_rates { kone_polling_rate_125 = 1, @@ -147,7 +144,7 @@ struct kone_settings { uint8_t calibration_data[4]; uint8_t unknown3[2]; uint16_t checksum; -}; +} __attribute__ ((__packed__)); /* * 12 byte mouse event read by interrupt_read @@ -163,7 +160,7 @@ struct kone_mouse_event { uint8_t event; uint8_t value; /* press = 0, release = 1 */ uint8_t macro_key; /* 0 to 8 */ -}; +} __attribute__ ((__packed__)); enum kone_mouse_events { /* osd events are thought to be display on screen */ @@ -191,9 +188,7 @@ struct kone_roccat_report { uint8_t event; uint8_t value; /* holds dpi or profile value */ uint8_t key; /* macro key on overlong macro execution */ -}; - -#pragma pack(pop) +} __attribute__ ((__packed__)); struct kone_device { /* diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c new file mode 100644 index 00000000000..1608c8d1efd --- /dev/null +++ b/drivers/hid/hid-roccat-koneplus.c @@ -0,0 +1,837 @@ +/* + * Roccat Kone[+] driver for Linux + * + * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/* + * Roccat Kone[+] is an updated/improved version of the Kone with more memory + * and functionality and without the non-standard behaviours the Kone had. + */ + +#include <linux/device.h> +#include <linux/input.h> +#include <linux/hid.h> +#include <linux/usb.h> +#include <linux/module.h> +#include <linux/slab.h> +#include "hid-ids.h" +#include "hid-roccat.h" +#include "hid-roccat-koneplus.h" + +static uint profile_numbers[5] = {0, 1, 2, 3, 4}; + +static struct class *koneplus_class; + +static void koneplus_profile_activated(struct koneplus_device *koneplus, + uint new_profile) +{ + koneplus->actual_profile = new_profile; +} + +static int koneplus_send_control(struct usb_device *usb_dev, uint value, + enum koneplus_control_requests request) +{ + int len; + struct koneplus_control *control; + + if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || + request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && + value > 4) + return -EINVAL; + + control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL); + if (!control) + return -ENOMEM; + + control->command = KONEPLUS_COMMAND_CONTROL; + control->value = value; + control->request = request; + + len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), + USB_REQ_SET_CONFIGURATION, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, + KONEPLUS_USB_COMMAND_CONTROL, 0, control, + sizeof(struct koneplus_control), + USB_CTRL_SET_TIMEOUT); + + kfree(control); + + if (len != sizeof(struct koneplus_control)) + return len; + + return 0; +} + +static int koneplus_receive(struct usb_device *usb_dev, uint usb_command, + void *buf, uint size) { + int len; + + len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), + USB_REQ_CLEAR_FEATURE, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); + + return (len != size) ? -EIO : 0; +} + +static int koneplus_receive_control_status(struct usb_device *usb_dev) +{ + int retval; + struct koneplus_control *control; + + control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL); + if (!control) + return -ENOMEM; + + do { + retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, + control, sizeof(struct koneplus_control)); + + /* check if we get a completely wrong answer */ + if (retval) + goto out; + + if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) { + retval = 0; + goto out; + } + + /* indicates that hardware needs some more time to complete action */ + if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { + msleep(500); /* windows driver uses 1000 */ + continue; + } + + /* seems to be critical - replug necessary */ + if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) { + retval = -EINVAL; + goto out; + } + + dev_err(&usb_dev->dev, "koneplus_receive_control_status: " + "unknown response value 0x%x\n", control->value); + retval = -EINVAL; + goto out; + + } while (1); +out: + kfree(control); + return retval; +} + +static int koneplus_send(struct usb_device *usb_dev, uint command, + void *buf, uint size) { + int len; + + len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), + USB_REQ_SET_CONFIGURATION, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, + command, 0, buf, size, USB_CTRL_SET_TIMEOUT); + + if (len != size) + return -EIO; + + if (koneplus_receive_control_status(usb_dev)) + return -EIO; + + return 0; +} + +static int koneplus_select_profile(struct usb_device *usb_dev, uint number, + enum koneplus_control_requests request) +{ + int retval; + + retval = koneplus_send_control(usb_dev, number, request); + if (retval) + return retval; + + /* allow time to settle things - windows driver uses 500 */ + msleep(100); + + retval = koneplus_receive_control_status(usb_dev); + if (retval) + return retval; + + return 0; +} + +static int koneplus_get_info(struct usb_device *usb_dev, + struct koneplus_info *buf) +{ + return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO, + buf, sizeof(struct koneplus_info)); +} + +static int koneplus_get_profile_settings(struct usb_device *usb_dev, + struct koneplus_profile_settings *buf, uint number) +{ + int retval; + + retval = koneplus_select_profile(usb_dev, number, + KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); + if (retval) + return retval; + + return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, + buf, sizeof(struct koneplus_profile_settings)); +} + +static int koneplus_set_profile_settings(struct usb_device *usb_dev, + struct koneplus_profile_settings const *settings) +{ + return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, + (void *)settings, sizeof(struct koneplus_profile_settings)); +} + +static int koneplus_get_profile_buttons(struct usb_device *usb_dev, + struct koneplus_profile_buttons *buf, int number) +{ + int retval; + + retval = koneplus_select_profile(usb_dev, number, + KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); + if (retval) + return retval; + + return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, + buf, sizeof(struct koneplus_profile_buttons)); +} + +static int koneplus_set_profile_buttons(struct usb_device *usb_dev, + struct koneplus_profile_buttons const *buttons) +{ + return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, + (void *)buttons, sizeof(struct koneplus_profile_buttons)); +} + +/* retval is 0-4 on success, < 0 on error */ +static int koneplus_get_startup_profile(struct usb_device *usb_dev) +{ + struct koneplus_startup_profile *buf; + int retval; + + buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL); + + retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, + buf, sizeof(struct koneplus_startup_profile)); + + if (retval) + goto out; + + retval = buf->startup_profile; +out: + kfree(buf); + return retval; +} + +static int koneplus_set_startup_profile(struct usb_device *usb_dev, + int startup_profile) +{ + struct koneplus_startup_profile buf; + + buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE; + buf.size = sizeof(struct koneplus_startup_profile); + buf.startup_profile = startup_profile; + + return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, + (char *)&buf, sizeof(struct koneplus_profile_buttons)); +} + +static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, + char *buf, loff_t off, size_t count, + size_t real_size, uint command) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval; + + if (off != 0 || count != real_size) + return -EINVAL; + + mutex_lock(&koneplus->koneplus_lock); + retval = koneplus_receive(usb_dev, command, buf, real_size); + mutex_unlock(&koneplus->koneplus_lock); + + if (retval) + return retval; + + return real_size; +} + +static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, + void const *buf, loff_t off, size_t count, + size_t real_size, uint command) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval; + + if (off != 0 || count != real_size) + return -EINVAL; + + mutex_lock(&koneplus->koneplus_lock); + retval = koneplus_send(usb_dev, command, (void *)buf, real_size); + mutex_unlock(&koneplus->koneplus_lock); + + if (retval) + return retval; + + return real_size; +} + +static ssize_t koneplus_sysfs_write_macro(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + return koneplus_sysfs_write(fp, kobj, buf, off, count, + sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO); +} + +static ssize_t koneplus_sysfs_read_sensor(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + return koneplus_sysfs_read(fp, kobj, buf, off, count, + sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); +} + +static ssize_t koneplus_sysfs_write_sensor(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + return koneplus_sysfs_write(fp, kobj, buf, off, count, + sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); +} + +static ssize_t koneplus_sysfs_write_tcu(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + return koneplus_sysfs_write(fp, kobj, buf, off, count, + sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU); +} + +static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + return koneplus_sysfs_read(fp, kobj, buf, off, count, + sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU); +} + +static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); + + if (off >= sizeof(struct koneplus_profile_settings)) + return 0; + + if (off + count > sizeof(struct koneplus_profile_settings)) + count = sizeof(struct koneplus_profile_settings) - off; + + mutex_lock(&koneplus->koneplus_lock); + memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, + count); + mutex_unlock(&koneplus->koneplus_lock); + + return count; +} + +static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval = 0; + int difference; + int profile_number; + struct koneplus_profile_settings *profile_settings; + + if (off != 0 || count != sizeof(struct koneplus_profile_settings)) + return -EINVAL; + + profile_number = ((struct koneplus_profile_settings const *)buf)->number; + profile_settings = &koneplus->profile_settings[profile_number]; + + mutex_lock(&koneplus->koneplus_lock); + difference = memcmp(buf, profile_settings, + sizeof(struct koneplus_profile_settings)); + if (difference) { + retval = koneplus_set_profile_settings(usb_dev, + (struct koneplus_profile_settings const *)buf); + if (!retval) + memcpy(profile_settings, buf, + sizeof(struct koneplus_profile_settings)); + } + mutex_unlock(&koneplus->koneplus_lock); + + if (retval) + return retval; + + return sizeof(struct koneplus_profile_settings); +} + +static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); + + if (off >= sizeof(struct koneplus_profile_buttons)) + return 0; + + if (off + count > sizeof(struct koneplus_profile_buttons)) + count = sizeof(struct koneplus_profile_buttons) - off; + + mutex_lock(&koneplus->koneplus_lock); + memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, + count); + mutex_unlock(&koneplus->koneplus_lock); + + return count; +} + +static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval = 0; + int difference; + uint profile_number; + struct koneplus_profile_buttons *profile_buttons; + + if (off != 0 || count != sizeof(struct koneplus_profile_buttons)) + return -EINVAL; + + profile_number = ((struct koneplus_profile_buttons const *)buf)->number; + profile_buttons = &koneplus->profile_buttons[profile_number]; + + mutex_lock(&koneplus->koneplus_lock); + difference = memcmp(buf, profile_buttons, + sizeof(struct koneplus_profile_buttons)); + if (difference) { + retval = koneplus_set_profile_buttons(usb_dev, + (struct koneplus_profile_buttons const *)buf); + if (!retval) + memcpy(profile_buttons, buf, + sizeof(struct koneplus_profile_buttons)); + } + mutex_unlock(&koneplus->koneplus_lock); + + if (retval) + return retval; + + return sizeof(struct koneplus_profile_buttons); +} + +static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct koneplus_device *koneplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile); +} + +static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev, + struct device_attribute *attr, char const *buf, size_t size) +{ + struct koneplus_device *koneplus; + struct usb_device *usb_dev; + unsigned long profile; + int retval; + + dev = dev->parent->parent; + koneplus = hid_get_drvdata(dev_get_drvdata(dev)); + usb_dev = interface_to_usbdev(to_usb_interface(dev)); + + retval = strict_strtoul(buf, 10, &profile); + if (retval) + return retval; + + mutex_lock(&koneplus->koneplus_lock); + retval = koneplus_set_startup_profile(usb_dev, profile); + mutex_unlock(&koneplus->koneplus_lock); + if (retval) + return retval; + + return size; +} + +static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct koneplus_device *koneplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); +} + +static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct koneplus_device *koneplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version); +} + +static struct device_attribute koneplus_attributes[] = { + __ATTR(startup_profile, 0660, + koneplus_sysfs_show_startup_profile, + koneplus_sysfs_set_startup_profile), + __ATTR(actual_profile, 0440, + koneplus_sysfs_show_actual_profile, NULL), + __ATTR(firmware_version, 0440, + koneplus_sysfs_show_firmware_version, NULL), + __ATTR_NULL +}; + +static struct bin_attribute koneplus_bin_attributes[] = { + { + .attr = { .name = "sensor", .mode = 0220 }, + .size = sizeof(struct koneplus_sensor), + .read = koneplus_sysfs_read_sensor, + .write = koneplus_sysfs_write_sensor + }, + { + .attr = { .name = "tcu", .mode = 0220 }, + .size = sizeof(struct koneplus_tcu), + .write = koneplus_sysfs_write_tcu + }, + { + .attr = { .name = "tcu_image", .mode = 0440 }, + .size = sizeof(struct koneplus_tcu_image), + .read = koneplus_sysfs_read_tcu_image + }, + { + .attr = { .name = "profile_settings", .mode = 0220 }, + .size = sizeof(struct koneplus_profile_settings), + .write = koneplus_sysfs_write_profile_settings + }, + { + .attr = { .name = "profile1_settings", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_settings), + .read = koneplus_sysfs_read_profilex_settings, + .private = &profile_numbers[0] + }, + { + .attr = { .name = "profile2_settings", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_settings), + .read = koneplus_sysfs_read_profilex_settings, + .private = &profile_numbers[1] + }, + { + .attr = { .name = "profile3_settings", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_settings), + .read = koneplus_sysfs_read_profilex_settings, + .private = &profile_numbers[2] + }, + { + .attr = { .name = "profile4_settings", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_settings), + .read = koneplus_sysfs_read_profilex_settings, + .private = &profile_numbers[3] + }, + { + .attr = { .name = "profile5_settings", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_settings), + .read = koneplus_sysfs_read_profilex_settings, + .private = &profile_numbers[4] + }, + { + .attr = { .name = "profile_buttons", .mode = 0220 }, + .size = sizeof(struct koneplus_profile_buttons), + .write = koneplus_sysfs_write_profile_buttons + }, + { + .attr = { .name = "profile1_buttons", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_buttons), + .read = koneplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[0] + }, + { + .attr = { .name = "profile2_buttons", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_buttons), + .read = koneplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[1] + }, + { + .attr = { .name = "profile3_buttons", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_buttons), + .read = koneplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[2] + }, + { + .attr = { .name = "profile4_buttons", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_buttons), + .read = koneplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[3] + }, + { + .attr = { .name = "profile5_buttons", .mode = 0440 }, + .size = sizeof(struct koneplus_profile_buttons), + .read = koneplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[4] + }, + { + .attr = { .name = "macro", .mode = 0220 }, + .size = sizeof(struct koneplus_macro), + .write = koneplus_sysfs_write_macro + }, + __ATTR_NULL +}; + +static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, + struct koneplus_device *koneplus) +{ + int retval, i; + static uint wait = 70; /* device will freeze with just 60 */ + + mutex_init(&koneplus->koneplus_lock); + + koneplus->startup_profile = koneplus_get_startup_profile(usb_dev); + + msleep(wait); + retval = koneplus_get_info(usb_dev, &koneplus->info); + if (retval) + return retval; + + for (i = 0; i < 5; ++i) { + msleep(wait); + retval = koneplus_get_profile_settings(usb_dev, + &koneplus->profile_settings[i], i); + if (retval) + return retval; + + msleep(wait); + retval = koneplus_get_profile_buttons(usb_dev, + &koneplus->profile_buttons[i], i); + if (retval) + return retval; + } + + koneplus_profile_activated(koneplus, koneplus->startup_profile); + + return 0; +} + +static int koneplus_init_specials(struct hid_device *hdev) +{ + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct usb_device *usb_dev = interface_to_usbdev(intf); + struct koneplus_device *koneplus; + int retval; + + if (intf->cur_altsetting->desc.bInterfaceProtocol + == USB_INTERFACE_PROTOCOL_MOUSE) { + + koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); + if (!koneplus) { + dev_err(&hdev->dev, "can't alloc device descriptor\n"); + return -ENOMEM; + } + hid_set_drvdata(hdev, koneplus); + + retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); + if (retval) { + dev_err(&hdev->dev, + "couldn't init struct koneplus_device\n"); + goto exit_free; + } + + retval = roccat_connect(koneplus_class, hdev); + if (retval < 0) { + dev_err(&hdev->dev, "couldn't init char dev\n"); + } else { + koneplus->chrdev_minor = retval; + koneplus->roccat_claimed = 1; + } + } else { + hid_set_drvdata(hdev, NULL); + } + + return 0; +exit_free: + kfree(koneplus); + return retval; +} + +static void koneplus_remove_specials(struct hid_device *hdev) +{ + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct koneplus_device *koneplus; + + if (intf->cur_altsetting->desc.bInterfaceProtocol + == USB_INTERFACE_PROTOCOL_MOUSE) { + koneplus = hid_get_drvdata(hdev); + if (koneplus->roccat_claimed) + roccat_disconnect(koneplus->chrdev_minor); + kfree(koneplus); + } +} + +static int koneplus_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int retval; + + retval = hid_parse(hdev); + if (retval) { + dev_err(&hdev->dev, "parse failed\n"); + goto exit; + } + + retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (retval) { + dev_err(&hdev->dev, "hw start failed\n"); + goto exit; + } + + retval = koneplus_init_specials(hdev); + if (retval) { + dev_err(&hdev->dev, "couldn't install mouse\n"); + goto exit_stop; + } + + return 0; + +exit_stop: + hid_hw_stop(hdev); +exit: + return retval; +} + +static void koneplus_remove(struct hid_device *hdev) +{ + koneplus_remove_specials(hdev); + hid_hw_stop(hdev); +} + +static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, + u8 const *data) +{ + struct koneplus_mouse_report_button const *button_report; + + switch (data[0]) { + case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: + button_report = (struct koneplus_mouse_report_button const *)data; + switch (button_report->type) { + case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: + koneplus_profile_activated(koneplus, button_report->data1 - 1); + break; + } + break; + } +} + +static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, + u8 const *data) +{ + struct koneplus_roccat_report roccat_report; + struct koneplus_mouse_report_button const *button_report; + + if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) + return; + + button_report = (struct koneplus_mouse_report_button const *)data; + + if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || + button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && + button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) + return; + + roccat_report.type = button_report->type; + roccat_report.data1 = button_report->data1; + roccat_report.data2 = button_report->data2; + roccat_report.profile = koneplus->actual_profile + 1; + roccat_report_event(koneplus->chrdev_minor, + (uint8_t const *)&roccat_report, + sizeof(struct koneplus_roccat_report)); +} + +static int koneplus_raw_event(struct hid_device *hdev, + struct hid_report *report, u8 *data, int size) +{ + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct koneplus_device *koneplus = hid_get_drvdata(hdev); + + if (intf->cur_altsetting->desc.bInterfaceProtocol + != USB_INTERFACE_PROTOCOL_MOUSE) + return 0; + + koneplus_keep_values_up_to_date(koneplus, data); + + if (koneplus->roccat_claimed) + koneplus_report_to_chrdev(koneplus, data); + + return 0; +} + +static const struct hid_device_id koneplus_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, + { } +}; + +MODULE_DEVICE_TABLE(hid, koneplus_devices); + +static struct hid_driver koneplus_driver = { + .name = "koneplus", + .id_table = koneplus_devices, + .probe = koneplus_probe, + .remove = koneplus_remove, + .raw_event = koneplus_raw_event +}; + +static int __init koneplus_init(void) +{ + int retval; + + /* class name has to be same as driver name */ + koneplus_class = class_create(THIS_MODULE, "koneplus"); + if (IS_ERR(koneplus_class)) + return PTR_ERR(koneplus_class); + koneplus_class->dev_attrs = koneplus_attributes; + koneplus_class->dev_bin_attrs = koneplus_bin_attributes; + + retval = hid_register_driver(&koneplus_driver); + if (retval) + class_destroy(koneplus_class); + return retval; +} + +static void __exit koneplus_exit(void) +{ + class_destroy(koneplus_class); + hid_unregister_driver(&koneplus_driver); +} + +module_init(koneplus_init); +module_exit(koneplus_exit); + +MODULE_AUTHOR("Stefan Achatz"); +MODULE_DESCRIPTION("USB Roccat Kone[+] driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h new file mode 100644 index 00000000000..57a5c1ab7b0 --- /dev/null +++ b/drivers/hid/hid-roccat-koneplus.h @@ -0,0 +1,224 @@ +#ifndef __HID_ROCCAT_KONEPLUS_H +#define __HID_ROCCAT_KONEPLUS_H + +/* + * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include <linux/types.h> + +/* + * case 1: writes request 80 and reads value 1 + * + */ +struct koneplus_control { + uint8_t command; /* KONEPLUS_COMMAND_CONTROL */ + /* + * value is profile number in range 0-4 for requesting settings and buttons + * 1 if status ok for requesting status + */ + uint8_t value; + uint8_t request; +} __attribute__ ((__packed__)); + +enum koneplus_control_requests { + KONEPLUS_CONTROL_REQUEST_STATUS = 0x00, + KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80, + KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90, +}; + +enum koneplus_control_values { + KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, + KONEPLUS_CONTROL_REQUEST_STATUS_OK = 1, + KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, +}; + +struct koneplus_startup_profile { + uint8_t command; /* KONEPLUS_COMMAND_STARTUP_PROFILE */ + uint8_t size; /* always 3 */ + uint8_t startup_profile; /* Range 0-4! */ +} __attribute__ ((__packed__)); + +struct koneplus_profile_settings { + uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */ + uint8_t size; /* always 43 */ + uint8_t number; /* range 0-4 */ + uint8_t advanced_sensitivity; + uint8_t sensitivity_x; + uint8_t sensitivity_y; + uint8_t cpi_levels_enabled; + uint8_t cpi_levels_x[5]; + uint8_t cpi_startup_level; /* range 0-4 */ + uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */ + uint8_t unknown1; + uint8_t polling_rate; + uint8_t lights_enabled; + uint8_t light_effect_mode; + uint8_t color_flow_effect; + uint8_t light_effect_type; + uint8_t light_effect_speed; + uint8_t lights[16]; + uint16_t checksum; +} __attribute__ ((__packed__)); + +struct koneplus_profile_buttons { + uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */ + uint8_t size; /* always 77 */ + uint8_t number; /* range 0-4 */ + uint8_t data[72]; + uint16_t checksum; +} __attribute__ ((__packed__)); + +struct koneplus_macro { + uint8_t command; /* KONEPLUS_COMMAND_MACRO */ + uint16_t size; /* always 0x822 little endian */ + uint8_t profile; /* range 0-4 */ + uint8_t button; /* range 0-23 */ + uint8_t data[2075]; + uint16_t checksum; +} __attribute__ ((__packed__)); + +struct koneplus_info { + uint8_t command; /* KONEPLUS_COMMAND_INFO */ + uint8_t size; /* always 6 */ + uint8_t firmware_version; + uint8_t unknown[3]; +} __attribute__ ((__packed__)); + +struct koneplus_e { + uint8_t command; /* KONEPLUS_COMMAND_E */ + uint8_t size; /* always 3 */ + uint8_t unknown; /* TODO 1; 0 before firmware update */ +} __attribute__ ((__packed__)); + +struct koneplus_sensor { + uint8_t command; /* KONEPLUS_COMMAND_SENSOR */ + uint8_t size; /* always 6 */ + uint8_t data[4]; +} __attribute__ ((__packed__)); + +struct koneplus_firmware_write { + uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */ + uint8_t unknown[1025]; +} __attribute__ ((__packed__)); + +struct koneplus_firmware_write_control { + uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */ + /* + * value is 1 on success + * 3 means "not finished yet" + */ + uint8_t value; + uint8_t unknown; /* always 0x75 */ +} __attribute__ ((__packed__)); + +struct koneplus_tcu { + uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */ + uint8_t data[2]; +} __attribute__ ((__packed__)); + +struct koneplus_tcu_image { + uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */ + uint8_t data[1024]; + uint16_t checksum; +} __attribute__ ((__packed__)); + +enum koneplus_commands { + KONEPLUS_COMMAND_CONTROL = 0x4, + KONEPLUS_COMMAND_STARTUP_PROFILE = 0x5, + KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, + KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, + KONEPLUS_COMMAND_MACRO = 0x8, + KONEPLUS_COMMAND_INFO = 0x9, + KONEPLUS_COMMAND_E = 0xe, + KONEPLUS_COMMAND_SENSOR = 0xf, + KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b, + KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, +}; + +enum koneplus_usb_commands { + KONEPLUS_USB_COMMAND_CONTROL = 0x304, + KONEPLUS_USB_COMMAND_STARTUP_PROFILE = 0x305, + KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306, + KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307, + KONEPLUS_USB_COMMAND_MACRO = 0x308, + KONEPLUS_USB_COMMAND_INFO = 0x309, + KONEPLUS_USB_COMMAND_TCU = 0x30c, + KONEPLUS_USB_COMMAND_E = 0x30e, + KONEPLUS_USB_COMMAND_SENSOR = 0x30f, + KONEPLUS_USB_COMMAND_FIRMWARE_WRITE = 0x31b, + KONEPLUS_USB_COMMAND_FIRMWARE_WRITE_CONTROL = 0x31c, +}; + +enum koneplus_mouse_report_numbers { + KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1, + KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, + KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3, +}; + +struct koneplus_mouse_report_button { + uint8_t report_number; /* always KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON */ + uint8_t zero1; + uint8_t type; + uint8_t data1; + uint8_t data2; + uint8_t zero2; + uint8_t unknown[2]; +} __attribute__ ((__packed__)); + +enum koneplus_mouse_report_button_types { + /* data1 = new profile range 1-5 */ + KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20, + + /* data1 = button number range 1-24; data2 = action */ + KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60, + + /* data1 = button number range 1-24; data2 = action */ + KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80, + + /* data1 = setting number range 1-5 */ + KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0, + + /* data1 and data2 = range 0x1-0xb */ + KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0, + + /* data1 = 22 = next track... + * data2 = action + */ + KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, +}; + +enum koneplus_mouse_report_button_action { + KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0, + KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1, +}; + +struct koneplus_roccat_report { + uint8_t type; + uint8_t data1; + uint8_t data2; + uint8_t profile; +} __attribute__ ((__packed__)); + +struct koneplus_device { + int actual_profile; + + int roccat_claimed; + int chrdev_minor; + + struct mutex koneplus_lock; + + int startup_profile; + struct koneplus_info info; + struct koneplus_profile_settings profile_settings[5]; + struct koneplus_profile_buttons profile_buttons[5]; +}; + +#endif diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 9bf23047892..02c58e015be 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c @@ -27,6 +27,11 @@ #include "hid-roccat.h" #include "hid-roccat-pyra.h" +static uint profile_numbers[5] = {0, 1, 2, 3, 4}; + +/* pyra_class is used for creating sysfs attributes via roccat char device */ +static struct class *pyra_class; + static void profile_activated(struct pyra_device *pyra, unsigned int new_profile) { @@ -87,9 +92,8 @@ static int pyra_receive_control_status(struct usb_device *usb_dev) control.value == 1) return 0; else { - dev_err(&usb_dev->dev, "receive control status: " - "unknown response 0x%x 0x%x\n", - control.request, control.value); + hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n", + control.request, control.value); return -EINVAL; } } @@ -221,9 +225,10 @@ static int pyra_set_settings(struct usb_device *usb_dev, static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count, int number) + loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); if (off >= sizeof(struct pyra_profile_settings)) @@ -233,58 +238,19 @@ static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, count = sizeof(struct pyra_profile_settings) - off; mutex_lock(&pyra->pyra_lock); - memcpy(buf, ((char const *)&pyra->profile_settings[number]) + off, + memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off, count); mutex_unlock(&pyra->pyra_lock); return count; } -static ssize_t pyra_sysfs_read_profile1_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_settings(fp, kobj, - attr, buf, off, count, 0); -} - -static ssize_t pyra_sysfs_read_profile2_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_settings(fp, kobj, - attr, buf, off, count, 1); -} - -static ssize_t pyra_sysfs_read_profile3_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_settings(fp, kobj, - attr, buf, off, count, 2); -} - -static ssize_t pyra_sysfs_read_profile4_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_settings(fp, kobj, - attr, buf, off, count, 3); -} - -static ssize_t pyra_sysfs_read_profile5_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_settings(fp, kobj, - attr, buf, off, count, 4); -} - static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count, int number) + loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); if (off >= sizeof(struct pyra_profile_buttons)) @@ -294,58 +260,19 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, count = sizeof(struct pyra_profile_buttons) - off; mutex_lock(&pyra->pyra_lock); - memcpy(buf, ((char const *)&pyra->profile_buttons[number]) + off, + memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off, count); mutex_unlock(&pyra->pyra_lock); return count; } -static ssize_t pyra_sysfs_read_profile1_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_buttons(fp, kobj, - attr, buf, off, count, 0); -} - -static ssize_t pyra_sysfs_read_profile2_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_buttons(fp, kobj, - attr, buf, off, count, 1); -} - -static ssize_t pyra_sysfs_read_profile3_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_buttons(fp, kobj, - attr, buf, off, count, 2); -} - -static ssize_t pyra_sysfs_read_profile4_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_buttons(fp, kobj, - attr, buf, off, count, 3); -} - -static ssize_t pyra_sysfs_read_profile5_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return pyra_sysfs_read_profilex_buttons(fp, kobj, - attr, buf, off, count, 4); -} - static ssize_t pyra_sysfs_write_profile_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval = 0; @@ -381,7 +308,8 @@ static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval = 0; @@ -417,7 +345,8 @@ static ssize_t pyra_sysfs_read_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); if (off >= sizeof(struct pyra_settings)) @@ -437,7 +366,8 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); int retval = 0; @@ -469,255 +399,125 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp, static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev, struct device_attribute *attr, char *buf) { - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); + struct pyra_device *pyra = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi); } static ssize_t pyra_sysfs_show_actual_profile(struct device *dev, struct device_attribute *attr, char *buf) { - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); + struct pyra_device *pyra = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile); } static ssize_t pyra_sysfs_show_firmware_version(struct device *dev, struct device_attribute *attr, char *buf) { - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); + struct pyra_device *pyra = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version); } static ssize_t pyra_sysfs_show_startup_profile(struct device *dev, struct device_attribute *attr, char *buf) { - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); + struct pyra_device *pyra = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile); } -static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL); - -static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL); - -static DEVICE_ATTR(firmware_version, 0440, - pyra_sysfs_show_firmware_version, NULL); - -static DEVICE_ATTR(startup_profile, 0440, - pyra_sysfs_show_startup_profile, NULL); - -static struct attribute *pyra_attributes[] = { - &dev_attr_actual_cpi.attr, - &dev_attr_actual_profile.attr, - &dev_attr_firmware_version.attr, - &dev_attr_startup_profile.attr, - NULL -}; - -static struct attribute_group pyra_attribute_group = { - .attrs = pyra_attributes +static struct device_attribute pyra_attributes[] = { + __ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL), + __ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL), + __ATTR(firmware_version, 0440, + pyra_sysfs_show_firmware_version, NULL), + __ATTR(startup_profile, 0440, + pyra_sysfs_show_startup_profile, NULL), + __ATTR_NULL }; -static struct bin_attribute pyra_profile_settings_attr = { +static struct bin_attribute pyra_bin_attributes[] = { + { .attr = { .name = "profile_settings", .mode = 0220 }, .size = sizeof(struct pyra_profile_settings), .write = pyra_sysfs_write_profile_settings -}; - -static struct bin_attribute pyra_profile1_settings_attr = { + }, + { .attr = { .name = "profile1_settings", .mode = 0440 }, .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profile1_settings -}; - -static struct bin_attribute pyra_profile2_settings_attr = { + .read = pyra_sysfs_read_profilex_settings, + .private = &profile_numbers[0] + }, + { .attr = { .name = "profile2_settings", .mode = 0440 }, .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profile2_settings -}; - -static struct bin_attribute pyra_profile3_settings_attr = { + .read = pyra_sysfs_read_profilex_settings, + .private = &profile_numbers[1] + }, + { .attr = { .name = "profile3_settings", .mode = 0440 }, .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profile3_settings -}; - -static struct bin_attribute pyra_profile4_settings_attr = { + .read = pyra_sysfs_read_profilex_settings, + .private = &profile_numbers[2] + }, + { .attr = { .name = "profile4_settings", .mode = 0440 }, .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profile4_settings -}; - -static struct bin_attribute pyra_profile5_settings_attr = { + .read = pyra_sysfs_read_profilex_settings, + .private = &profile_numbers[3] + }, + { .attr = { .name = "profile5_settings", .mode = 0440 }, .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profile5_settings -}; - -static struct bin_attribute pyra_profile_buttons_attr = { + .read = pyra_sysfs_read_profilex_settings, + .private = &profile_numbers[4] + }, + { .attr = { .name = "profile_buttons", .mode = 0220 }, .size = sizeof(struct pyra_profile_buttons), .write = pyra_sysfs_write_profile_buttons -}; - -static struct bin_attribute pyra_profile1_buttons_attr = { + }, + { .attr = { .name = "profile1_buttons", .mode = 0440 }, .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profile1_buttons -}; - -static struct bin_attribute pyra_profile2_buttons_attr = { + .read = pyra_sysfs_read_profilex_buttons, + .private = &profile_numbers[0] + }, + { .attr = { .name = "profile2_buttons", .mode = 0440 }, .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profile2_buttons -}; - -static struct bin_attribute pyra_profile3_buttons_attr = { + .read = pyra_sysfs_read_profilex_buttons, + .private = &profile_numbers[1] + }, + { .attr = { .name = "profile3_buttons", .mode = 0440 }, .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profile3_buttons -}; - -static struct bin_attribute pyra_profile4_buttons_attr = { + .read = pyra_sysfs_read_profilex_buttons, + .private = &profile_numbers[2] + }, + { .attr = { .name = "profile4_buttons", .mode = 0440 }, .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profile4_buttons -}; - -static struct bin_attribute pyra_profile5_buttons_attr = { + .read = pyra_sysfs_read_profilex_buttons, + .private = &profile_numbers[3] + }, + { .attr = { .name = "profile5_buttons", .mode = 0440 }, .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profile5_buttons -}; - -static struct bin_attribute pyra_settings_attr = { + .read = pyra_sysfs_read_profilex_buttons, + .private = &profile_numbers[4] + }, + { .attr = { .name = "settings", .mode = 0660 }, .size = sizeof(struct pyra_settings), .read = pyra_sysfs_read_settings, .write = pyra_sysfs_write_settings + }, + __ATTR_NULL }; -static int pyra_create_sysfs_attributes(struct usb_interface *intf) -{ - int retval; - - retval = sysfs_create_group(&intf->dev.kobj, &pyra_attribute_group); - if (retval) - goto exit_1; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile_settings_attr); - if (retval) - goto exit_2; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile1_settings_attr); - if (retval) - goto exit_3; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile2_settings_attr); - if (retval) - goto exit_4; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile3_settings_attr); - if (retval) - goto exit_5; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile4_settings_attr); - if (retval) - goto exit_6; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile5_settings_attr); - if (retval) - goto exit_7; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile_buttons_attr); - if (retval) - goto exit_8; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile1_buttons_attr); - if (retval) - goto exit_9; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile2_buttons_attr); - if (retval) - goto exit_10; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile3_buttons_attr); - if (retval) - goto exit_11; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile4_buttons_attr); - if (retval) - goto exit_12; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_profile5_buttons_attr); - if (retval) - goto exit_13; - - retval = sysfs_create_bin_file(&intf->dev.kobj, - &pyra_settings_attr); - if (retval) - goto exit_14; - - return 0; - -exit_14: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr); -exit_13: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr); -exit_12: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr); -exit_11: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr); -exit_10: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr); -exit_9: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr); -exit_8: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr); -exit_7: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr); -exit_6: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr); -exit_5: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr); -exit_4: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr); -exit_3: - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr); -exit_2: - sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group); -exit_1: - return retval; -} - -static void pyra_remove_sysfs_attributes(struct usb_interface *intf) -{ - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_settings_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr); - sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr); - sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group); -} - static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, struct pyra_device *pyra) { @@ -770,31 +570,24 @@ static int pyra_init_specials(struct hid_device *hdev) pyra = kzalloc(sizeof(*pyra), GFP_KERNEL); if (!pyra) { - dev_err(&hdev->dev, "can't alloc device descriptor\n"); + hid_err(hdev, "can't alloc device descriptor\n"); return -ENOMEM; } hid_set_drvdata(hdev, pyra); retval = pyra_init_pyra_device_struct(usb_dev, pyra); if (retval) { - dev_err(&hdev->dev, - "couldn't init struct pyra_device\n"); + hid_err(hdev, "couldn't init struct pyra_device\n"); goto exit_free; } - retval = roccat_connect(hdev); + retval = roccat_connect(pyra_class, hdev); if (retval < 0) { - dev_err(&hdev->dev, "couldn't init char dev\n"); + hid_err(hdev, "couldn't init char dev\n"); } else { pyra->chrdev_minor = retval; pyra->roccat_claimed = 1; } - - retval = pyra_create_sysfs_attributes(intf); - if (retval) { - dev_err(&hdev->dev, "cannot create sysfs files\n"); - goto exit_free; - } } else { hid_set_drvdata(hdev, NULL); } @@ -812,7 +605,6 @@ static void pyra_remove_specials(struct hid_device *hdev) if (intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) { - pyra_remove_sysfs_attributes(intf); pyra = hid_get_drvdata(hdev); if (pyra->roccat_claimed) roccat_disconnect(pyra->chrdev_minor); @@ -826,19 +618,19 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) retval = hid_parse(hdev); if (retval) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto exit; } retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (retval) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto exit; } retval = pyra_init_specials(hdev); if (retval) { - dev_err(&hdev->dev, "couldn't install mouse\n"); + hid_err(hdev, "couldn't install mouse\n"); goto exit_stop; } return 0; @@ -952,11 +744,24 @@ static struct hid_driver pyra_driver = { static int __init pyra_init(void) { - return hid_register_driver(&pyra_driver); + int retval; + + /* class name has to be same as driver name */ + pyra_class = class_create(THIS_MODULE, "pyra"); + if (IS_ERR(pyra_class)) + return PTR_ERR(pyra_class); + pyra_class->dev_attrs = pyra_attributes; + pyra_class->dev_bin_attrs = pyra_bin_attributes; + + retval = hid_register_driver(&pyra_driver); + if (retval) + class_destroy(pyra_class); + return retval; } static void __exit pyra_exit(void) { + class_destroy(pyra_class); hid_unregister_driver(&pyra_driver); } diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h index 22f80a8f26f..14cbbe1621e 100644 --- a/drivers/hid/hid-roccat-pyra.h +++ b/drivers/hid/hid-roccat-pyra.h @@ -14,14 +14,11 @@ #include <linux/types.h> -#pragma pack(push) -#pragma pack(1) - struct pyra_b { uint8_t command; /* PYRA_COMMAND_B */ uint8_t size; /* always 3 */ uint8_t unknown; /* 1 */ -}; +} __attribute__ ((__packed__)); struct pyra_control { uint8_t command; /* PYRA_COMMAND_CONTROL */ @@ -31,7 +28,7 @@ struct pyra_control { */ uint8_t value; /* Range 0-4 */ uint8_t request; -}; +} __attribute__ ((__packed__)); enum pyra_control_requests { PYRA_CONTROL_REQUEST_STATUS = 0x00, @@ -43,7 +40,7 @@ struct pyra_settings { uint8_t command; /* PYRA_COMMAND_SETTINGS */ uint8_t size; /* always 3 */ uint8_t startup_profile; /* Range 0-4! */ -}; +} __attribute__ ((__packed__)); struct pyra_profile_settings { uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */ @@ -58,7 +55,7 @@ struct pyra_profile_settings { uint8_t light_effect; uint8_t handedness; uint16_t checksum; /* byte sum */ -}; +} __attribute__ ((__packed__)); struct pyra_profile_buttons { uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */ @@ -66,7 +63,7 @@ struct pyra_profile_buttons { uint8_t number; /* Range 0-4 */ uint8_t buttons[14]; uint16_t checksum; /* byte sum */ -}; +} __attribute__ ((__packed__)); struct pyra_info { uint8_t command; /* PYRA_COMMAND_INFO */ @@ -75,7 +72,7 @@ struct pyra_info { uint8_t unknown1; /* always 0 */ uint8_t unknown2; /* always 1 */ uint8_t unknown3; /* always 0 */ -}; +} __attribute__ ((__packed__)); enum pyra_commands { PYRA_COMMAND_CONTROL = 0x4, @@ -107,13 +104,13 @@ struct pyra_mouse_event_button { uint8_t type; uint8_t data1; uint8_t data2; -}; +} __attribute__ ((__packed__)); struct pyra_mouse_event_audio { uint8_t report_number; /* always 2 */ uint8_t type; uint8_t unused; /* always 0 */ -}; +} __attribute__ ((__packed__)); /* hid audio controls */ enum pyra_mouse_event_audio_types { @@ -167,9 +164,7 @@ struct pyra_roccat_report { uint8_t type; uint8_t value; uint8_t key; -}; - -#pragma pack(pop) +} __attribute__ ((__packed__)); struct pyra_device { int actual_profile; diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index 5a6879e235a..a14c579ea78 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -21,6 +21,8 @@ * It is inspired by hidraw, but uses only one circular buffer for all readers. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/cdev.h> #include <linux/poll.h> #include <linux/sched.h> @@ -65,7 +67,6 @@ struct roccat_reader { }; static int roccat_major; -static struct class *roccat_class; static struct cdev roccat_cdev; static struct roccat_device *devices[ROCCAT_MAX_DEVICES]; @@ -165,27 +166,22 @@ static int roccat_open(struct inode *inode, struct file *file) mutex_lock(&device->readers_lock); if (!device) { - printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", - minor); + pr_emerg("roccat device with minor %d doesn't exist\n", minor); error = -ENODEV; goto exit_err; } if (!device->open++) { /* power on device on adding first reader */ - if (device->hid->ll_driver->power) { - error = device->hid->ll_driver->power(device->hid, - PM_HINT_FULLON); - if (error < 0) { - --device->open; - goto exit_err; - } + error = hid_hw_power(device->hid, PM_HINT_FULLON); + if (error < 0) { + --device->open; + goto exit_err; } - error = device->hid->ll_driver->open(device->hid); + + error = hid_hw_open(device->hid); if (error < 0) { - if (device->hid->ll_driver->power) - device->hid->ll_driver->power(device->hid, - PM_HINT_NORMAL); + hid_hw_power(device->hid, PM_HINT_NORMAL); --device->open; goto exit_err; } @@ -218,8 +214,7 @@ static int roccat_release(struct inode *inode, struct file *file) device = devices[minor]; if (!device) { mutex_unlock(&devices_lock); - printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", - minor); + pr_emerg("roccat device with minor %d doesn't exist\n", minor); return -ENODEV; } @@ -231,10 +226,8 @@ static int roccat_release(struct inode *inode, struct file *file) if (!--device->open) { /* removing last reader */ if (device->exist) { - if (device->hid->ll_driver->power) - device->hid->ll_driver->power(device->hid, - PM_HINT_NORMAL); - device->hid->ll_driver->close(device->hid); + hid_hw_power(device->hid, PM_HINT_NORMAL); + hid_hw_close(device->hid); } else { kfree(device); } @@ -295,12 +288,14 @@ EXPORT_SYMBOL_GPL(roccat_report_event); /* * roccat_connect() - create a char device for special event output + * @class: the class thats used to create the device. Meant to hold device + * specific sysfs attributes. * @hid: the hid device the char device should be connected to. * * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on * success, a negative error code on failure. */ -int roccat_connect(struct hid_device *hid) +int roccat_connect(struct class *klass, struct hid_device *hid) { unsigned int minor; struct roccat_device *device; @@ -326,7 +321,7 @@ int roccat_connect(struct hid_device *hid) return -EINVAL; } - device->dev = device_create(roccat_class, &hid->dev, + device->dev = device_create(klass, &hid->dev, MKDEV(roccat_major, minor), NULL, "%s%s%d", "roccat", hid->driver->name, minor); @@ -367,10 +362,10 @@ void roccat_disconnect(int minor) device->exist = 0; /* TODO exist maybe not needed */ - device_destroy(roccat_class, MKDEV(roccat_major, minor)); + device_destroy(device->dev->class, MKDEV(roccat_major, minor)); if (device->open) { - device->hid->ll_driver->close(device->hid); + hid_hw_close(device->hid); wake_up_interruptible(&device->wait); } else { kfree(device); @@ -398,14 +393,7 @@ static int __init roccat_init(void) roccat_major = MAJOR(dev_id); if (retval < 0) { - printk(KERN_WARNING "roccat: can't get major number\n"); - return retval; - } - - roccat_class = class_create(THIS_MODULE, "roccat"); - if (IS_ERR(roccat_class)) { - retval = PTR_ERR(roccat_class); - unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); + pr_warn("can't get major number\n"); return retval; } @@ -420,7 +408,6 @@ static void __exit roccat_exit(void) dev_t dev_id = MKDEV(roccat_major, 0); cdev_del(&roccat_cdev); - class_destroy(roccat_class); unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); } diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h index 09e864e9f79..5784281d613 100644 --- a/drivers/hid/hid-roccat.h +++ b/drivers/hid/hid-roccat.h @@ -16,11 +16,12 @@ #include <linux/types.h> #if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE) -int roccat_connect(struct hid_device *hid); +int roccat_connect(struct class *klass, struct hid_device *hid); void roccat_disconnect(int minor); int roccat_report_event(int minor, u8 const *data, int len); #else -static inline int roccat_connect(struct hid_device *hid) { return -1; } +static inline int roccat_connect(struct class *klass, + struct hid_device *hid) { return -1; } static inline void roccat_disconnect(int minor) {} static inline int roccat_report_event(int minor, u8 const *data, int len) { diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index 35894444e00..3c1fd8af5e0 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c @@ -57,8 +57,8 @@ static inline void samsung_irda_dev_trace(struct hid_device *hdev, unsigned int rsize) { - dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " - "descriptor\n", rsize); + hid_info(hdev, "fixing up Samsung IrDA %d byte report descriptor\n", + rsize); } static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, @@ -160,7 +160,7 @@ static int samsung_probe(struct hid_device *hdev, ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } @@ -174,7 +174,7 @@ static int samsung_probe(struct hid_device *hdev, ret = hid_hw_start(hdev, cmask); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c index e10a7687ebf..16f7cafc969 100644 --- a/drivers/hid/hid-sjoy.c +++ b/drivers/hid/hid-sjoy.c @@ -74,26 +74,25 @@ static int sjoyff_init(struct hid_device *hid) int error; if (list_empty(report_list)) { - dev_err(&hid->dev, "no output reports found\n"); + hid_err(hid, "no output reports found\n"); return -ENODEV; } report_ptr = report_ptr->next; if (report_ptr == report_list) { - dev_err(&hid->dev, "required output report is " - "missing\n"); + hid_err(hid, "required output report is missing\n"); return -ENODEV; } report = list_entry(report_ptr, struct hid_report, list); if (report->maxfield < 1) { - dev_err(&hid->dev, "no fields in the report\n"); + hid_err(hid, "no fields in the report\n"); return -ENODEV; } if (report->field[0]->report_count < 3) { - dev_err(&hid->dev, "not enough values in the field\n"); + hid_err(hid, "not enough values in the field\n"); return -ENODEV; } @@ -117,8 +116,7 @@ static int sjoyff_init(struct hid_device *hid) sjoyff->report->field[0]->value[2] = 0x00; usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); - dev_info(&hid->dev, - "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); + hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); return 0; } @@ -135,13 +133,13 @@ static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err; } diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 677bb3da10e..68d7b36e31e 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -40,8 +40,7 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { - dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " - "descriptor\n"); + hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n"); rdesc[55] = 0x06; } return rdesc; @@ -89,7 +88,7 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) (3 << 8) | 0xf2, ifnum, buf, 17, USB_CTRL_GET_TIMEOUT); if (ret < 0) - dev_err(&hdev->dev, "can't set operational mode\n"); + hid_err(hdev, "can't set operational mode\n"); kfree(buf); @@ -110,7 +109,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) sc = kzalloc(sizeof(*sc), GFP_KERNEL); if (sc == NULL) { - dev_err(&hdev->dev, "can't alloc sony descriptor\n"); + hid_err(hdev, "can't alloc sony descriptor\n"); return -ENOMEM; } @@ -119,14 +118,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c index 3171be28c3d..b2be1d11916 100644 --- a/drivers/hid/hid-stantum.c +++ b/drivers/hid/hid-stantum.c @@ -222,7 +222,7 @@ static int stantum_probe(struct hid_device *hdev, sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL); if (!sd) { - dev_err(&hdev->dev, "cannot allocate Stantum data\n"); + hid_err(hdev, "cannot allocate Stantum data\n"); return -ENOMEM; } sd->valid = false; diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index 164ed568f6c..d484a0043dd 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c @@ -27,8 +27,7 @@ static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, { if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && rdesc[106] == 0x03) { - dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop " - "report descriptor\n"); + hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n"); rdesc[105] = rdesc[110] = 0x03; rdesc[106] = rdesc[111] = 0x21; } diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index 25be4e1461b..575862b0688 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c @@ -151,28 +151,23 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) switch (field->usage[0].hid) { case THRUSTMASTER_USAGE_FF: if (field->report_count < 2) { - dev_warn(&hid->dev, "ignoring FF field " - "with report_count < 2\n"); + hid_warn(hid, "ignoring FF field with report_count < 2\n"); continue; } if (field->logical_maximum == field->logical_minimum) { - dev_warn(&hid->dev, "ignoring FF field " - "with logical_maximum " - "== logical_minimum\n"); + hid_warn(hid, "ignoring FF field with logical_maximum == logical_minimum\n"); continue; } if (tmff->report && tmff->report != report) { - dev_warn(&hid->dev, "ignoring FF field " - "in other report\n"); + hid_warn(hid, "ignoring FF field in other report\n"); continue; } if (tmff->ff_field && tmff->ff_field != field) { - dev_warn(&hid->dev, "ignoring " - "duplicate FF field\n"); + hid_warn(hid, "ignoring duplicate FF field\n"); continue; } @@ -185,16 +180,15 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) break; default: - dev_warn(&hid->dev, "ignoring unknown output " - "usage %08x\n", - field->usage[0].hid); + hid_warn(hid, "ignoring unknown output usage %08x\n", + field->usage[0].hid); continue; } } } if (!tmff->report) { - dev_err(&hid->dev, "can't find FF field in output reports\n"); + hid_err(hid, "can't find FF field in output reports\n"); error = -ENODEV; goto fail; } @@ -203,8 +197,7 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) if (error) goto fail; - dev_info(&hid->dev, "force feedback for ThrustMaster devices by Zinx " - "Verituse <zinx@epicsol.org>"); + hid_info(hid, "force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>\n"); return 0; fail: @@ -224,13 +217,13 @@ static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err; } diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 956ed9ac19d..613ff7b1d74 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c @@ -66,6 +66,7 @@ static const struct hid_device_id ts_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, { } }; MODULE_DEVICE_TABLE(hid, ts_devices); diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 724f46ed612..06888323828 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -18,6 +18,8 @@ * any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/device.h> #include <linux/hid.h> #include <linux/module.h> @@ -141,8 +143,8 @@ static void wacom_poke(struct hid_device *hdev, u8 speed) * Note that if the raw queries fail, it's not a hard failure and it * is safe to continue */ - dev_warn(&hdev->dev, "failed to poke device, command %d, err %d\n", - rep_data[0], ret); + hid_warn(hdev, "failed to poke device, command %d, err %d\n", + rep_data[0], ret); return; } @@ -172,7 +174,7 @@ static ssize_t wacom_store_speed(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(speed, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, wacom_show_speed, wacom_store_speed); static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, @@ -312,7 +314,7 @@ static int wacom_probe(struct hid_device *hdev, wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); if (wdata == NULL) { - dev_err(&hdev->dev, "can't alloc wacom descriptor\n"); + hid_err(hdev, "can't alloc wacom descriptor\n"); return -ENOMEM; } @@ -321,20 +323,20 @@ static int wacom_probe(struct hid_device *hdev, /* Parse the HID report now */ ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } ret = device_create_file(&hdev->dev, &dev_attr_speed); if (ret) - dev_warn(&hdev->dev, - "can't create sysfs speed attribute err: %d\n", ret); + hid_warn(hdev, + "can't create sysfs speed attribute err: %d\n", ret); /* Set Wacom mode 2 with high reporting speed */ wacom_poke(hdev, 1); @@ -349,8 +351,8 @@ static int wacom_probe(struct hid_device *hdev, ret = power_supply_register(&hdev->dev, &wdata->battery); if (ret) { - dev_warn(&hdev->dev, - "can't create sysfs battery attribute, err: %d\n", ret); + hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n", + ret); /* * battery attribute is not critical for the tablet, but if it * failed then there is no need to create ac attribute @@ -367,8 +369,8 @@ static int wacom_probe(struct hid_device *hdev, ret = power_supply_register(&hdev->dev, &wdata->ac); if (ret) { - dev_warn(&hdev->dev, - "can't create ac battery attribute, err: %d\n", ret); + hid_warn(hdev, + "can't create ac battery attribute, err: %d\n", ret); /* * ac attribute is not critical for the tablet, but if it * failed then we don't want to battery attribute to exist @@ -454,7 +456,7 @@ static int __init wacom_init(void) ret = hid_register_driver(&wacom_driver); if (ret) - printk(KERN_ERR "can't register wacom driver\n"); + pr_err("can't register wacom driver\n"); return ret; } diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index b7acceabba8..f31fab012f2 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -75,14 +75,14 @@ static int zpff_init(struct hid_device *hid) int error; if (list_empty(report_list)) { - dev_err(&hid->dev, "no output report found\n"); + hid_err(hid, "no output report found\n"); return -ENODEV; } report = list_entry(report_list->next, struct hid_report, list); if (report->maxfield < 4) { - dev_err(&hid->dev, "not enough fields in report\n"); + hid_err(hid, "not enough fields in report\n"); return -ENODEV; } @@ -105,8 +105,7 @@ static int zpff_init(struct hid_device *hid) zpff->report->field[3]->value[0] = 0x00; usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); - dev_info(&hid->dev, "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"); return 0; } @@ -123,13 +122,13 @@ static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err; } diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c index aac1f927314..e90371508fd 100644 --- a/drivers/hid/hid-zydacron.c +++ b/drivers/hid/hid-zydacron.c @@ -34,9 +34,8 @@ static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff && rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff && rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) { - dev_info(&hdev->dev, - "fixing up zydacron remote control report " - "descriptor\n"); + hid_info(hdev, + "fixing up zydacron remote control report descriptor\n"); rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c; rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00; } @@ -172,7 +171,7 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id) zc = kzalloc(sizeof(*zc), GFP_KERNEL); if (zc == NULL) { - dev_err(&hdev->dev, "zydacron: can't alloc descriptor\n"); + hid_err(hdev, "can't alloc descriptor\n"); return -ENOMEM; } @@ -180,13 +179,13 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { - dev_err(&hdev->dev, "zydacron: parse failed\n"); + hid_err(hdev, "parse failed\n"); goto err_free; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { - dev_err(&hdev->dev, "zydacron: hw start failed\n"); + hid_err(hdev, "hw start failed\n"); goto err_free; } diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index e1f07483691..468e87b53ed 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -19,6 +19,8 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/fs.h> #include <linux/module.h> #include <linux/errno.h> @@ -122,15 +124,15 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t } if (count > HID_MAX_BUFFER_SIZE) { - printk(KERN_WARNING "hidraw: pid %d passed too large report\n", - task_pid_nr(current)); + hid_warn(dev, "pid %d passed too large report\n", + task_pid_nr(current)); ret = -EINVAL; goto out; } if (count < 2) { - printk(KERN_WARNING "hidraw: pid %d passed too short report\n", - task_pid_nr(current)); + hid_warn(dev, "pid %d passed too short report\n", + task_pid_nr(current)); ret = -EINVAL; goto out; } @@ -192,15 +194,13 @@ static int hidraw_open(struct inode *inode, struct file *file) dev = hidraw_table[minor]; if (!dev->open++) { - if (dev->hid->ll_driver->power) { - err = dev->hid->ll_driver->power(dev->hid, PM_HINT_FULLON); - if (err < 0) - goto out_unlock; - } - err = dev->hid->ll_driver->open(dev->hid); + err = hid_hw_power(dev->hid, PM_HINT_FULLON); + if (err < 0) + goto out_unlock; + + err = hid_hw_open(dev->hid); if (err < 0) { - if (dev->hid->ll_driver->power) - dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL); + hid_hw_power(dev->hid, PM_HINT_NORMAL); dev->open--; } } @@ -229,9 +229,8 @@ static int hidraw_release(struct inode * inode, struct file * file) dev = hidraw_table[minor]; if (!--dev->open) { if (list->hidraw->exist) { - if (dev->hid->ll_driver->power) - dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL); - dev->hid->ll_driver->close(dev->hid); + hid_hw_power(dev->hid, PM_HINT_NORMAL); + hid_hw_close(dev->hid); } else { kfree(list->hidraw); } @@ -345,6 +344,9 @@ static const struct file_operations hidraw_ops = { .open = hidraw_open, .release = hidraw_release, .unlocked_ioctl = hidraw_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = hidraw_ioctl, +#endif .llseek = noop_llseek, }; @@ -433,7 +435,7 @@ void hidraw_disconnect(struct hid_device *hid) device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); if (hidraw->open) { - hid->ll_driver->close(hid); + hid_hw_close(hid); wake_up_interruptible(&hidraw->wait); } else { kfree(hidraw); @@ -452,7 +454,7 @@ int __init hidraw_init(void) hidraw_major = MAJOR(dev_id); if (result < 0) { - printk(KERN_WARNING "hidraw: can't get major number\n"); + pr_warn("can't get major number\n"); result = 0; goto out; } diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile index 1329ecb37a1..db3cf31c6fa 100644 --- a/drivers/hid/usbhid/Makefile +++ b/drivers/hid/usbhid/Makefile @@ -3,15 +3,15 @@ # # Multipart objects. -usbhid-objs := hid-core.o hid-quirks.o +usbhid-y := hid-core.o hid-quirks.o # Optional parts of multipart objects. ifeq ($(CONFIG_USB_HIDDEV),y) - usbhid-objs += hiddev.o + usbhid-y += hiddev.o endif ifeq ($(CONFIG_HID_PID),y) - usbhid-objs += hid-pidff.o + usbhid-y += hid-pidff.o endif obj-$(CONFIG_USB_HID) += usbhid.o diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 5489eab3a6b..b336dd84036 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -67,7 +67,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " * Input submission and I/O error handler. */ static DEFINE_MUTEX(hid_open_mut); -static struct workqueue_struct *resumption_waker; static void hid_io_error(struct hid_device *hid); static int hid_submit_out(struct hid_device *hid); @@ -136,10 +135,10 @@ static void hid_reset(struct work_struct *work) hid_io_error(hid); break; default: - err_hid("can't reset device, %s-%s/input%d, status %d", - hid_to_usb_dev(hid)->bus->bus_name, - hid_to_usb_dev(hid)->devpath, - usbhid->ifnum, rc); + hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n", + hid_to_usb_dev(hid)->bus->bus_name, + hid_to_usb_dev(hid)->devpath, + usbhid->ifnum, rc); /* FALLTHROUGH */ case -EHOSTUNREACH: case -ENODEV: @@ -278,18 +277,18 @@ static void hid_irq_in(struct urb *urb) hid_io_error(hid); return; default: /* error */ - dev_warn(&urb->dev->dev, "input irq status %d " - "received\n", urb->status); + hid_warn(urb->dev, "input irq status %d received\n", + urb->status); } status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { clear_bit(HID_IN_RUNNING, &usbhid->iofl); if (status != -EPERM) { - err_hid("can't resubmit intr, %s-%s/input%d, status %d", - hid_to_usb_dev(hid)->bus->bus_name, - hid_to_usb_dev(hid)->devpath, - usbhid->ifnum, status); + hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n", + hid_to_usb_dev(hid)->bus->bus_name, + hid_to_usb_dev(hid)->devpath, + usbhid->ifnum, status); hid_io_error(hid); } } @@ -300,10 +299,19 @@ static int hid_submit_out(struct hid_device *hid) struct hid_report *report; char *raw_report; struct usbhid_device *usbhid = hid->driver_data; + int r; report = usbhid->out[usbhid->outtail].report; raw_report = usbhid->out[usbhid->outtail].raw_report; + r = usb_autopm_get_interface_async(usbhid->intf); + if (r < 0) + return -1; + + /* + * if the device hasn't been woken, we leave the output + * to resume() + */ if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); usbhid->urbout->dev = hid_to_usb_dev(hid); @@ -313,17 +321,11 @@ static int hid_submit_out(struct hid_device *hid) dbg_hid("submitting out urb\n"); if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { - err_hid("usb_submit_urb(out) failed"); + hid_err(hid, "usb_submit_urb(out) failed\n"); + usb_autopm_put_interface_async(usbhid->intf); return -1; } usbhid->last_out = jiffies; - } else { - /* - * queue work to wake up the device. - * as the work queue is freezeable, this is safe - * with respect to STD and STR - */ - queue_work(resumption_waker, &usbhid->restart_work); } return 0; @@ -334,13 +336,16 @@ static int hid_submit_ctrl(struct hid_device *hid) struct hid_report *report; unsigned char dir; char *raw_report; - int len; + int len, r; struct usbhid_device *usbhid = hid->driver_data; report = usbhid->ctrl[usbhid->ctrltail].report; raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; dir = usbhid->ctrl[usbhid->ctrltail].dir; + r = usb_autopm_get_interface_async(usbhid->intf); + if (r < 0) + return -1; if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { len = ((report->size - 1) >> 3) + 1 + (report->id > 0); if (dir == USB_DIR_OUT) { @@ -375,17 +380,11 @@ static int hid_submit_ctrl(struct hid_device *hid) usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { - err_hid("usb_submit_urb(ctrl) failed"); + usb_autopm_put_interface_async(usbhid->intf); + hid_err(hid, "usb_submit_urb(ctrl) failed\n"); return -1; } usbhid->last_ctrl = jiffies; - } else { - /* - * queue work to wake up the device. - * as the work queue is freezeable, this is safe - * with respect to STD and STR - */ - queue_work(resumption_waker, &usbhid->restart_work); } return 0; @@ -413,8 +412,8 @@ static void hid_irq_out(struct urb *urb) case -ENOENT: break; default: /* error */ - dev_warn(&urb->dev->dev, "output irq status %d " - "received\n", urb->status); + hid_warn(urb->dev, "output irq status %d received\n", + urb->status); } spin_lock_irqsave(&usbhid->lock, flags); @@ -435,6 +434,7 @@ static void hid_irq_out(struct urb *urb) clear_bit(HID_OUT_RUNNING, &usbhid->iofl); spin_unlock_irqrestore(&usbhid->lock, flags); + usb_autopm_put_interface_async(usbhid->intf); wake_up(&usbhid->wait); } @@ -466,8 +466,7 @@ static void hid_ctrl(struct urb *urb) case -EPIPE: /* report not available */ break; default: /* error */ - dev_warn(&urb->dev->dev, "ctrl urb status %d " - "received\n", status); + hid_warn(urb->dev, "ctrl urb status %d received\n", status); } if (unplug) @@ -481,11 +480,13 @@ static void hid_ctrl(struct urb *urb) wake_up(&usbhid->wait); } spin_unlock(&usbhid->lock); + usb_autopm_put_interface_async(usbhid->intf); return; } clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); spin_unlock(&usbhid->lock); + usb_autopm_put_interface_async(usbhid->intf); wake_up(&usbhid->wait); } @@ -501,13 +502,13 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { - dev_warn(&hid->dev, "output queue full\n"); + hid_warn(hid, "output queue full\n"); return; } usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); if (!usbhid->out[usbhid->outhead].raw_report) { - dev_warn(&hid->dev, "output queueing failed\n"); + hid_warn(hid, "output queueing failed\n"); return; } hid_output_report(report, usbhid->out[usbhid->outhead].raw_report); @@ -532,14 +533,14 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re } if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { - dev_warn(&hid->dev, "control queue full\n"); + hid_warn(hid, "control queue full\n"); return; } if (dir == USB_DIR_OUT) { usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { - dev_warn(&hid->dev, "control queueing failed\n"); + hid_warn(hid, "control queueing failed\n"); return; } hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report); @@ -590,7 +591,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un return -1; if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { - dev_warn(&dev->dev, "event field not found\n"); + hid_warn(dev, "event field not found\n"); return -1; } @@ -656,7 +657,7 @@ int usbhid_open(struct hid_device *hid) mutex_lock(&hid_open_mut); if (!hid->open++) { res = usb_autopm_get_interface(usbhid->intf); - /* the device must be awake to reliable request remote wakeup */ + /* the device must be awake to reliably request remote wakeup */ if (res < 0) { hid->open--; mutex_unlock(&hid_open_mut); @@ -722,7 +723,7 @@ void usbhid_init_reports(struct hid_device *hid) } if (err) - dev_warn(&hid->dev, "timeout initializing reports\n"); + hid_warn(hid, "timeout initializing reports\n"); } /* @@ -857,18 +858,6 @@ static void usbhid_restart_queues(struct usbhid_device *usbhid) usbhid_restart_ctrl_queue(usbhid); } -static void __usbhid_restart_queues(struct work_struct *work) -{ - struct usbhid_device *usbhid = - container_of(work, struct usbhid_device, restart_work); - int r; - - r = usb_autopm_get_interface(usbhid->intf); - if (r < 0) - return; - usb_autopm_put_interface(usbhid->intf); -} - static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) { struct usbhid_device *usbhid = hid->driver_data; @@ -1140,8 +1129,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) has_in++; if (!has_in) { - dev_err(&intf->dev, "couldn't find an input interrupt " - "endpoint\n"); + hid_err(intf, "couldn't find an input interrupt endpoint\n"); return -ENODEV; } @@ -1206,14 +1194,13 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * init_waitqueue_head(&usbhid->wait); INIT_WORK(&usbhid->reset_work, hid_reset); - INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); spin_lock_init(&usbhid->lock); ret = hid_add_device(hid); if (ret) { if (ret != -ENODEV) - dev_err(&intf->dev, "can't add hid device: %d\n", ret); + hid_err(intf, "can't add hid device: %d\n", ret); goto err_free; } @@ -1241,7 +1228,6 @@ static void usbhid_disconnect(struct usb_interface *intf) static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) { del_timer_sync(&usbhid->io_retry); - cancel_work_sync(&usbhid->restart_work); cancel_work_sync(&usbhid->reset_work); } @@ -1262,7 +1248,6 @@ static int hid_pre_reset(struct usb_interface *intf) spin_lock_irq(&usbhid->lock); set_bit(HID_RESET_PENDING, &usbhid->iofl); spin_unlock_irq(&usbhid->lock); - cancel_work_sync(&usbhid->restart_work); hid_cease_io(usbhid); return 0; @@ -1461,9 +1446,6 @@ static int __init hid_init(void) { int retval = -ENOMEM; - resumption_waker = create_freezeable_workqueue("usbhid_resumer"); - if (!resumption_waker) - goto no_queue; retval = hid_register_driver(&hid_usb_driver); if (retval) goto hid_register_fail; @@ -1481,8 +1463,6 @@ usb_register_fail: usbhid_quirks_init_fail: hid_unregister_driver(&hid_usb_driver); hid_register_fail: - destroy_workqueue(resumption_waker); -no_queue: return retval; } @@ -1491,7 +1471,6 @@ static void __exit hid_exit(void) usb_deregister(&hid_driver); usbhid_quirks_exit(); hid_unregister_driver(&hid_usb_driver); - destroy_workqueue(resumption_waker); } module_init(hid_init); diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index ef381d79cfa..f91c136821f 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -22,7 +22,7 @@ /* #define DEBUG */ -#define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg) +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/input.h> #include <linux/slab.h> @@ -220,7 +220,7 @@ static int pidff_rescale_signed(int i, struct hid_field *field) static void pidff_set(struct pidff_usage *usage, u16 value) { usage->value[0] = pidff_rescale(value, 0xffff, usage->field); - debug("calculated from %d to %d", value, usage->value[0]); + pr_debug("calculated from %d to %d\n", value, usage->value[0]); } static void pidff_set_signed(struct pidff_usage *usage, s16 value) @@ -235,7 +235,7 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value) usage->value[0] = pidff_rescale(value, 0x7fff, usage->field); } - debug("calculated from %d to %d", value, usage->value[0]); + pr_debug("calculated from %d to %d\n", value, usage->value[0]); } /* @@ -259,8 +259,9 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; - debug("attack %u => %d", envelope->attack_level, - pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); + hid_dbg(pidff->hid, "attack %u => %d\n", + envelope->attack_level, + pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], USB_DIR_OUT); @@ -466,33 +467,33 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) pidff->create_new_effect_type->value[0] = efnum; usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], USB_DIR_OUT); - debug("create_new_effect sent, type: %d", 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_status->value[0] = 0; usbhid_wait_io(pidff->hid); for (j = 0; j < 60; j++) { - debug("pid_block_load requested"); + hid_dbg(pidff->hid, "pid_block_load requested\n"); usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], USB_DIR_IN); usbhid_wait_io(pidff->hid); if (pidff->block_load_status->value[0] == pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { - debug("device reported free memory: %d bytes", - pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? - pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); + hid_dbg(pidff->hid, "device reported free memory: %d bytes\n", + pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? + pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); return 0; } if (pidff->block_load_status->value[0] == pidff->status_id[PID_BLOCK_LOAD_FULL]) { - debug("not enough memory free: %d bytes", - pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? + hid_dbg(pidff->hid, "not enough memory free: %d bytes\n", + pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); return -ENOSPC; } } - printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n"); + hid_err(pidff->hid, "pid_block_load failed 60 times\n"); return -EIO; } @@ -546,7 +547,8 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id) struct pidff_device *pidff = dev->ff->private; int pid_id = pidff->pid_id[effect_id]; - debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]); + hid_dbg(pidff->hid, "starting to erase %d/%d\n", + effect_id, pidff->pid_id[effect_id]); /* Wait for the queue to clear. We do not want a full fifo to prevent the effect removal. */ usbhid_wait_io(pidff->hid); @@ -604,8 +606,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, type_id = PID_SAW_DOWN; break; default: - printk(KERN_ERR - "hid-pidff: invalid waveform\n"); + hid_err(pidff->hid, "invalid waveform\n"); return -EINVAL; } @@ -696,7 +697,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, break; default: - printk(KERN_ERR "hid-pidff: invalid type\n"); + hid_err(pidff->hid, "invalid type\n"); return -EINVAL; } @@ -704,7 +705,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, pidff->pid_id[effect->id] = pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - debug("uploaded"); + hid_dbg(pidff->hid, "uploaded\n"); return 0; } @@ -770,14 +771,14 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, for (i = 0; i < report->maxfield; i++) { if (report->field[i]->maxusage != report->field[i]->report_count) { - debug("maxusage and report_count do not match, " - "skipping"); + pr_debug("maxusage and report_count do not match, skipping\n"); continue; } for (j = 0; j < report->field[i]->maxusage; j++) { if (report->field[i]->usage[j].hid == (HID_UP_PID | table[k])) { - debug("found %d at %d->%d", k, i, j); + pr_debug("found %d at %d->%d\n", + k, i, j); usage[k].field = report->field[i]; usage[k].value = &report->field[i]->value[j]; @@ -789,7 +790,7 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, break; } if (!found && strict) { - debug("failed to locate %d", k); + pr_debug("failed to locate %d\n", k); return -1; } } @@ -826,8 +827,8 @@ static void pidff_find_reports(struct hid_device *hid, int report_type, continue; ret = pidff_check_usage(report->field[0]->logical); if (ret != -1) { - debug("found usage 0x%02x from field->logical", - pidff_reports[ret]); + hid_dbg(hid, "found usage 0x%02x from field->logical\n", + pidff_reports[ret]); pidff->reports[ret] = report; continue; } @@ -845,8 +846,9 @@ static void pidff_find_reports(struct hid_device *hid, int report_type, continue; ret = pidff_check_usage(hid->collection[i - 1].usage); if (ret != -1 && !pidff->reports[ret]) { - debug("found usage 0x%02x from collection array", - pidff_reports[ret]); + hid_dbg(hid, + "found usage 0x%02x from collection array\n", + pidff_reports[ret]); pidff->reports[ret] = report; } } @@ -861,7 +863,7 @@ static int pidff_reports_ok(struct pidff_device *pidff) for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { if (!pidff->reports[i]) { - debug("%d missing", i); + hid_dbg(pidff->hid, "%d missing\n", i); return 0; } } @@ -884,8 +886,7 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report, report->field[i]->logical_minimum == 1) return report->field[i]; else { - printk(KERN_ERR "hid-pidff: logical_minimum " - "is not 1 as it should be\n"); + pr_err("logical_minimum is not 1 as it should be\n"); return NULL; } } @@ -924,7 +925,7 @@ static int pidff_find_special_keys(int *keys, struct hid_field *fld, */ static int pidff_find_special_fields(struct pidff_device *pidff) { - debug("finding special fields"); + hid_dbg(pidff->hid, "finding special fields\n"); pidff->create_new_effect_type = pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], @@ -945,32 +946,30 @@ static int pidff_find_special_fields(struct pidff_device *pidff) pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], 0x78, 1); - debug("search done"); + hid_dbg(pidff->hid, "search done\n"); if (!pidff->create_new_effect_type || !pidff->set_effect_type) { - printk(KERN_ERR "hid-pidff: effect lists not found\n"); + hid_err(pidff->hid, "effect lists not found\n"); return -1; } if (!pidff->effect_direction) { - printk(KERN_ERR "hid-pidff: direction field not found\n"); + hid_err(pidff->hid, "direction field not found\n"); return -1; } if (!pidff->device_control) { - printk(KERN_ERR "hid-pidff: device control field not found\n"); + hid_err(pidff->hid, "device control field not found\n"); return -1; } if (!pidff->block_load_status) { - printk(KERN_ERR - "hid-pidff: block load status field not found\n"); + hid_err(pidff->hid, "block load status field not found\n"); return -1; } if (!pidff->effect_operation_status) { - printk(KERN_ERR - "hid-pidff: effect operation field not found\n"); + hid_err(pidff->hid, "effect operation field not found\n"); return -1; } @@ -982,23 +981,22 @@ static int pidff_find_special_fields(struct pidff_device *pidff) if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, effect_types)) { - printk(KERN_ERR "hid-pidff: no effect types found\n"); + hid_err(pidff->hid, "no effect types found\n"); return -1; } if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, block_load_status) != sizeof(pidff_block_load_status)) { - printk(KERN_ERR - "hidpidff: block load status identifiers not found\n"); + hid_err(pidff->hid, + "block load status identifiers not found\n"); return -1; } if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, effect_operation_status) != sizeof(pidff_effect_operation_status)) { - printk(KERN_ERR - "hidpidff: effect operation identifiers not found\n"); + hid_err(pidff->hid, "effect operation identifiers not found\n"); return -1; } @@ -1017,8 +1015,8 @@ static int pidff_find_effects(struct pidff_device *pidff, int pidff_type = pidff->type_id[i]; if (pidff->set_effect_type->usage[pidff_type].hid != pidff->create_new_effect_type->usage[pidff_type].hid) { - printk(KERN_ERR "hid-pidff: " - "effect type number %d is invalid\n", i); + hid_err(pidff->hid, + "effect type number %d is invalid\n", i); return -1; } } @@ -1073,27 +1071,23 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) int envelope_ok = 0; if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { - printk(KERN_ERR - "hid-pidff: unknown set_effect report layout\n"); + hid_err(pidff->hid, "unknown set_effect report layout\n"); return -ENODEV; } PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { - printk(KERN_ERR - "hid-pidff: unknown pid_block_load report layout\n"); + hid_err(pidff->hid, "unknown pid_block_load report layout\n"); return -ENODEV; } if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { - printk(KERN_ERR - "hid-pidff: unknown effect_operation report layout\n"); + hid_err(pidff->hid, "unknown effect_operation report layout\n"); return -ENODEV; } if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { - printk(KERN_ERR - "hid-pidff: unknown pid_block_free report layout\n"); + hid_err(pidff->hid, "unknown pid_block_free report layout\n"); return -ENODEV; } @@ -1105,27 +1099,26 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) if (!envelope_ok) { if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) - printk(KERN_WARNING "hid-pidff: " - "has constant effect but no envelope\n"); + hid_warn(pidff->hid, + "has constant effect but no envelope\n"); if (test_and_clear_bit(FF_RAMP, dev->ffbit)) - printk(KERN_WARNING "hid-pidff: " - "has ramp effect but no envelope\n"); + hid_warn(pidff->hid, + "has ramp effect but no envelope\n"); if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) - printk(KERN_WARNING "hid-pidff: " - "has periodic effect but no envelope\n"); + hid_warn(pidff->hid, + "has periodic effect but no envelope\n"); } if (test_bit(FF_CONSTANT, dev->ffbit) && PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { - printk(KERN_WARNING - "hid-pidff: unknown constant effect layout\n"); + hid_warn(pidff->hid, "unknown constant effect layout\n"); clear_bit(FF_CONSTANT, dev->ffbit); } if (test_bit(FF_RAMP, dev->ffbit) && PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { - printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n"); + hid_warn(pidff->hid, "unknown ramp effect layout\n"); clear_bit(FF_RAMP, dev->ffbit); } @@ -1134,8 +1127,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) test_bit(FF_FRICTION, dev->ffbit) || test_bit(FF_INERTIA, dev->ffbit)) && PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { - printk(KERN_WARNING - "hid-pidff: unknown condition effect layout\n"); + hid_warn(pidff->hid, "unknown condition effect layout\n"); clear_bit(FF_SPRING, dev->ffbit); clear_bit(FF_DAMPER, dev->ffbit); clear_bit(FF_FRICTION, dev->ffbit); @@ -1144,8 +1136,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) if (test_bit(FF_PERIODIC, dev->ffbit) && PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { - printk(KERN_WARNING - "hid-pidff: unknown periodic effect layout\n"); + hid_warn(pidff->hid, "unknown periodic effect layout\n"); clear_bit(FF_PERIODIC, dev->ffbit); } @@ -1184,12 +1175,12 @@ static void pidff_reset(struct pidff_device *pidff) if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { if (i++ > 20) { - printk(KERN_WARNING "hid-pidff: device reports " - "%d simultaneous effects\n", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); + hid_warn(pidff->hid, + "device reports %d simultaneous effects\n", + pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); break; } - debug("pid_pool requested again"); + hid_dbg(pidff->hid, "pid_pool requested again\n"); usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); usbhid_wait_io(hid); @@ -1215,7 +1206,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff, error = pidff_request_effect_upload(pidff, 1); if (error) { - printk(KERN_ERR "hid-pidff: upload request failed\n"); + hid_err(pidff->hid, "upload request failed\n"); return error; } @@ -1224,8 +1215,8 @@ static int pidff_check_autocenter(struct pidff_device *pidff, pidff_autocenter(pidff, 0xffff); set_bit(FF_AUTOCENTER, dev->ffbit); } else { - printk(KERN_NOTICE "hid-pidff: " - "device has unknown autocenter control method\n"); + hid_notice(pidff->hid, + "device has unknown autocenter control method\n"); } pidff_erase_pid(pidff, @@ -1248,10 +1239,10 @@ int hid_pidff_init(struct hid_device *hid) int max_effects; int error; - debug("starting pid init"); + hid_dbg(hid, "starting pid init\n"); if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { - debug("not a PID device, no output report"); + hid_dbg(hid, "not a PID device, no output report\n"); return -ENODEV; } @@ -1265,7 +1256,7 @@ int hid_pidff_init(struct hid_device *hid) pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); if (!pidff_reports_ok(pidff)) { - debug("reports not ok, aborting"); + hid_dbg(hid, "reports not ok, aborting\n"); error = -ENODEV; goto fail; } @@ -1278,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid) if (test_bit(FF_GAIN, dev->ffbit)) { pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); - usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], - USB_DIR_OUT); + usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN], + USB_DIR_OUT); } error = pidff_check_autocenter(pidff, dev); @@ -1290,23 +1281,23 @@ int hid_pidff_init(struct hid_device *hid) pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1; - debug("max effects is %d", max_effects); + hid_dbg(hid, "max effects is %d\n", max_effects); if (max_effects > PID_EFFECTS_MAX) max_effects = PID_EFFECTS_MAX; if (pidff->pool[PID_SIMULTANEOUS_MAX].value) - debug("max simultaneous effects is %d", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); + hid_dbg(hid, "max simultaneous effects is %d\n", + pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); if (pidff->pool[PID_RAM_POOL_SIZE].value) - debug("device memory size is %d bytes", - pidff->pool[PID_RAM_POOL_SIZE].value[0]); + hid_dbg(hid, "device memory size is %d bytes\n", + pidff->pool[PID_RAM_POOL_SIZE].value[0]); if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { - printk(KERN_NOTICE "hid-pidff: " - "device does not support device managed pool\n"); + hid_notice(hid, + "device does not support device managed pool\n"); goto fail; } @@ -1322,8 +1313,7 @@ int hid_pidff_init(struct hid_device *hid) ff->set_autocenter = pidff_set_autocenter; ff->playback = pidff_playback; - printk(KERN_INFO "Force feedback for USB HID PID devices by " - "Anssi Hannula <anssi.hannula@gmail.com>\n"); + hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); return 0; diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2c185477eeb..9a94b643ccd 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -35,7 +35,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, @@ -85,7 +84,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, - + { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, { 0, 0 } }; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 984feb351a5..af0a7c1002a 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -585,163 +585,168 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct hiddev_list *list = file->private_data; struct hiddev *hiddev = list->hiddev; - struct hid_device *hid = hiddev->hid; - struct usb_device *dev; + struct hid_device *hid; struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; struct hiddev_devinfo dinfo; struct hid_report *report; struct hid_field *field; - struct usbhid_device *usbhid = hid->driver_data; void __user *user_arg = (void __user *)arg; - int i, r; - + int i, r = -EINVAL; + /* Called without BKL by compat methods so no BKL taken */ - /* FIXME: Who or what stop this racing with a disconnect ?? */ - if (!hiddev->exist || !hid) - return -EIO; + mutex_lock(&hiddev->existancelock); + if (!hiddev->exist) { + r = -ENODEV; + goto ret_unlock; + } - dev = hid_to_usb_dev(hid); + hid = hiddev->hid; switch (cmd) { case HIDIOCGVERSION: - return put_user(HID_VERSION, (int __user *)arg); + r = put_user(HID_VERSION, (int __user *)arg) ? + -EFAULT : 0; + break; case HIDIOCAPPLICATION: if (arg < 0 || arg >= hid->maxapplication) - return -EINVAL; + break; for (i = 0; i < hid->maxcollection; i++) if (hid->collection[i].type == HID_COLLECTION_APPLICATION && arg-- == 0) break; - if (i == hid->maxcollection) - return -EINVAL; - - return hid->collection[i].usage; + if (i < hid->maxcollection) + r = hid->collection[i].usage; + break; case HIDIOCGDEVINFO: - dinfo.bustype = BUS_USB; - dinfo.busnum = dev->bus->busnum; - dinfo.devnum = dev->devnum; - dinfo.ifnum = usbhid->ifnum; - dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); - dinfo.product = le16_to_cpu(dev->descriptor.idProduct); - dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); - dinfo.num_applications = hid->maxapplication; - if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) - return -EFAULT; - - return 0; + { + struct usb_device *dev = hid_to_usb_dev(hid); + struct usbhid_device *usbhid = hid->driver_data; + + dinfo.bustype = BUS_USB; + dinfo.busnum = dev->bus->busnum; + dinfo.devnum = dev->devnum; + dinfo.ifnum = usbhid->ifnum; + dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); + dinfo.product = le16_to_cpu(dev->descriptor.idProduct); + dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); + dinfo.num_applications = hid->maxapplication; + + r = copy_to_user(user_arg, &dinfo, sizeof(dinfo)) ? + -EFAULT : 0; + break; + } case HIDIOCGFLAG: - if (put_user(list->flags, (int __user *)arg)) - return -EFAULT; - - return 0; + r = put_user(list->flags, (int __user *)arg) ? + -EFAULT : 0; + break; case HIDIOCSFLAG: { int newflags; - if (get_user(newflags, (int __user *)arg)) - return -EFAULT; + + if (get_user(newflags, (int __user *)arg)) { + r = -EFAULT; + break; + } if ((newflags & ~HIDDEV_FLAGS) != 0 || ((newflags & HIDDEV_FLAG_REPORT) != 0 && (newflags & HIDDEV_FLAG_UREF) == 0)) - return -EINVAL; + break; list->flags = newflags; - return 0; + r = 0; + break; } case HIDIOCGSTRING: - mutex_lock(&hiddev->existancelock); - if (hiddev->exist) - r = hiddev_ioctl_string(hiddev, cmd, user_arg); - else - r = -ENODEV; - mutex_unlock(&hiddev->existancelock); - return r; + r = hiddev_ioctl_string(hiddev, cmd, user_arg); + break; case HIDIOCINITREPORT: - mutex_lock(&hiddev->existancelock); - if (!hiddev->exist) { - mutex_unlock(&hiddev->existancelock); - return -ENODEV; - } usbhid_init_reports(hid); - mutex_unlock(&hiddev->existancelock); - - return 0; + r = 0; + break; case HIDIOCGREPORT: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) - return -EFAULT; + if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { + r = -EFAULT; + break; + } if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) - return -EINVAL; + break; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; + report = hiddev_lookup_report(hid, &rinfo); + if (report == NULL) + break; - mutex_lock(&hiddev->existancelock); - if (hiddev->exist) { - usbhid_submit_report(hid, report, USB_DIR_IN); - usbhid_wait_io(hid); - } - mutex_unlock(&hiddev->existancelock); + usbhid_submit_report(hid, report, USB_DIR_IN); + usbhid_wait_io(hid); - return 0; + r = 0; + break; case HIDIOCSREPORT: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) - return -EFAULT; + if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { + r = -EFAULT; + break; + } if (rinfo.report_type == HID_REPORT_TYPE_INPUT) - return -EINVAL; + break; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; + report = hiddev_lookup_report(hid, &rinfo); + if (report == NULL) + break; - mutex_lock(&hiddev->existancelock); - if (hiddev->exist) { - usbhid_submit_report(hid, report, USB_DIR_OUT); - usbhid_wait_io(hid); - } - mutex_unlock(&hiddev->existancelock); + usbhid_submit_report(hid, report, USB_DIR_OUT); + usbhid_wait_io(hid); - return 0; + r = 0; + break; case HIDIOCGREPORTINFO: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) - return -EFAULT; + if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { + r = -EFAULT; + break; + } - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; + report = hiddev_lookup_report(hid, &rinfo); + if (report == NULL) + break; rinfo.num_fields = report->maxfield; - if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) - return -EFAULT; - - return 0; + r = copy_to_user(user_arg, &rinfo, sizeof(rinfo)) ? + -EFAULT : 0; + break; case HIDIOCGFIELDINFO: - if (copy_from_user(&finfo, user_arg, sizeof(finfo))) - return -EFAULT; + if (copy_from_user(&finfo, user_arg, sizeof(finfo))) { + r = -EFAULT; + break; + } + rinfo.report_type = finfo.report_type; rinfo.report_id = finfo.report_id; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; + + report = hiddev_lookup_report(hid, &rinfo); + if (report == NULL) + break; if (finfo.field_index >= report->maxfield) - return -EINVAL; + break; field = report->field[finfo.field_index]; memset(&finfo, 0, sizeof(finfo)); @@ -760,10 +765,9 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) finfo.unit_exponent = field->unit_exponent; finfo.unit = field->unit; - if (copy_to_user(user_arg, &finfo, sizeof(finfo))) - return -EFAULT; - - return 0; + r = copy_to_user(user_arg, &finfo, sizeof(finfo)) ? + -EFAULT : 0; + break; case HIDIOCGUCODE: /* fall through */ @@ -772,57 +776,66 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case HIDIOCGUSAGES: case HIDIOCSUSAGES: case HIDIOCGCOLLECTIONINDEX: - mutex_lock(&hiddev->existancelock); - if (hiddev->exist) - r = hiddev_ioctl_usage(hiddev, cmd, user_arg); - else - r = -ENODEV; - mutex_unlock(&hiddev->existancelock); - return r; + r = hiddev_ioctl_usage(hiddev, cmd, user_arg); + break; case HIDIOCGCOLLECTIONINFO: - if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) - return -EFAULT; + if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) { + r = -EFAULT; + break; + } if (cinfo.index >= hid->maxcollection) - return -EINVAL; + break; cinfo.type = hid->collection[cinfo.index].type; cinfo.usage = hid->collection[cinfo.index].usage; cinfo.level = hid->collection[cinfo.index].level; - if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) - return -EFAULT; - return 0; + r = copy_to_user(user_arg, &cinfo, sizeof(cinfo)) ? + -EFAULT : 0; + break; default: - if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) - return -EINVAL; + break; if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { int len; - if (!hid->name) - return 0; + + if (!hid->name) { + r = 0; + break; + } + len = strlen(hid->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(user_arg, hid->name, len) ? + r = copy_to_user(user_arg, hid->name, len) ? -EFAULT : len; + break; } if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { int len; - if (!hid->phys) - return 0; + + if (!hid->phys) { + r = 0; + break; + } + len = strlen(hid->phys) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(user_arg, hid->phys, len) ? + r = copy_to_user(user_arg, hid->phys, len) ? -EFAULT : len; + break; } } - return -EINVAL; + +ret_unlock: + mutex_unlock(&hiddev->existancelock); + return r; } #ifdef CONFIG_COMPAT @@ -892,7 +905,7 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) hiddev->exist = 1; retval = usb_register_dev(usbhid->intf, &hiddev_class); if (retval) { - err_hid("Not able to get a minor for this device."); + hid_err(hid, "Not able to get a minor for this device\n"); hid->hiddev = NULL; kfree(hiddev); return -1; diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 89d2e847dcc..1673cac93d7 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -95,7 +95,6 @@ struct usbhid_device { unsigned long stop_retry; /* Time to give up, in jiffies */ unsigned int retry_delay; /* Delay length in ms */ struct work_struct reset_work; /* Task context for resets */ - struct work_struct restart_work; /* waking up for output to be done in a task */ wait_queue_head_t wait; /* For sleeping */ int ledcount; /* counting the number of active leds */ }; diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index a948605564f..065817329f0 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -24,6 +24,8 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> @@ -104,16 +106,18 @@ static void usb_kbd_irq(struct urb *urb) if (usb_kbd_keycode[kbd->old[i]]) input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); else - dev_info(&urb->dev->dev, - "Unknown key (scancode %#x) released.\n", kbd->old[i]); + hid_info(urb->dev, + "Unknown key (scancode %#x) released.\n", + kbd->old[i]); } if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { if (usb_kbd_keycode[kbd->new[i]]) input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); else - dev_info(&urb->dev->dev, - "Unknown key (scancode %#x) released.\n", kbd->new[i]); + hid_info(urb->dev, + "Unknown key (scancode %#x) released.\n", + kbd->new[i]); } } @@ -124,9 +128,9 @@ static void usb_kbd_irq(struct urb *urb) resubmit: i = usb_submit_urb (urb, GFP_ATOMIC); if (i) - err_hid ("can't resubmit intr, %s-%s/input0, status %d", - kbd->usbdev->bus->bus_name, - kbd->usbdev->devpath, i); + hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d", + kbd->usbdev->bus->bus_name, + kbd->usbdev->devpath, i); } static int usb_kbd_event(struct input_dev *dev, unsigned int type, @@ -150,7 +154,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type, *(kbd->leds) = kbd->newleds; kbd->led->dev = kbd->usbdev; if (usb_submit_urb(kbd->led, GFP_ATOMIC)) - err_hid("usb_submit_urb(leds) failed"); + pr_err("usb_submit_urb(leds) failed\n"); return 0; } @@ -160,7 +164,7 @@ static void usb_kbd_led(struct urb *urb) struct usb_kbd *kbd = urb->context; if (urb->status) - dev_warn(&urb->dev->dev, "led urb status %d received\n", + hid_warn(urb->dev, "led urb status %d received\n", urb->status); if (*(kbd->leds) == kbd->newleds) @@ -169,7 +173,7 @@ static void usb_kbd_led(struct urb *urb) *(kbd->leds) = kbd->newleds; kbd->led->dev = kbd->usbdev; if (usb_submit_urb(kbd->led, GFP_ATOMIC)) - err_hid("usb_submit_urb(leds) failed"); + hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); } static int usb_kbd_open(struct input_dev *dev) |