···371371 tristate "Logitech Unifying receivers full support"372372 depends on HIDRAW373373 depends on HID_LOGITECH374374+ select HID_LOGITECH_HIDPP374375 ---help---375376 Say Y if you want support for Logitech Unifying receivers and devices.376377 Unifying receivers are capable of pairing up to 6 Logitech compliant377378 devices to the same receiver. Without this driver it will be handled by378379 generic USB_HID driver and all incoming events will be multiplexed379380 into a single mouse and a single keyboard device.381381+382382+config HID_LOGITECH_HIDPP383383+ tristate "Logitech HID++ devices support"384384+ depends on HID_LOGITECH385385+ ---help---386386+ Support for Logitech devices relyingon the HID++ Logitech specification387387+388388+ Say Y if you want support for Logitech devices relying on the HID++389389+ specification. Such devices are the various Logitech Touchpads (T650,390390+ T651, TK820), some mice (Zone Touch mouse), or even keyboards (Solar391391+ Keayboard).380392381393config LOGITECH_FF382394 bool "Logitech force feedback support"···624612 depends on HID_PICOLCD=RC_CORE || RC_CORE=y625613 ---help---626614 Provide access to PicoLCD's CIR interface via remote control (LIRC).615615+616616+config HID_PLANTRONICS617617+ tristate "Plantronics USB HID Driver"618618+ default !EXPERT619619+ depends on HID620620+ ---help---621621+ Provides HID support for Plantronics telephony devices.627622628623config HID_PRIMAX629624 tristate "Primax non-fully HID-compliant devices"
···12151215 return hid->ll_driver->request(hid, report, HID_REQ_SET_REPORT);1216121612171217 /* fall back to generic raw-output-report */12181218- len = ((report->size - 1) >> 3) + 1 + (report->id > 0);12181218+ len = hid_report_len(report);12191219 buf = hid_alloc_report_buf(report, GFP_KERNEL);12201220 if (!buf)12211221 return;
+6-7
drivers/hid/hid-lenovo.c
···6262 /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */6363 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||6464 (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {6565- set_bit(EV_REP, hi->input->evbit);6665 switch (usage->hid & HID_USAGE) {6766 case 0x00f1: /* Fn-F4: Mic mute */6867 map_key_clear(KEY_MICMUTE);···8485 case 0x00f8: /* Fn-F11: View open applications (3 boxes) */8586 map_key_clear(KEY_SCALE);8687 return 1;8787- case 0x00fa: /* Fn-Esc: Fn-lock toggle */8888- map_key_clear(KEY_FN_ESC);8989- return 1;9090- case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */8888+ case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */9189 /* NB: This mapping is invented in raw_event below */9290 map_key_clear(KEY_FILE);9191+ return 1;9292+ case 0x00fa: /* Fn-Esc: Fn-lock toggle */9393+ map_key_clear(KEY_FN_ESC);9394 return 1;9495 }9596 }···206207 && data[0] == 0x15207208 && data[1] == 0x94208209 && data[2] == 0x01)) {209209- data[1] = 0x0;210210- data[2] = 0x4;210210+ data[1] = 0x00;211211+ data[2] = 0x01;211212 }212213213214 return 0;
+300-97
drivers/hid/hid-logitech-dj.c
···2626#include <linux/hid.h>2727#include <linux/module.h>2828#include <linux/usb.h>2929+#include <linux/kfifo.h>2930#include <asm/unaligned.h>3031#include "hid-ids.h"3131-#include "hid-logitech-dj.h"3232+3333+#define DJ_MAX_PAIRED_DEVICES 63434+#define DJ_MAX_NUMBER_NOTIFICATIONS 83535+#define DJ_RECEIVER_INDEX 03636+#define DJ_DEVICE_INDEX_MIN 13737+#define DJ_DEVICE_INDEX_MAX 63838+3939+#define DJREPORT_SHORT_LENGTH 154040+#define DJREPORT_LONG_LENGTH 324141+4242+#define REPORT_ID_DJ_SHORT 0x204343+#define REPORT_ID_DJ_LONG 0x214444+4545+#define REPORT_ID_HIDPP_SHORT 0x104646+#define REPORT_ID_HIDPP_LONG 0x114747+4848+#define HIDPP_REPORT_SHORT_LENGTH 74949+#define HIDPP_REPORT_LONG_LENGTH 205050+5151+#define HIDPP_RECEIVER_INDEX 0xff5252+5353+#define REPORT_TYPE_RFREPORT_FIRST 0x015454+#define REPORT_TYPE_RFREPORT_LAST 0x1F5555+5656+/* Command Switch to DJ mode */5757+#define REPORT_TYPE_CMD_SWITCH 0x805858+#define CMD_SWITCH_PARAM_DEVBITFIELD 0x005959+#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x016060+#define TIMEOUT_NO_KEEPALIVE 0x006161+6262+/* Command to Get the list of Paired devices */6363+#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x816464+6565+/* Device Paired Notification */6666+#define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x416767+#define SPFUNCTION_MORE_NOTIF_EXPECTED 0x016868+#define SPFUNCTION_DEVICE_LIST_EMPTY 0x026969+#define DEVICE_PAIRED_PARAM_SPFUNCTION 0x007070+#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x017171+#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x027272+#define DEVICE_PAIRED_RF_REPORT_TYPE 0x037373+7474+/* Device Un-Paired Notification */7575+#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x407676+7777+7878+/* Connection Status Notification */7979+#define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x428080+#define CONNECTION_STATUS_PARAM_STATUS 0x008181+#define STATUS_LINKLOSS 0x018282+8383+/* Error Notification */8484+#define REPORT_TYPE_NOTIF_ERROR 0x7F8585+#define NOTIF_ERROR_PARAM_ETYPE 0x008686+#define ETYPE_KEEPALIVE_TIMEOUT 0x018787+8888+/* supported DJ HID && RF report types */8989+#define REPORT_TYPE_KEYBOARD 0x019090+#define REPORT_TYPE_MOUSE 0x029191+#define REPORT_TYPE_CONSUMER_CONTROL 0x039292+#define REPORT_TYPE_SYSTEM_CONTROL 0x049393+#define REPORT_TYPE_MEDIA_CENTER 0x089494+#define REPORT_TYPE_LEDS 0x0E9595+9696+/* RF Report types bitfield */9797+#define STD_KEYBOARD 0x000000029898+#define STD_MOUSE 0x000000049999+#define MULTIMEDIA 0x00000008100100+#define POWER_KEYS 0x00000010101101+#define MEDIA_CENTER 0x00000100102102+#define KBD_LEDS 0x00004000103103+104104+struct dj_report {105105+ u8 report_id;106106+ u8 device_index;107107+ u8 report_type;108108+ u8 report_params[DJREPORT_SHORT_LENGTH - 3];109109+};110110+111111+struct dj_receiver_dev {112112+ struct hid_device *hdev;113113+ struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +114114+ DJ_DEVICE_INDEX_MIN];115115+ struct work_struct work;116116+ struct kfifo notif_fifo;117117+ spinlock_t lock;118118+ bool querying_devices;119119+};120120+121121+struct dj_device {122122+ struct hid_device *hdev;123123+ struct dj_receiver_dev *dj_receiver_dev;124124+ u32 reports_supported;125125+ u8 device_index;126126+};3212733128/* Keyboard descriptor (1) */34129static const char kbd_descriptor[] = {···251156 0xc0, /* EndCollection */252157}; /* */253158159159+/* HIDPP descriptor */160160+static const char hidpp_descriptor[] = {161161+ 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */162162+ 0x09, 0x01, /* Usage (Vendor Usage 1) */163163+ 0xa1, 0x01, /* Collection (Application) */164164+ 0x85, 0x10, /* Report ID (16) */165165+ 0x75, 0x08, /* Report Size (8) */166166+ 0x95, 0x06, /* Report Count (6) */167167+ 0x15, 0x00, /* Logical Minimum (0) */168168+ 0x26, 0xff, 0x00, /* Logical Maximum (255) */169169+ 0x09, 0x01, /* Usage (Vendor Usage 1) */170170+ 0x81, 0x00, /* Input (Data,Arr,Abs) */171171+ 0x09, 0x01, /* Usage (Vendor Usage 1) */172172+ 0x91, 0x00, /* Output (Data,Arr,Abs) */173173+ 0xc0, /* End Collection */174174+ 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */175175+ 0x09, 0x02, /* Usage (Vendor Usage 2) */176176+ 0xa1, 0x01, /* Collection (Application) */177177+ 0x85, 0x11, /* Report ID (17) */178178+ 0x75, 0x08, /* Report Size (8) */179179+ 0x95, 0x13, /* Report Count (19) */180180+ 0x15, 0x00, /* Logical Minimum (0) */181181+ 0x26, 0xff, 0x00, /* Logical Maximum (255) */182182+ 0x09, 0x02, /* Usage (Vendor Usage 2) */183183+ 0x81, 0x00, /* Input (Data,Arr,Abs) */184184+ 0x09, 0x02, /* Usage (Vendor Usage 2) */185185+ 0x91, 0x00, /* Output (Data,Arr,Abs) */186186+ 0xc0, /* End Collection */187187+ 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */188188+ 0x09, 0x04, /* Usage (Vendor Usage 0x04) */189189+ 0xa1, 0x01, /* Collection (Application) */190190+ 0x85, 0x20, /* Report ID (32) */191191+ 0x75, 0x08, /* Report Size (8) */192192+ 0x95, 0x0e, /* Report Count (14) */193193+ 0x15, 0x00, /* Logical Minimum (0) */194194+ 0x26, 0xff, 0x00, /* Logical Maximum (255) */195195+ 0x09, 0x41, /* Usage (Vendor Usage 0x41) */196196+ 0x81, 0x00, /* Input (Data,Arr,Abs) */197197+ 0x09, 0x41, /* Usage (Vendor Usage 0x41) */198198+ 0x91, 0x00, /* Output (Data,Arr,Abs) */199199+ 0x85, 0x21, /* Report ID (33) */200200+ 0x95, 0x1f, /* Report Count (31) */201201+ 0x15, 0x00, /* Logical Minimum (0) */202202+ 0x26, 0xff, 0x00, /* Logical Maximum (255) */203203+ 0x09, 0x42, /* Usage (Vendor Usage 0x42) */204204+ 0x81, 0x00, /* Input (Data,Arr,Abs) */205205+ 0x09, 0x42, /* Usage (Vendor Usage 0x42) */206206+ 0x91, 0x00, /* Output (Data,Arr,Abs) */207207+ 0xc0, /* End Collection */208208+};209209+254210/* Maximum size of all defined hid reports in bytes (including report id) */255211#define MAX_REPORT_SIZE 8256212···311165 sizeof(mse_descriptor) + \312166 sizeof(consumer_descriptor) + \313167 sizeof(syscontrol_descriptor) + \314314- sizeof(media_descriptor))168168+ sizeof(media_descriptor) + \169169+ sizeof(hidpp_descriptor))315170316171/* Number of possible hid report types that can be created by this driver.317172 *···403256 dj_hiddev->dev.parent = &djrcv_hdev->dev;404257 dj_hiddev->bus = BUS_USB;405258 dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);406406- dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct);259259+ dj_hiddev->product =260260+ (dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB]261261+ << 8) |262262+ dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB];407263 snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),408408- "Logitech Unifying Device. Wireless PID:%02x%02x",409409- dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB],410410- dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]);264264+ "Logitech Unifying Device. Wireless PID:%04x",265265+ dj_hiddev->product);266266+267267+ dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE;411268412269 usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));413270 snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);···573422 }574423}575424425425+static void logi_dj_recv_forward_hidpp(struct dj_device *dj_dev, u8 *data,426426+ int size)427427+{428428+ /* We are called from atomic context (tasklet && djrcv->lock held) */429429+ if (hid_input_report(dj_dev->hdev, HID_INPUT_REPORT, data, size, 1))430430+ dbg_hid("hid_input_report error\n");431431+}576432577433static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,578434 struct dj_report *dj_report)···630472static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,631473 unsigned timeout)632474{475475+ struct hid_device *hdev = djrcv_dev->hdev;633476 struct dj_report *dj_report;477477+ u8 *buf;634478 int retval;635479636480 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);···644484 dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;645485 dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;646486 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);647647- kfree(dj_report);648487649488 /*650489 * Ugly sleep to work around a USB 3.0 bug when the receiver is still···652493 */653494 msleep(50);654495496496+ /*497497+ * Magical bits to set up hidpp notifications when the dj devices498498+ * are connected/disconnected.499499+ *500500+ * We can reuse dj_report because HIDPP_REPORT_SHORT_LENGTH is smaller501501+ * than DJREPORT_SHORT_LENGTH.502502+ */503503+ buf = (u8 *)dj_report;504504+505505+ memset(buf, 0, HIDPP_REPORT_SHORT_LENGTH);506506+507507+ buf[0] = REPORT_ID_HIDPP_SHORT;508508+ buf[1] = 0xFF;509509+ buf[2] = 0x80;510510+ buf[3] = 0x00;511511+ buf[4] = 0x00;512512+ buf[5] = 0x09;513513+ buf[6] = 0x00;514514+515515+ hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf,516516+ HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,517517+ HID_REQ_SET_REPORT);518518+519519+ kfree(dj_report);655520 return retval;656521}657522···692509 dbg_hid("%s:%s\n", __func__, hid->phys);693510}694511512512+static u8 unifying_name_query[] = {0x10, 0xff, 0x83, 0xb5, 0x40, 0x00, 0x00};513513+static u8 unifying_name_answer[] = {0x11, 0xff, 0x83, 0xb5};514514+695515static int logi_dj_ll_raw_request(struct hid_device *hid,696516 unsigned char reportnum, __u8 *buf,697517 size_t count, unsigned char report_type,···704518 struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;705519 u8 *out_buf;706520 int ret;521521+522522+ if ((buf[0] == REPORT_ID_HIDPP_SHORT) ||523523+ (buf[0] == REPORT_ID_HIDPP_LONG)) {524524+ if (count < 2)525525+ return -EINVAL;526526+527527+ /* special case where we should not overwrite528528+ * the device_index */529529+ if (count == 7 && !memcmp(buf, unifying_name_query,530530+ sizeof(unifying_name_query)))531531+ buf[4] |= djdev->device_index - 1;532532+ else533533+ buf[1] = djdev->device_index;534534+ return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf,535535+ count, report_type, reqtype);536536+ }707537708538 if (buf[0] != REPORT_TYPE_LEDS)709539 return -EINVAL;···799597 __func__, djdev->reports_supported);800598 }801599600600+ rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor));601601+802602 retval = hid_parse_report(hid, rdesc, rsize);803603 kfree(rdesc);804604···828624 .raw_request = logi_dj_ll_raw_request,829625};830626831831-832832-static int logi_dj_raw_event(struct hid_device *hdev,627627+static int logi_dj_dj_event(struct hid_device *hdev,833628 struct hid_report *report, u8 *data,834629 int size)835630{···836633 struct dj_report *dj_report = (struct dj_report *) data;837634 unsigned long flags;838635839839- dbg_hid("%s, size:%d\n", __func__, size);840840-841841- /* Here we receive all data coming from iface 2, there are 4 cases:636636+ /*637637+ * Here we receive all data coming from iface 2, there are 3 cases:842638 *843843- * 1) Data should continue its normal processing i.e. data does not844844- * come from the DJ collection, in which case we do nothing and845845- * return 0, so hid-core can continue normal processing (will forward846846- * to associated hidraw device)639639+ * 1) Data is intended for this driver i. e. data contains arrival,640640+ * departure, etc notifications, in which case we queue them for delayed641641+ * processing by the work queue. We return 1 to hid-core as no further642642+ * processing is required from it.847643 *848848- * 2) Data is from DJ collection, and is intended for this driver i. e.849849- * data contains arrival, departure, etc notifications, in which case850850- * we queue them for delayed processing by the work queue. We return 1851851- * to hid-core as no further processing is required from it.644644+ * 2) Data informs a connection change, if the change means rf link645645+ * loss, then we must send a null report to the upper layer to discard646646+ * potentially pressed keys that may be repeated forever by the input647647+ * layer. Return 1 to hid-core as no further processing is required.852648 *853853- * 3) Data is from DJ collection, and informs a connection change,854854- * if the change means rf link loss, then we must send a null report855855- * to the upper layer to discard potentially pressed keys that may be856856- * repeated forever by the input layer. Return 1 to hid-core as no857857- * further processing is required.858858- *859859- * 4) Data is from DJ collection and is an actual input event from860860- * a paired DJ device in which case we forward it to the correct hid861861- * device (via hid_input_report() ) and return 1 so hid-core does not do862862- * anything else with it.649649+ * 3) Data is an actual input event from a paired DJ device in which650650+ * case we forward it to the correct hid device (via hid_input_report()651651+ * ) and return 1 so hid-core does not anything else with it.863652 */864864-865865- /* case 1) */866866- if (data[0] != REPORT_ID_DJ_SHORT)867867- return false;868653869654 if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||870655 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {···898707 return true;899708}900709710710+static int logi_dj_hidpp_event(struct hid_device *hdev,711711+ struct hid_report *report, u8 *data,712712+ int size)713713+{714714+ struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);715715+ struct dj_report *dj_report = (struct dj_report *) data;716716+ unsigned long flags;717717+ u8 device_index = dj_report->device_index;718718+719719+ if (device_index == HIDPP_RECEIVER_INDEX) {720720+ /* special case were the device wants to know its unifying721721+ * name */722722+ if (size == HIDPP_REPORT_LONG_LENGTH &&723723+ !memcmp(data, unifying_name_answer,724724+ sizeof(unifying_name_answer)) &&725725+ ((data[4] & 0xF0) == 0x40))726726+ device_index = (data[4] & 0x0F) + 1;727727+ else728728+ return false;729729+ }730730+731731+ /*732732+ * Data is from the HID++ collection, in this case, we forward the733733+ * data to the corresponding child dj device and return 0 to hid-core734734+ * so he data also goes to the hidraw device of the receiver. This735735+ * allows a user space application to implement the full HID++ routing736736+ * via the receiver.737737+ */738738+739739+ if ((device_index < DJ_DEVICE_INDEX_MIN) ||740740+ (device_index > DJ_DEVICE_INDEX_MAX)) {741741+ /*742742+ * Device index is wrong, bail out.743743+ * This driver can ignore safely the receiver notifications,744744+ * so ignore those reports too.745745+ */746746+ dev_err(&hdev->dev, "%s: invalid device index:%d\n",747747+ __func__, dj_report->device_index);748748+ return false;749749+ }750750+751751+ spin_lock_irqsave(&djrcv_dev->lock, flags);752752+753753+ if (!djrcv_dev->paired_dj_devices[device_index])754754+ /* received an event for an unknown device, bail out */755755+ goto out;756756+757757+ logi_dj_recv_forward_hidpp(djrcv_dev->paired_dj_devices[device_index],758758+ data, size);759759+760760+out:761761+ spin_unlock_irqrestore(&djrcv_dev->lock, flags);762762+763763+ return false;764764+}765765+766766+static int logi_dj_raw_event(struct hid_device *hdev,767767+ struct hid_report *report, u8 *data,768768+ int size)769769+{770770+ dbg_hid("%s, size:%d\n", __func__, size);771771+772772+ switch (data[0]) {773773+ case REPORT_ID_DJ_SHORT:774774+ return logi_dj_dj_event(hdev, report, data, size);775775+ case REPORT_ID_HIDPP_SHORT:776776+ /* intentional fallthrough */777777+ case REPORT_ID_HIDPP_LONG:778778+ return logi_dj_hidpp_event(hdev, report, data, size);779779+ }780780+781781+ return false;782782+}783783+901784static int logi_dj_probe(struct hid_device *hdev,902785 const struct hid_device_id *id)903786{904787 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);905788 struct dj_receiver_dev *djrcv_dev;906789 int retval;907907-908908- if (is_dj_device((struct dj_device *)hdev->driver_data))909909- return -ENODEV;910790911791 dbg_hid("%s called for ifnum %d\n", __func__,912792 intf->cur_altsetting->desc.bInterfaceNumber);···1131869 hid_set_drvdata(hdev, NULL);1132870}113387111341134-static int logi_djdevice_probe(struct hid_device *hdev,11351135- const struct hid_device_id *id)11361136-{11371137- int ret;11381138- struct dj_device *dj_dev = hdev->driver_data;11391139-11401140- if (!is_dj_device(dj_dev))11411141- return -ENODEV;11421142-11431143- ret = hid_parse(hdev);11441144- if (!ret)11451145- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);11461146-11471147- return ret;11481148-}11491149-1150872static const struct hid_device_id logi_dj_receivers[] = {1151873 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,1152874 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},···1152906#endif1153907};1154908909909+module_hid_driver(logi_djreceiver_driver);115591011561156-static const struct hid_device_id logi_dj_devices[] = {11571157- {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,11581158- USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},11591159- {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,11601160- USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},11611161- {}11621162-};11631163-11641164-static struct hid_driver logi_djdevice_driver = {11651165- .name = "logitech-djdevice",11661166- .id_table = logi_dj_devices,11671167- .probe = logi_djdevice_probe,11681168-};11691169-11701170-11711171-static int __init logi_dj_init(void)11721172-{11731173- int retval;11741174-11751175- dbg_hid("Logitech-DJ:%s\n", __func__);11761176-11771177- retval = hid_register_driver(&logi_djreceiver_driver);11781178- if (retval)11791179- return retval;11801180-11811181- retval = hid_register_driver(&logi_djdevice_driver);11821182- if (retval)11831183- hid_unregister_driver(&logi_djreceiver_driver);11841184-11851185- return retval;11861186-11871187-}11881188-11891189-static void __exit logi_dj_exit(void)11901190-{11911191- dbg_hid("Logitech-DJ:%s\n", __func__);11921192-11931193- hid_unregister_driver(&logi_djdevice_driver);11941194- hid_unregister_driver(&logi_djreceiver_driver);11951195-11961196-}11971197-11981198-module_init(logi_dj_init);11991199-module_exit(logi_dj_exit);1200911MODULE_LICENSE("GPL");1201912MODULE_AUTHOR("Logitech");1202913MODULE_AUTHOR("Nestor Lopez Casado");
-125
drivers/hid/hid-logitech-dj.h
···11-#ifndef __HID_LOGITECH_DJ_H22-#define __HID_LOGITECH_DJ_H33-44-/*55- * HID driver for Logitech Unifying receivers66- *77- * Copyright (c) 2011 Logitech88- */99-1010-/*1111- * This program is free software; you can redistribute it and/or modify1212- * it under the terms of the GNU General Public License version 2 as1313- * published by the Free Software Foundation.1414- *1515- * This program is distributed in the hope that it will be useful,1616- * but WITHOUT ANY WARRANTY; without even the implied warranty of1717- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1818- * GNU General Public License for more details.1919- *2020- * You should have received a copy of the GNU General Public License2121- * along with this program; if not, write to the Free Software2222- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2323- *2424- */2525-2626-#include <linux/kfifo.h>2727-2828-#define DJ_MAX_PAIRED_DEVICES 62929-#define DJ_MAX_NUMBER_NOTIFICATIONS 83030-#define DJ_RECEIVER_INDEX 03131-#define DJ_DEVICE_INDEX_MIN 13232-#define DJ_DEVICE_INDEX_MAX 63333-3434-#define DJREPORT_SHORT_LENGTH 153535-#define DJREPORT_LONG_LENGTH 323636-3737-#define REPORT_ID_DJ_SHORT 0x203838-#define REPORT_ID_DJ_LONG 0x213939-4040-#define REPORT_TYPE_RFREPORT_FIRST 0x014141-#define REPORT_TYPE_RFREPORT_LAST 0x1F4242-4343-/* Command Switch to DJ mode */4444-#define REPORT_TYPE_CMD_SWITCH 0x804545-#define CMD_SWITCH_PARAM_DEVBITFIELD 0x004646-#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x014747-#define TIMEOUT_NO_KEEPALIVE 0x004848-4949-/* Command to Get the list of Paired devices */5050-#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x815151-5252-/* Device Paired Notification */5353-#define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x415454-#define SPFUNCTION_MORE_NOTIF_EXPECTED 0x015555-#define SPFUNCTION_DEVICE_LIST_EMPTY 0x025656-#define DEVICE_PAIRED_PARAM_SPFUNCTION 0x005757-#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x015858-#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x025959-#define DEVICE_PAIRED_RF_REPORT_TYPE 0x036060-6161-/* Device Un-Paired Notification */6262-#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x406363-6464-6565-/* Connection Status Notification */6666-#define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x426767-#define CONNECTION_STATUS_PARAM_STATUS 0x006868-#define STATUS_LINKLOSS 0x016969-7070-/* Error Notification */7171-#define REPORT_TYPE_NOTIF_ERROR 0x7F7272-#define NOTIF_ERROR_PARAM_ETYPE 0x007373-#define ETYPE_KEEPALIVE_TIMEOUT 0x017474-7575-/* supported DJ HID && RF report types */7676-#define REPORT_TYPE_KEYBOARD 0x017777-#define REPORT_TYPE_MOUSE 0x027878-#define REPORT_TYPE_CONSUMER_CONTROL 0x037979-#define REPORT_TYPE_SYSTEM_CONTROL 0x048080-#define REPORT_TYPE_MEDIA_CENTER 0x088181-#define REPORT_TYPE_LEDS 0x0E8282-8383-/* RF Report types bitfield */8484-#define STD_KEYBOARD 0x000000028585-#define STD_MOUSE 0x000000048686-#define MULTIMEDIA 0x000000088787-#define POWER_KEYS 0x000000108888-#define MEDIA_CENTER 0x000001008989-#define KBD_LEDS 0x000040009090-9191-struct dj_report {9292- u8 report_id;9393- u8 device_index;9494- u8 report_type;9595- u8 report_params[DJREPORT_SHORT_LENGTH - 3];9696-};9797-9898-struct dj_receiver_dev {9999- struct hid_device *hdev;100100- struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +101101- DJ_DEVICE_INDEX_MIN];102102- struct work_struct work;103103- struct kfifo notif_fifo;104104- spinlock_t lock;105105- bool querying_devices;106106-};107107-108108-struct dj_device {109109- struct hid_device *hdev;110110- struct dj_receiver_dev *dj_receiver_dev;111111- u32 reports_supported;112112- u8 device_index;113113-};114114-115115-/**116116- * is_dj_device - know if the given dj_device is not the receiver.117117- * @dj_dev: the dj device to test118118- *119119- * This macro tests if a struct dj_device pointer is a device created120120- * by the bus enumarator.121121- */122122-#define is_dj_device(dj_dev) \123123- (&(dj_dev)->dj_receiver_dev->hdev->dev == (dj_dev)->hdev->dev.parent)124124-125125-#endif
+1241
drivers/hid/hid-logitech-hidpp.c
···11+/*22+ * HIDPP protocol for Logitech Unifying receivers33+ *44+ * Copyright (c) 2011 Logitech (c)55+ * Copyright (c) 2012-2013 Google (c)66+ * Copyright (c) 2013-2014 Red Hat Inc.77+ */88+99+/*1010+ * This program is free software; you can redistribute it and/or modify it1111+ * under the terms of the GNU General Public License as published by the Free1212+ * Software Foundation; version 2 of the License.1313+ */1414+1515+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt1616+1717+#include <linux/device.h>1818+#include <linux/hid.h>1919+#include <linux/module.h>2020+#include <linux/slab.h>2121+#include <linux/sched.h>2222+#include <linux/kfifo.h>2323+#include <linux/input/mt.h>2424+#include <asm/unaligned.h>2525+#include "hid-ids.h"2626+2727+MODULE_LICENSE("GPL");2828+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");2929+MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>");3030+3131+#define REPORT_ID_HIDPP_SHORT 0x103232+#define REPORT_ID_HIDPP_LONG 0x113333+3434+#define HIDPP_REPORT_SHORT_LENGTH 73535+#define HIDPP_REPORT_LONG_LENGTH 203636+3737+#define HIDPP_QUIRK_CLASS_WTP BIT(0)3838+3939+/* bits 1..20 are reserved for classes */4040+#define HIDPP_QUIRK_DELAYED_INIT BIT(21)4141+#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)4242+#define HIDPP_QUIRK_MULTI_INPUT BIT(23)4343+4444+/*4545+ * There are two hidpp protocols in use, the first version hidpp10 is known4646+ * as register access protocol or RAP, the second version hidpp20 is known as4747+ * feature access protocol or FAP4848+ *4949+ * Most older devices (including the Unifying usb receiver) use the RAP protocol5050+ * where as most newer devices use the FAP protocol. Both protocols are5151+ * compatible with the underlying transport, which could be usb, Unifiying, or5252+ * bluetooth. The message lengths are defined by the hid vendor specific report5353+ * descriptor for the HIDPP_SHORT report type (total message lenth 7 bytes) and5454+ * the HIDPP_LONG report type (total message length 20 bytes)5555+ *5656+ * The RAP protocol uses both report types, whereas the FAP only uses HIDPP_LONG5757+ * messages. The Unifying receiver itself responds to RAP messages (device index5858+ * is 0xFF for the receiver), and all messages (short or long) with a device5959+ * index between 1 and 6 are passed untouched to the corresponding paired6060+ * Unifying device.6161+ *6262+ * The paired device can be RAP or FAP, it will receive the message untouched6363+ * from the Unifiying receiver.6464+ */6565+6666+struct fap {6767+ u8 feature_index;6868+ u8 funcindex_clientid;6969+ u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];7070+};7171+7272+struct rap {7373+ u8 sub_id;7474+ u8 reg_address;7575+ u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];7676+};7777+7878+struct hidpp_report {7979+ u8 report_id;8080+ u8 device_index;8181+ union {8282+ struct fap fap;8383+ struct rap rap;8484+ u8 rawbytes[sizeof(struct fap)];8585+ };8686+} __packed;8787+8888+struct hidpp_device {8989+ struct hid_device *hid_dev;9090+ struct mutex send_mutex;9191+ void *send_receive_buf;9292+ wait_queue_head_t wait;9393+ bool answer_available;9494+ u8 protocol_major;9595+ u8 protocol_minor;9696+9797+ void *private_data;9898+9999+ struct work_struct work;100100+ struct kfifo delayed_work_fifo;101101+ atomic_t connected;102102+ struct input_dev *delayed_input;103103+104104+ unsigned long quirks;105105+};106106+107107+108108+#define HIDPP_ERROR 0x8f109109+#define HIDPP_ERROR_SUCCESS 0x00110110+#define HIDPP_ERROR_INVALID_SUBID 0x01111111+#define HIDPP_ERROR_INVALID_ADRESS 0x02112112+#define HIDPP_ERROR_INVALID_VALUE 0x03113113+#define HIDPP_ERROR_CONNECT_FAIL 0x04114114+#define HIDPP_ERROR_TOO_MANY_DEVICES 0x05115115+#define HIDPP_ERROR_ALREADY_EXISTS 0x06116116+#define HIDPP_ERROR_BUSY 0x07117117+#define HIDPP_ERROR_UNKNOWN_DEVICE 0x08118118+#define HIDPP_ERROR_RESOURCE_ERROR 0x09119119+#define HIDPP_ERROR_REQUEST_UNAVAILABLE 0x0a120120+#define HIDPP_ERROR_INVALID_PARAM_VALUE 0x0b121121+#define HIDPP_ERROR_WRONG_PIN_CODE 0x0c122122+123123+static void hidpp_connect_event(struct hidpp_device *hidpp_dev);124124+125125+static int __hidpp_send_report(struct hid_device *hdev,126126+ struct hidpp_report *hidpp_report)127127+{128128+ int fields_count, ret;129129+130130+ switch (hidpp_report->report_id) {131131+ case REPORT_ID_HIDPP_SHORT:132132+ fields_count = HIDPP_REPORT_SHORT_LENGTH;133133+ break;134134+ case REPORT_ID_HIDPP_LONG:135135+ fields_count = HIDPP_REPORT_LONG_LENGTH;136136+ break;137137+ default:138138+ return -ENODEV;139139+ }140140+141141+ /*142142+ * set the device_index as the receiver, it will be overwritten by143143+ * hid_hw_request if needed144144+ */145145+ hidpp_report->device_index = 0xff;146146+147147+ ret = hid_hw_raw_request(hdev, hidpp_report->report_id,148148+ (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,149149+ HID_REQ_SET_REPORT);150150+151151+ return ret == fields_count ? 0 : -1;152152+}153153+154154+/**155155+ * hidpp_send_message_sync() returns 0 in case of success, and something else156156+ * in case of a failure.157157+ * - If ' something else' is positive, that means that an error has been raised158158+ * by the protocol itself.159159+ * - If ' something else' is negative, that means that we had a classic error160160+ * (-ENOMEM, -EPIPE, etc...)161161+ */162162+static int hidpp_send_message_sync(struct hidpp_device *hidpp,163163+ struct hidpp_report *message,164164+ struct hidpp_report *response)165165+{166166+ int ret;167167+168168+ mutex_lock(&hidpp->send_mutex);169169+170170+ hidpp->send_receive_buf = response;171171+ hidpp->answer_available = false;172172+173173+ /*174174+ * So that we can later validate the answer when it arrives175175+ * in hidpp_raw_event176176+ */177177+ *response = *message;178178+179179+ ret = __hidpp_send_report(hidpp->hid_dev, message);180180+181181+ if (ret) {182182+ dbg_hid("__hidpp_send_report returned err: %d\n", ret);183183+ memset(response, 0, sizeof(struct hidpp_report));184184+ goto exit;185185+ }186186+187187+ if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,188188+ 5*HZ)) {189189+ dbg_hid("%s:timeout waiting for response\n", __func__);190190+ memset(response, 0, sizeof(struct hidpp_report));191191+ ret = -ETIMEDOUT;192192+ }193193+194194+ if (response->report_id == REPORT_ID_HIDPP_SHORT &&195195+ response->fap.feature_index == HIDPP_ERROR) {196196+ ret = response->fap.params[1];197197+ dbg_hid("__hidpp_send_report got hidpp error %02X\n", ret);198198+ goto exit;199199+ }200200+201201+exit:202202+ mutex_unlock(&hidpp->send_mutex);203203+ return ret;204204+205205+}206206+207207+static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,208208+ u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count,209209+ struct hidpp_report *response)210210+{211211+ struct hidpp_report *message;212212+ int ret;213213+214214+ if (param_count > sizeof(message->fap.params))215215+ return -EINVAL;216216+217217+ message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);218218+ if (!message)219219+ return -ENOMEM;220220+ message->report_id = REPORT_ID_HIDPP_LONG;221221+ message->fap.feature_index = feat_index;222222+ message->fap.funcindex_clientid = funcindex_clientid;223223+ memcpy(&message->fap.params, params, param_count);224224+225225+ ret = hidpp_send_message_sync(hidpp, message, response);226226+ kfree(message);227227+ return ret;228228+}229229+230230+static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,231231+ u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count,232232+ struct hidpp_report *response)233233+{234234+ struct hidpp_report *message;235235+ int ret;236236+237237+ if ((report_id != REPORT_ID_HIDPP_SHORT) &&238238+ (report_id != REPORT_ID_HIDPP_LONG))239239+ return -EINVAL;240240+241241+ if (param_count > sizeof(message->rap.params))242242+ return -EINVAL;243243+244244+ message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);245245+ if (!message)246246+ return -ENOMEM;247247+ message->report_id = report_id;248248+ message->rap.sub_id = sub_id;249249+ message->rap.reg_address = reg_address;250250+ memcpy(&message->rap.params, params, param_count);251251+252252+ ret = hidpp_send_message_sync(hidpp_dev, message, response);253253+ kfree(message);254254+ return ret;255255+}256256+257257+static void delayed_work_cb(struct work_struct *work)258258+{259259+ struct hidpp_device *hidpp = container_of(work, struct hidpp_device,260260+ work);261261+ hidpp_connect_event(hidpp);262262+}263263+264264+static inline bool hidpp_match_answer(struct hidpp_report *question,265265+ struct hidpp_report *answer)266266+{267267+ return (answer->fap.feature_index == question->fap.feature_index) &&268268+ (answer->fap.funcindex_clientid == question->fap.funcindex_clientid);269269+}270270+271271+static inline bool hidpp_match_error(struct hidpp_report *question,272272+ struct hidpp_report *answer)273273+{274274+ return (answer->fap.feature_index == HIDPP_ERROR) &&275275+ (answer->fap.funcindex_clientid == question->fap.feature_index) &&276276+ (answer->fap.params[0] == question->fap.funcindex_clientid);277277+}278278+279279+static inline bool hidpp_report_is_connect_event(struct hidpp_report *report)280280+{281281+ return (report->report_id == REPORT_ID_HIDPP_SHORT) &&282282+ (report->rap.sub_id == 0x41);283283+}284284+285285+/* -------------------------------------------------------------------------- */286286+/* HIDP++ 1.0 commands */287287+/* -------------------------------------------------------------------------- */288288+289289+#define HIDPP_SET_REGISTER 0x80290290+#define HIDPP_GET_REGISTER 0x81291291+#define HIDPP_SET_LONG_REGISTER 0x82292292+#define HIDPP_GET_LONG_REGISTER 0x83293293+294294+#define HIDPP_REG_PAIRING_INFORMATION 0xB5295295+#define DEVICE_NAME 0x40296296+297297+static char *hidpp_get_unifying_name(struct hidpp_device *hidpp_dev)298298+{299299+ struct hidpp_report response;300300+ int ret;301301+ /* hid-logitech-dj is in charge of setting the right device index */302302+ u8 params[1] = { DEVICE_NAME };303303+ char *name;304304+ int len;305305+306306+ ret = hidpp_send_rap_command_sync(hidpp_dev,307307+ REPORT_ID_HIDPP_SHORT,308308+ HIDPP_GET_LONG_REGISTER,309309+ HIDPP_REG_PAIRING_INFORMATION,310310+ params, 1, &response);311311+ if (ret)312312+ return NULL;313313+314314+ len = response.rap.params[1];315315+316316+ if (2 + len > sizeof(response.rap.params))317317+ return NULL;318318+319319+ name = kzalloc(len + 1, GFP_KERNEL);320320+ if (!name)321321+ return NULL;322322+323323+ memcpy(name, &response.rap.params[2], len);324324+ return name;325325+}326326+327327+/* -------------------------------------------------------------------------- */328328+/* 0x0000: Root */329329+/* -------------------------------------------------------------------------- */330330+331331+#define HIDPP_PAGE_ROOT 0x0000332332+#define HIDPP_PAGE_ROOT_IDX 0x00333333+334334+#define CMD_ROOT_GET_FEATURE 0x01335335+#define CMD_ROOT_GET_PROTOCOL_VERSION 0x11336336+337337+static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature,338338+ u8 *feature_index, u8 *feature_type)339339+{340340+ struct hidpp_report response;341341+ int ret;342342+ u8 params[2] = { feature >> 8, feature & 0x00FF };343343+344344+ ret = hidpp_send_fap_command_sync(hidpp,345345+ HIDPP_PAGE_ROOT_IDX,346346+ CMD_ROOT_GET_FEATURE,347347+ params, 2, &response);348348+ if (ret)349349+ return ret;350350+351351+ *feature_index = response.fap.params[0];352352+ *feature_type = response.fap.params[1];353353+354354+ return ret;355355+}356356+357357+static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp)358358+{359359+ struct hidpp_report response;360360+ int ret;361361+362362+ ret = hidpp_send_fap_command_sync(hidpp,363363+ HIDPP_PAGE_ROOT_IDX,364364+ CMD_ROOT_GET_PROTOCOL_VERSION,365365+ NULL, 0, &response);366366+367367+ if (ret == HIDPP_ERROR_INVALID_SUBID) {368368+ hidpp->protocol_major = 1;369369+ hidpp->protocol_minor = 0;370370+ return 0;371371+ }372372+373373+ /* the device might not be connected */374374+ if (ret == HIDPP_ERROR_RESOURCE_ERROR)375375+ return -EIO;376376+377377+ if (ret > 0) {378378+ hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",379379+ __func__, ret);380380+ return -EPROTO;381381+ }382382+ if (ret)383383+ return ret;384384+385385+ hidpp->protocol_major = response.fap.params[0];386386+ hidpp->protocol_minor = response.fap.params[1];387387+388388+ return ret;389389+}390390+391391+static bool hidpp_is_connected(struct hidpp_device *hidpp)392392+{393393+ int ret;394394+395395+ ret = hidpp_root_get_protocol_version(hidpp);396396+ if (!ret)397397+ hid_dbg(hidpp->hid_dev, "HID++ %u.%u device connected.\n",398398+ hidpp->protocol_major, hidpp->protocol_minor);399399+ return ret == 0;400400+}401401+402402+/* -------------------------------------------------------------------------- */403403+/* 0x0005: GetDeviceNameType */404404+/* -------------------------------------------------------------------------- */405405+406406+#define HIDPP_PAGE_GET_DEVICE_NAME_TYPE 0x0005407407+408408+#define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x01409409+#define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x11410410+#define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x21411411+412412+static int hidpp_devicenametype_get_count(struct hidpp_device *hidpp,413413+ u8 feature_index, u8 *nameLength)414414+{415415+ struct hidpp_report response;416416+ int ret;417417+418418+ ret = hidpp_send_fap_command_sync(hidpp, feature_index,419419+ CMD_GET_DEVICE_NAME_TYPE_GET_COUNT, NULL, 0, &response);420420+421421+ if (ret > 0) {422422+ hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",423423+ __func__, ret);424424+ return -EPROTO;425425+ }426426+ if (ret)427427+ return ret;428428+429429+ *nameLength = response.fap.params[0];430430+431431+ return ret;432432+}433433+434434+static int hidpp_devicenametype_get_device_name(struct hidpp_device *hidpp,435435+ u8 feature_index, u8 char_index, char *device_name, int len_buf)436436+{437437+ struct hidpp_report response;438438+ int ret, i;439439+ int count;440440+441441+ ret = hidpp_send_fap_command_sync(hidpp, feature_index,442442+ CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME, &char_index, 1,443443+ &response);444444+445445+ if (ret > 0) {446446+ hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",447447+ __func__, ret);448448+ return -EPROTO;449449+ }450450+ if (ret)451451+ return ret;452452+453453+ if (response.report_id == REPORT_ID_HIDPP_LONG)454454+ count = HIDPP_REPORT_LONG_LENGTH - 4;455455+ else456456+ count = HIDPP_REPORT_SHORT_LENGTH - 4;457457+458458+ if (len_buf < count)459459+ count = len_buf;460460+461461+ for (i = 0; i < count; i++)462462+ device_name[i] = response.fap.params[i];463463+464464+ return count;465465+}466466+467467+static char *hidpp_get_device_name(struct hidpp_device *hidpp)468468+{469469+ u8 feature_type;470470+ u8 feature_index;471471+ u8 __name_length;472472+ char *name;473473+ unsigned index = 0;474474+ int ret;475475+476476+ ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_GET_DEVICE_NAME_TYPE,477477+ &feature_index, &feature_type);478478+ if (ret)479479+ return NULL;480480+481481+ ret = hidpp_devicenametype_get_count(hidpp, feature_index,482482+ &__name_length);483483+ if (ret)484484+ return NULL;485485+486486+ name = kzalloc(__name_length + 1, GFP_KERNEL);487487+ if (!name)488488+ return NULL;489489+490490+ while (index < __name_length) {491491+ ret = hidpp_devicenametype_get_device_name(hidpp,492492+ feature_index, index, name + index,493493+ __name_length - index);494494+ if (ret <= 0) {495495+ kfree(name);496496+ return NULL;497497+ }498498+ index += ret;499499+ }500500+501501+ return name;502502+}503503+504504+/* -------------------------------------------------------------------------- */505505+/* 0x6100: TouchPadRawXY */506506+/* -------------------------------------------------------------------------- */507507+508508+#define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100509509+510510+#define CMD_TOUCHPAD_GET_RAW_INFO 0x01511511+#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x21512512+513513+#define EVENT_TOUCHPAD_RAW_XY 0x00514514+515515+#define TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT 0x01516516+#define TOUCHPAD_RAW_XY_ORIGIN_UPPER_LEFT 0x03517517+518518+struct hidpp_touchpad_raw_info {519519+ u16 x_size;520520+ u16 y_size;521521+ u8 z_range;522522+ u8 area_range;523523+ u8 timestamp_unit;524524+ u8 maxcontacts;525525+ u8 origin;526526+ u16 res;527527+};528528+529529+struct hidpp_touchpad_raw_xy_finger {530530+ u8 contact_type;531531+ u8 contact_status;532532+ u16 x;533533+ u16 y;534534+ u8 z;535535+ u8 area;536536+ u8 finger_id;537537+};538538+539539+struct hidpp_touchpad_raw_xy {540540+ u16 timestamp;541541+ struct hidpp_touchpad_raw_xy_finger fingers[2];542542+ u8 spurious_flag;543543+ u8 end_of_frame;544544+ u8 finger_count;545545+ u8 button;546546+};547547+548548+static int hidpp_touchpad_get_raw_info(struct hidpp_device *hidpp,549549+ u8 feature_index, struct hidpp_touchpad_raw_info *raw_info)550550+{551551+ struct hidpp_report response;552552+ int ret;553553+ u8 *params = (u8 *)response.fap.params;554554+555555+ ret = hidpp_send_fap_command_sync(hidpp, feature_index,556556+ CMD_TOUCHPAD_GET_RAW_INFO, NULL, 0, &response);557557+558558+ if (ret > 0) {559559+ hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",560560+ __func__, ret);561561+ return -EPROTO;562562+ }563563+ if (ret)564564+ return ret;565565+566566+ raw_info->x_size = get_unaligned_be16(¶ms[0]);567567+ raw_info->y_size = get_unaligned_be16(¶ms[2]);568568+ raw_info->z_range = params[4];569569+ raw_info->area_range = params[5];570570+ raw_info->maxcontacts = params[7];571571+ raw_info->origin = params[8];572572+ /* res is given in unit per inch */573573+ raw_info->res = get_unaligned_be16(¶ms[13]) * 2 / 51;574574+575575+ return ret;576576+}577577+578578+static int hidpp_touchpad_set_raw_report_state(struct hidpp_device *hidpp_dev,579579+ u8 feature_index, bool send_raw_reports,580580+ bool sensor_enhanced_settings)581581+{582582+ struct hidpp_report response;583583+584584+ /*585585+ * Params:586586+ * bit 0 - enable raw587587+ * bit 1 - 16bit Z, no area588588+ * bit 2 - enhanced sensitivity589589+ * bit 3 - width, height (4 bits each) instead of area590590+ * bit 4 - send raw + gestures (degrades smoothness)591591+ * remaining bits - reserved592592+ */593593+ u8 params = send_raw_reports | (sensor_enhanced_settings << 2);594594+595595+ return hidpp_send_fap_command_sync(hidpp_dev, feature_index,596596+ CMD_TOUCHPAD_SET_RAW_REPORT_STATE, ¶ms, 1, &response);597597+}598598+599599+static void hidpp_touchpad_touch_event(u8 *data,600600+ struct hidpp_touchpad_raw_xy_finger *finger)601601+{602602+ u8 x_m = data[0] << 2;603603+ u8 y_m = data[2] << 2;604604+605605+ finger->x = x_m << 6 | data[1];606606+ finger->y = y_m << 6 | data[3];607607+608608+ finger->contact_type = data[0] >> 6;609609+ finger->contact_status = data[2] >> 6;610610+611611+ finger->z = data[4];612612+ finger->area = data[5];613613+ finger->finger_id = data[6] >> 4;614614+}615615+616616+static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev,617617+ u8 *data, struct hidpp_touchpad_raw_xy *raw_xy)618618+{619619+ memset(raw_xy, 0, sizeof(struct hidpp_touchpad_raw_xy));620620+ raw_xy->end_of_frame = data[8] & 0x01;621621+ raw_xy->spurious_flag = (data[8] >> 1) & 0x01;622622+ raw_xy->finger_count = data[15] & 0x0f;623623+ raw_xy->button = (data[8] >> 2) & 0x01;624624+625625+ if (raw_xy->finger_count) {626626+ hidpp_touchpad_touch_event(&data[2], &raw_xy->fingers[0]);627627+ hidpp_touchpad_touch_event(&data[9], &raw_xy->fingers[1]);628628+ }629629+}630630+631631+/* ************************************************************************** */632632+/* */633633+/* Device Support */634634+/* */635635+/* ************************************************************************** */636636+637637+/* -------------------------------------------------------------------------- */638638+/* Touchpad HID++ devices */639639+/* -------------------------------------------------------------------------- */640640+641641+#define WTP_MANUAL_RESOLUTION 39642642+643643+struct wtp_data {644644+ struct input_dev *input;645645+ u16 x_size, y_size;646646+ u8 finger_count;647647+ u8 mt_feature_index;648648+ u8 button_feature_index;649649+ u8 maxcontacts;650650+ bool flip_y;651651+ unsigned int resolution;652652+};653653+654654+static int wtp_input_mapping(struct hid_device *hdev, struct hid_input *hi,655655+ struct hid_field *field, struct hid_usage *usage,656656+ unsigned long **bit, int *max)657657+{658658+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);659659+660660+ if ((hidpp->quirks & HIDPP_QUIRK_MULTI_INPUT) &&661661+ (field->application == HID_GD_KEYBOARD))662662+ return 0;663663+664664+ return -1;665665+}666666+667667+static void wtp_populate_input(struct hidpp_device *hidpp,668668+ struct input_dev *input_dev, bool origin_is_hid_core)669669+{670670+ struct wtp_data *wd = hidpp->private_data;671671+672672+ if ((hidpp->quirks & HIDPP_QUIRK_MULTI_INPUT) && origin_is_hid_core)673673+ /* this is the generic hid-input call */674674+ return;675675+676676+ __set_bit(EV_ABS, input_dev->evbit);677677+ __set_bit(EV_KEY, input_dev->evbit);678678+ __clear_bit(EV_REL, input_dev->evbit);679679+ __clear_bit(EV_LED, input_dev->evbit);680680+681681+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, wd->x_size, 0, 0);682682+ input_abs_set_res(input_dev, ABS_MT_POSITION_X, wd->resolution);683683+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, wd->y_size, 0, 0);684684+ input_abs_set_res(input_dev, ABS_MT_POSITION_Y, wd->resolution);685685+686686+ /* Max pressure is not given by the devices, pick one */687687+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 50, 0, 0);688688+689689+ input_set_capability(input_dev, EV_KEY, BTN_LEFT);690690+691691+ if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS)692692+ input_set_capability(input_dev, EV_KEY, BTN_RIGHT);693693+ else694694+ __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);695695+696696+ input_mt_init_slots(input_dev, wd->maxcontacts, INPUT_MT_POINTER |697697+ INPUT_MT_DROP_UNUSED);698698+699699+ wd->input = input_dev;700700+}701701+702702+static void wtp_touch_event(struct wtp_data *wd,703703+ struct hidpp_touchpad_raw_xy_finger *touch_report)704704+{705705+ int slot;706706+707707+ if (!touch_report->finger_id || touch_report->contact_type)708708+ /* no actual data */709709+ return;710710+711711+ slot = input_mt_get_slot_by_key(wd->input, touch_report->finger_id);712712+713713+ input_mt_slot(wd->input, slot);714714+ input_mt_report_slot_state(wd->input, MT_TOOL_FINGER,715715+ touch_report->contact_status);716716+ if (touch_report->contact_status) {717717+ input_event(wd->input, EV_ABS, ABS_MT_POSITION_X,718718+ touch_report->x);719719+ input_event(wd->input, EV_ABS, ABS_MT_POSITION_Y,720720+ wd->flip_y ? wd->y_size - touch_report->y :721721+ touch_report->y);722722+ input_event(wd->input, EV_ABS, ABS_MT_PRESSURE,723723+ touch_report->area);724724+ }725725+}726726+727727+static void wtp_send_raw_xy_event(struct hidpp_device *hidpp,728728+ struct hidpp_touchpad_raw_xy *raw)729729+{730730+ struct wtp_data *wd = hidpp->private_data;731731+ int i;732732+733733+ for (i = 0; i < 2; i++)734734+ wtp_touch_event(wd, &(raw->fingers[i]));735735+736736+ if (raw->end_of_frame &&737737+ !(hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS))738738+ input_event(wd->input, EV_KEY, BTN_LEFT, raw->button);739739+740740+ if (raw->end_of_frame || raw->finger_count <= 2) {741741+ input_mt_sync_frame(wd->input);742742+ input_sync(wd->input);743743+ }744744+}745745+746746+static int wtp_mouse_raw_xy_event(struct hidpp_device *hidpp, u8 *data)747747+{748748+ struct wtp_data *wd = hidpp->private_data;749749+ u8 c1_area = ((data[7] & 0xf) * (data[7] & 0xf) +750750+ (data[7] >> 4) * (data[7] >> 4)) / 2;751751+ u8 c2_area = ((data[13] & 0xf) * (data[13] & 0xf) +752752+ (data[13] >> 4) * (data[13] >> 4)) / 2;753753+ struct hidpp_touchpad_raw_xy raw = {754754+ .timestamp = data[1],755755+ .fingers = {756756+ {757757+ .contact_type = 0,758758+ .contact_status = !!data[7],759759+ .x = get_unaligned_le16(&data[3]),760760+ .y = get_unaligned_le16(&data[5]),761761+ .z = c1_area,762762+ .area = c1_area,763763+ .finger_id = data[2],764764+ }, {765765+ .contact_type = 0,766766+ .contact_status = !!data[13],767767+ .x = get_unaligned_le16(&data[9]),768768+ .y = get_unaligned_le16(&data[11]),769769+ .z = c2_area,770770+ .area = c2_area,771771+ .finger_id = data[8],772772+ }773773+ },774774+ .finger_count = wd->maxcontacts,775775+ .spurious_flag = 0,776776+ .end_of_frame = (data[0] >> 7) == 0,777777+ .button = data[0] & 0x01,778778+ };779779+780780+ wtp_send_raw_xy_event(hidpp, &raw);781781+782782+ return 1;783783+}784784+785785+static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size)786786+{787787+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);788788+ struct wtp_data *wd = hidpp->private_data;789789+ struct hidpp_report *report = (struct hidpp_report *)data;790790+ struct hidpp_touchpad_raw_xy raw;791791+792792+ if (!wd || !wd->input)793793+ return 1;794794+795795+ switch (data[0]) {796796+ case 0x02:797797+ if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS) {798798+ input_event(wd->input, EV_KEY, BTN_LEFT,799799+ !!(data[1] & 0x01));800800+ input_event(wd->input, EV_KEY, BTN_RIGHT,801801+ !!(data[1] & 0x02));802802+ input_sync(wd->input);803803+ } else {804804+ if (size < 21)805805+ return 1;806806+ return wtp_mouse_raw_xy_event(hidpp, &data[7]);807807+ }808808+ case REPORT_ID_HIDPP_LONG:809809+ if ((report->fap.feature_index != wd->mt_feature_index) ||810810+ (report->fap.funcindex_clientid != EVENT_TOUCHPAD_RAW_XY))811811+ return 1;812812+ hidpp_touchpad_raw_xy_event(hidpp, data + 4, &raw);813813+814814+ wtp_send_raw_xy_event(hidpp, &raw);815815+ return 0;816816+ }817817+818818+ return 0;819819+}820820+821821+static int wtp_get_config(struct hidpp_device *hidpp)822822+{823823+ struct wtp_data *wd = hidpp->private_data;824824+ struct hidpp_touchpad_raw_info raw_info = {0};825825+ u8 feature_type;826826+ int ret;827827+828828+ ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_TOUCHPAD_RAW_XY,829829+ &wd->mt_feature_index, &feature_type);830830+ if (ret)831831+ /* means that the device is not powered up */832832+ return ret;833833+834834+ ret = hidpp_touchpad_get_raw_info(hidpp, wd->mt_feature_index,835835+ &raw_info);836836+ if (ret)837837+ return ret;838838+839839+ wd->x_size = raw_info.x_size;840840+ wd->y_size = raw_info.y_size;841841+ wd->maxcontacts = raw_info.maxcontacts;842842+ wd->flip_y = raw_info.origin == TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT;843843+ wd->resolution = raw_info.res;844844+ if (!wd->resolution)845845+ wd->resolution = WTP_MANUAL_RESOLUTION;846846+847847+ return 0;848848+}849849+850850+static int wtp_allocate(struct hid_device *hdev, const struct hid_device_id *id)851851+{852852+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);853853+ struct wtp_data *wd;854854+855855+ wd = devm_kzalloc(&hdev->dev, sizeof(struct wtp_data),856856+ GFP_KERNEL);857857+ if (!wd)858858+ return -ENOMEM;859859+860860+ hidpp->private_data = wd;861861+862862+ return 0;863863+};864864+865865+static void wtp_connect(struct hid_device *hdev, bool connected)866866+{867867+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);868868+ struct wtp_data *wd = hidpp->private_data;869869+ int ret;870870+871871+ if (!connected)872872+ return;873873+874874+ if (!wd->x_size) {875875+ ret = wtp_get_config(hidpp);876876+ if (ret) {877877+ hid_err(hdev, "Can not get wtp config: %d\n", ret);878878+ return;879879+ }880880+ }881881+882882+ hidpp_touchpad_set_raw_report_state(hidpp, wd->mt_feature_index,883883+ true, true);884884+}885885+886886+/* -------------------------------------------------------------------------- */887887+/* Generic HID++ devices */888888+/* -------------------------------------------------------------------------- */889889+890890+static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi,891891+ struct hid_field *field, struct hid_usage *usage,892892+ unsigned long **bit, int *max)893893+{894894+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);895895+896896+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)897897+ return wtp_input_mapping(hdev, hi, field, usage, bit, max);898898+899899+ return 0;900900+}901901+902902+static void hidpp_populate_input(struct hidpp_device *hidpp,903903+ struct input_dev *input, bool origin_is_hid_core)904904+{905905+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)906906+ wtp_populate_input(hidpp, input, origin_is_hid_core);907907+}908908+909909+static void hidpp_input_configured(struct hid_device *hdev,910910+ struct hid_input *hidinput)911911+{912912+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);913913+ struct input_dev *input = hidinput->input;914914+915915+ hidpp_populate_input(hidpp, input, true);916916+}917917+918918+static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,919919+ int size)920920+{921921+ struct hidpp_report *question = hidpp->send_receive_buf;922922+ struct hidpp_report *answer = hidpp->send_receive_buf;923923+ struct hidpp_report *report = (struct hidpp_report *)data;924924+925925+ /*926926+ * If the mutex is locked then we have a pending answer from a927927+ * previoulsly sent command928928+ */929929+ if (unlikely(mutex_is_locked(&hidpp->send_mutex))) {930930+ /*931931+ * Check for a correct hidpp20 answer or the corresponding932932+ * error933933+ */934934+ if (hidpp_match_answer(question, report) ||935935+ hidpp_match_error(question, report)) {936936+ *answer = *report;937937+ hidpp->answer_available = true;938938+ wake_up(&hidpp->wait);939939+ /*940940+ * This was an answer to a command that this driver sent941941+ * We return 1 to hid-core to avoid forwarding the942942+ * command upstream as it has been treated by the driver943943+ */944944+945945+ return 1;946946+ }947947+ }948948+949949+ if (unlikely(hidpp_report_is_connect_event(report))) {950950+ atomic_set(&hidpp->connected,951951+ !(report->rap.params[0] & (1 << 6)));952952+ if ((hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) &&953953+ (schedule_work(&hidpp->work) == 0))954954+ dbg_hid("%s: connect event already queued\n", __func__);955955+ return 1;956956+ }957957+958958+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)959959+ return wtp_raw_event(hidpp->hid_dev, data, size);960960+961961+ return 0;962962+}963963+964964+static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,965965+ u8 *data, int size)966966+{967967+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);968968+969969+ switch (data[0]) {970970+ case REPORT_ID_HIDPP_LONG:971971+ if (size != HIDPP_REPORT_LONG_LENGTH) {972972+ hid_err(hdev, "received hid++ report of bad size (%d)",973973+ size);974974+ return 1;975975+ }976976+ return hidpp_raw_hidpp_event(hidpp, data, size);977977+ case REPORT_ID_HIDPP_SHORT:978978+ if (size != HIDPP_REPORT_SHORT_LENGTH) {979979+ hid_err(hdev, "received hid++ report of bad size (%d)",980980+ size);981981+ return 1;982982+ }983983+ return hidpp_raw_hidpp_event(hidpp, data, size);984984+ }985985+986986+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)987987+ return wtp_raw_event(hdev, data, size);988988+989989+ return 0;990990+}991991+992992+static void hidpp_overwrite_name(struct hid_device *hdev, bool use_unifying)993993+{994994+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);995995+ char *name;996996+997997+ if (use_unifying)998998+ /*999999+ * the device is connected through an Unifying receiver, and10001000+ * might not be already connected.10011001+ * Ask the receiver for its name.10021002+ */10031003+ name = hidpp_get_unifying_name(hidpp);10041004+ else10051005+ name = hidpp_get_device_name(hidpp);10061006+10071007+ if (!name)10081008+ hid_err(hdev, "unable to retrieve the name of the device");10091009+ else10101010+ snprintf(hdev->name, sizeof(hdev->name), "%s", name);10111011+10121012+ kfree(name);10131013+}10141014+10151015+static int hidpp_input_open(struct input_dev *dev)10161016+{10171017+ struct hid_device *hid = input_get_drvdata(dev);10181018+10191019+ return hid_hw_open(hid);10201020+}10211021+10221022+static void hidpp_input_close(struct input_dev *dev)10231023+{10241024+ struct hid_device *hid = input_get_drvdata(dev);10251025+10261026+ hid_hw_close(hid);10271027+}10281028+10291029+static struct input_dev *hidpp_allocate_input(struct hid_device *hdev)10301030+{10311031+ struct input_dev *input_dev = devm_input_allocate_device(&hdev->dev);10321032+10331033+ if (!input_dev)10341034+ return NULL;10351035+10361036+ input_set_drvdata(input_dev, hdev);10371037+ input_dev->open = hidpp_input_open;10381038+ input_dev->close = hidpp_input_close;10391039+10401040+ input_dev->name = hdev->name;10411041+ input_dev->phys = hdev->phys;10421042+ input_dev->uniq = hdev->uniq;10431043+ input_dev->id.bustype = hdev->bus;10441044+ input_dev->id.vendor = hdev->vendor;10451045+ input_dev->id.product = hdev->product;10461046+ input_dev->id.version = hdev->version;10471047+ input_dev->dev.parent = &hdev->dev;10481048+10491049+ return input_dev;10501050+}10511051+10521052+static void hidpp_connect_event(struct hidpp_device *hidpp)10531053+{10541054+ struct hid_device *hdev = hidpp->hid_dev;10551055+ int ret = 0;10561056+ bool connected = atomic_read(&hidpp->connected);10571057+ struct input_dev *input;10581058+ char *name, *devm_name;10591059+10601060+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)10611061+ wtp_connect(hdev, connected);10621062+10631063+ if (!connected || hidpp->delayed_input)10641064+ return;10651065+10661066+ if (!hidpp->protocol_major) {10671067+ ret = !hidpp_is_connected(hidpp);10681068+ if (ret) {10691069+ hid_err(hdev, "Can not get the protocol version.\n");10701070+ return;10711071+ }10721072+ }10731073+10741074+ /* the device is already connected, we can ask for its name and10751075+ * protocol */10761076+ hid_info(hdev, "HID++ %u.%u device connected.\n",10771077+ hidpp->protocol_major, hidpp->protocol_minor);10781078+10791079+ input = hidpp_allocate_input(hdev);10801080+ if (!input) {10811081+ hid_err(hdev, "cannot allocate new input device: %d\n", ret);10821082+ return;10831083+ }10841084+10851085+ name = hidpp_get_device_name(hidpp);10861086+ if (!name) {10871087+ hid_err(hdev, "unable to retrieve the name of the device");10881088+ } else {10891089+ devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s", name);10901090+ if (devm_name)10911091+ input->name = devm_name;10921092+ kfree(name);10931093+ }10941094+10951095+ hidpp_populate_input(hidpp, input, false);10961096+10971097+ ret = input_register_device(input);10981098+ if (ret)10991099+ input_free_device(input);11001100+11011101+ hidpp->delayed_input = input;11021102+}11031103+11041104+static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)11051105+{11061106+ struct hidpp_device *hidpp;11071107+ int ret;11081108+ bool connected;11091109+ unsigned int connect_mask = HID_CONNECT_DEFAULT;11101110+11111111+ hidpp = devm_kzalloc(&hdev->dev, sizeof(struct hidpp_device),11121112+ GFP_KERNEL);11131113+ if (!hidpp)11141114+ return -ENOMEM;11151115+11161116+ hidpp->hid_dev = hdev;11171117+ hid_set_drvdata(hdev, hidpp);11181118+11191119+ hidpp->quirks = id->driver_data;11201120+11211121+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {11221122+ ret = wtp_allocate(hdev, id);11231123+ if (ret)11241124+ goto wtp_allocate_fail;11251125+ }11261126+11271127+ INIT_WORK(&hidpp->work, delayed_work_cb);11281128+ mutex_init(&hidpp->send_mutex);11291129+ init_waitqueue_head(&hidpp->wait);11301130+11311131+ ret = hid_parse(hdev);11321132+ if (ret) {11331133+ hid_err(hdev, "%s:parse failed\n", __func__);11341134+ goto hid_parse_fail;11351135+ }11361136+11371137+ /* Allow incoming packets */11381138+ hid_device_io_start(hdev);11391139+11401140+ connected = hidpp_is_connected(hidpp);11411141+ if (id->group != HID_GROUP_LOGITECH_DJ_DEVICE) {11421142+ if (!connected) {11431143+ hid_err(hdev, "Device not connected");11441144+ hid_device_io_stop(hdev);11451145+ goto hid_parse_fail;11461146+ }11471147+11481148+ hid_info(hdev, "HID++ %u.%u device connected.\n",11491149+ hidpp->protocol_major, hidpp->protocol_minor);11501150+ }11511151+11521152+ hidpp_overwrite_name(hdev, id->group == HID_GROUP_LOGITECH_DJ_DEVICE);11531153+ atomic_set(&hidpp->connected, connected);11541154+11551155+ if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {11561156+ ret = wtp_get_config(hidpp);11571157+ if (ret)11581158+ goto hid_parse_fail;11591159+ }11601160+11611161+ /* Block incoming packets */11621162+ hid_device_io_stop(hdev);11631163+11641164+ if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)11651165+ connect_mask &= ~HID_CONNECT_HIDINPUT;11661166+11671167+ /* Re-enable hidinput for multi-input devices */11681168+ if (hidpp->quirks & HIDPP_QUIRK_MULTI_INPUT)11691169+ connect_mask |= HID_CONNECT_HIDINPUT;11701170+11711171+ ret = hid_hw_start(hdev, connect_mask);11721172+ if (ret) {11731173+ hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);11741174+ goto hid_hw_start_fail;11751175+ }11761176+11771177+ if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) {11781178+ /* Allow incoming packets */11791179+ hid_device_io_start(hdev);11801180+11811181+ hidpp_connect_event(hidpp);11821182+ }11831183+11841184+ return ret;11851185+11861186+hid_hw_start_fail:11871187+hid_parse_fail:11881188+ cancel_work_sync(&hidpp->work);11891189+ mutex_destroy(&hidpp->send_mutex);11901190+wtp_allocate_fail:11911191+ hid_set_drvdata(hdev, NULL);11921192+ return ret;11931193+}11941194+11951195+static void hidpp_remove(struct hid_device *hdev)11961196+{11971197+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);11981198+11991199+ cancel_work_sync(&hidpp->work);12001200+ mutex_destroy(&hidpp->send_mutex);12011201+ hid_hw_stop(hdev);12021202+}12031203+12041204+static const struct hid_device_id hidpp_devices[] = {12051205+ { /* wireless touchpad */12061206+ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,12071207+ USB_VENDOR_ID_LOGITECH, 0x4011),12081208+ .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT |12091209+ HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS },12101210+ { /* wireless touchpad T650 */12111211+ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,12121212+ USB_VENDOR_ID_LOGITECH, 0x4101),12131213+ .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT },12141214+ { /* wireless touchpad T651 */12151215+ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,12161216+ USB_DEVICE_ID_LOGITECH_T651),12171217+ .driver_data = HIDPP_QUIRK_CLASS_WTP },12181218+ { /* Keyboard TK820 */12191219+ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,12201220+ USB_VENDOR_ID_LOGITECH, 0x4102),12211221+ .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_MULTI_INPUT |12221222+ HIDPP_QUIRK_CLASS_WTP },12231223+12241224+ { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,12251225+ USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},12261226+ {}12271227+};12281228+12291229+MODULE_DEVICE_TABLE(hid, hidpp_devices);12301230+12311231+static struct hid_driver hidpp_driver = {12321232+ .name = "logitech-hidpp-device",12331233+ .id_table = hidpp_devices,12341234+ .probe = hidpp_probe,12351235+ .remove = hidpp_remove,12361236+ .raw_event = hidpp_raw_event,12371237+ .input_configured = hidpp_input_configured,12381238+ .input_mapping = hidpp_input_mapping,12391239+};12401240+12411241+module_hid_driver(hidpp_driver);
···11+/*22+ * Plantronics USB HID Driver33+ *44+ * Copyright (c) 2014 JD Cole <jd.cole@plantronics.com>55+ * Copyright (c) 2014 Terry Junge <terry.junge@plantronics.com>66+ */77+88+/*99+ * This program is free software; you can redistribute it and/or modify it1010+ * under the terms of the GNU General Public License as published by the Free1111+ * Software Foundation; either version 2 of the License, or (at your option)1212+ * any later version.1313+ */1414+1515+#include "hid-ids.h"1616+1717+#include <linux/hid.h>1818+#include <linux/module.h>1919+2020+static int plantronics_input_mapping(struct hid_device *hdev,2121+ struct hid_input *hi,2222+ struct hid_field *field,2323+ struct hid_usage *usage,2424+ unsigned long **bit, int *max)2525+{2626+ if (field->application == HID_CP_CONSUMERCONTROL2727+ && (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {2828+ hid_dbg(hdev, "usage: %08x (appl: %08x) - defaulted\n",2929+ usage->hid, field->application);3030+ return 0;3131+ }3232+3333+ hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n",3434+ usage->hid, field->application);3535+3636+ return -1;3737+}3838+3939+static const struct hid_device_id plantronics_devices[] = {4040+ { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },4141+ { }4242+};4343+MODULE_DEVICE_TABLE(hid, plantronics_devices);4444+4545+static struct hid_driver plantronics_driver = {4646+ .name = "plantronics",4747+ .id_table = plantronics_devices,4848+ .input_mapping = plantronics_input_mapping,4949+};5050+module_hid_driver(plantronics_driver);5151+5252+MODULE_AUTHOR("JD Cole <jd.cole@plantronics.com>");5353+MODULE_AUTHOR("Terry Junge <terry.junge@plantronics.com>");5454+MODULE_DESCRIPTION("Plantronics USB HID Driver");5555+MODULE_LICENSE("GPL");
+63-20
drivers/hid/hid-rmi.c
···584584 bool has_query10 = false;585585 bool has_query11;586586 bool has_query12;587587+ bool has_query27;588588+ bool has_query28;589589+ bool has_query36 = false;587590 bool has_physical_props;588591 bool has_gestures;589592 bool has_rel;593593+ bool has_data40 = false;590594 unsigned x_size, y_size;591591- u16 query12_offset;595595+ u16 query_offset;592596593597 if (!data->f11.query_base_addr) {594598 hid_err(hdev, "No 2D sensor found, giving up.\n");···608604 has_query9 = !!(buf[0] & BIT(3));609605 has_query11 = !!(buf[0] & BIT(4));610606 has_query12 = !!(buf[0] & BIT(5));607607+ has_query27 = !!(buf[0] & BIT(6));608608+ has_query28 = !!(buf[0] & BIT(7));611609612610 /* query 1 to get the max number of fingers */613611 ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf);···632626 has_rel = !!(buf[0] & BIT(3));633627 has_gestures = !!(buf[0] & BIT(5));634628629629+ /*630630+ * At least 4 queries are guaranteed to be present in F11631631+ * +1 for query 5 which is present since absolute events are632632+ * reported and +1 for query 12.633633+ */634634+ query_offset = 6;635635+636636+ if (has_rel)637637+ ++query_offset; /* query 6 is present */638638+635639 if (has_gestures) {636640 /* query 8 to find out if query 10 exists */637637- ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf);641641+ ret = rmi_read(hdev,642642+ data->f11.query_base_addr + query_offset + 1, buf);638643 if (ret) {639644 hid_err(hdev, "can not read gesture information: %d.\n",640645 ret);641646 return ret;642647 }643648 has_query10 = !!(buf[0] & BIT(2));649649+650650+ query_offset += 2; /* query 7 and 8 are present */644651 }645652646646- /*647647- * At least 4 queries are guaranteed to be present in F11648648- * +1 for query 5 which is present since absolute events are649649- * reported and +1 for query 12.650650- */651651- query12_offset = 6;652652-653653- if (has_rel)654654- ++query12_offset; /* query 6 is present */655655-656656- if (has_gestures)657657- query12_offset += 2; /* query 7 and 8 are present */658658-659653 if (has_query9)660660- ++query12_offset;654654+ ++query_offset;661655662656 if (has_query10)663663- ++query12_offset;657657+ ++query_offset;664658665659 if (has_query11)666666- ++query12_offset;660660+ ++query_offset;667661668662 /* query 12 to know if the physical properties are reported */669663 if (has_query12) {670664 ret = rmi_read(hdev, data->f11.query_base_addr671671- + query12_offset, buf);665665+ + query_offset, buf);672666 if (ret) {673667 hid_err(hdev, "can not get query 12: %d.\n", ret);674668 return ret;···676670 has_physical_props = !!(buf[0] & BIT(5));677671678672 if (has_physical_props) {673673+ query_offset += 1;679674 ret = rmi_read_block(hdev,680675 data->f11.query_base_addr681681- + query12_offset + 1, buf, 4);676676+ + query_offset, buf, 4);682677 if (ret) {683678 hid_err(hdev, "can not read query 15-18: %d.\n",684679 ret);···694687695688 hid_info(hdev, "%s: size in mm: %d x %d\n",696689 __func__, data->x_size_mm, data->y_size_mm);690690+691691+ /*692692+ * query 15 - 18 contain the size of the sensor693693+ * and query 19 - 26 contain bezel dimensions694694+ */695695+ query_offset += 12;697696 }698697 }698698+699699+ if (has_query27)700700+ ++query_offset;701701+702702+ if (has_query28) {703703+ ret = rmi_read(hdev, data->f11.query_base_addr704704+ + query_offset, buf);705705+ if (ret) {706706+ hid_err(hdev, "can not get query 28: %d.\n", ret);707707+ return ret;708708+ }709709+710710+ has_query36 = !!(buf[0] & BIT(6));711711+ }712712+713713+ if (has_query36) {714714+ query_offset += 2;715715+ ret = rmi_read(hdev, data->f11.query_base_addr716716+ + query_offset, buf);717717+ if (ret) {718718+ hid_err(hdev, "can not get query 36: %d.\n", ret);719719+ return ret;720720+ }721721+722722+ has_data40 = !!(buf[0] & BIT(5));723723+ }724724+725725+726726+ if (has_data40)727727+ data->f11.report_size += data->max_fingers * 2;699728700729 /*701730 * retrieve the ctrl registers
+116-34
drivers/hid/hid-sony.c
···798798 __u8 buf[36];799799};800800801801+#define DS4_REPORT_0x02_SIZE 37802802+#define DS4_REPORT_0x05_SIZE 32803803+#define DS4_REPORT_0x11_SIZE 78804804+#define DS4_REPORT_0x81_SIZE 7805805+#define SIXAXIS_REPORT_0xF2_SIZE 18806806+801807static spinlock_t sony_dev_list_lock;802808static LIST_HEAD(sony_device_list);803809static DEFINE_IDA(sony_device_id_allocator);···817811 struct work_struct state_worker;818812 struct power_supply battery;819813 int device_id;814814+ __u8 *output_report_dmabuf;820815821816#ifdef CONFIG_SONY_FF822817 __u8 left;···1149114211501143static int sixaxis_set_operational_bt(struct hid_device *hdev)11511144{11521152- unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };11531153- return hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),11451145+ static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };11461146+ __u8 *buf;11471147+ int ret;11481148+11491149+ buf = kmemdup(report, sizeof(report), GFP_KERNEL);11501150+ if (!buf)11511151+ return -ENOMEM;11521152+11531153+ ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),11541154 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);11551155+11561156+ kfree(buf);11571157+11581158+ return ret;11551159}1156116011571161/*···11711153 */11721154static int dualshock4_set_operational_bt(struct hid_device *hdev)11731155{11741174- __u8 buf[37] = { 0 };11561156+ __u8 *buf;11571157+ int ret;1175115811761176- return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf),11591159+ buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL);11601160+ if (!buf)11611161+ return -ENOMEM;11621162+11631163+ ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE,11771164 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);11651165+11661166+ kfree(buf);11671167+11681168+ return ret;11781169}1179117011801171static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS])···1498147114991472static void sixaxis_state_worker(struct work_struct *work)15001473{15011501- struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);15021502- int n;15031503- union sixaxis_output_report_01 report = {14741474+ static const union sixaxis_output_report_01 default_report = {15041475 .buf = {15051476 0x01,15061477 0x00, 0xff, 0x00, 0xff, 0x00,···15101485 0x00, 0x00, 0x00, 0x00, 0x0015111486 }15121487 };14881488+ struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);14891489+ struct sixaxis_output_report *report =14901490+ (struct sixaxis_output_report *)sc->output_report_dmabuf;14911491+ int n;14921492+14931493+ /* Initialize the report with default values */14941494+ memcpy(report, &default_report, sizeof(struct sixaxis_output_report));1513149515141496#ifdef CONFIG_SONY_FF15151515- report.data.rumble.right_motor_on = sc->right ? 1 : 0;15161516- report.data.rumble.left_motor_force = sc->left;14971497+ report->rumble.right_motor_on = sc->right ? 1 : 0;14981498+ report->rumble.left_motor_force = sc->left;15171499#endif1518150015191519- report.data.leds_bitmap |= sc->led_state[0] << 1;15201520- report.data.leds_bitmap |= sc->led_state[1] << 2;15211521- report.data.leds_bitmap |= sc->led_state[2] << 3;15221522- report.data.leds_bitmap |= sc->led_state[3] << 4;15011501+ report->leds_bitmap |= sc->led_state[0] << 1;15021502+ report->leds_bitmap |= sc->led_state[1] << 2;15031503+ report->leds_bitmap |= sc->led_state[2] << 3;15041504+ report->leds_bitmap |= sc->led_state[3] << 4;1523150515241506 /* Set flag for all leds off, required for 3rd party INTEC controller */15251525- if ((report.data.leds_bitmap & 0x1E) == 0)15261526- report.data.leds_bitmap |= 0x20;15071507+ if ((report->leds_bitmap & 0x1E) == 0)15081508+ report->leds_bitmap |= 0x20;1527150915281510 /*15291511 * The LEDs in the report are indexed in reverse order to their···15431511 */15441512 for (n = 0; n < 4; n++) {15451513 if (sc->led_delay_on[n] || sc->led_delay_off[n]) {15461546- report.data.led[3 - n].duty_off = sc->led_delay_off[n];15471547- report.data.led[3 - n].duty_on = sc->led_delay_on[n];15141514+ report->led[3 - n].duty_off = sc->led_delay_off[n];15151515+ report->led[3 - n].duty_on = sc->led_delay_on[n];15481516 }15491517 }1550151815511551- hid_hw_raw_request(sc->hdev, report.data.report_id, report.buf,15521552- sizeof(report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);15191519+ hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report,15201520+ sizeof(struct sixaxis_output_report),15211521+ HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);15531522}1554152315551524static void dualshock4_state_worker(struct work_struct *work)15561525{15571526 struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);15581527 struct hid_device *hdev = sc->hdev;15281528+ __u8 *buf = sc->output_report_dmabuf;15591529 int offset;1560153015611561- __u8 buf[78] = { 0 };15621562-15631531 if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {15321532+ memset(buf, 0, DS4_REPORT_0x05_SIZE);15641533 buf[0] = 0x05;15651534 buf[1] = 0xFF;15661535 offset = 4;15671536 } else {15371537+ memset(buf, 0, DS4_REPORT_0x11_SIZE);15681538 buf[0] = 0x11;15691539 buf[1] = 0xB0;15701540 buf[3] = 0x0F;···15941560 buf[offset++] = sc->led_delay_off[3];1595156115961562 if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)15971597- hid_hw_output_report(hdev, buf, 32);15631563+ hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE);15981564 else15991599- hid_hw_raw_request(hdev, 0x11, buf, 78,15651565+ hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE,16001566 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);15671567+}15681568+15691569+static int sony_allocate_output_report(struct sony_sc *sc)15701570+{15711571+ if (sc->quirks & SIXAXIS_CONTROLLER)15721572+ sc->output_report_dmabuf =15731573+ kmalloc(sizeof(union sixaxis_output_report_01),15741574+ GFP_KERNEL);15751575+ else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)15761576+ sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE,15771577+ GFP_KERNEL);15781578+ else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)15791579+ sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,15801580+ GFP_KERNEL);15811581+ else15821582+ return 0;15831583+15841584+ if (!sc->output_report_dmabuf)15851585+ return -ENOMEM;15861586+15871587+ return 0;16011588}1602158916031590#ifdef CONFIG_SONY_FF···1809175418101755static int sony_check_add(struct sony_sc *sc)18111756{17571757+ __u8 *buf = NULL;18121758 int n, ret;1813175918141760 if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||···18251769 return 0;18261770 }18271771 } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {18281828- __u8 buf[7];17721772+ buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL);17731773+ if (!buf)17741774+ return -ENOMEM;1829177518301776 /*18311777 * The MAC address of a DS4 controller connected via USB can be18321778 * retrieved with feature report 0x81. The address begins at18331779 * offset 1.18341780 */18351835- ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf),18361836- HID_FEATURE_REPORT, HID_REQ_GET_REPORT);17811781+ ret = hid_hw_raw_request(sc->hdev, 0x81, buf,17821782+ DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT,17831783+ HID_REQ_GET_REPORT);1837178418381838- if (ret != 7) {17851785+ if (ret != DS4_REPORT_0x81_SIZE) {18391786 hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");18401840- return ret < 0 ? ret : -EINVAL;17871787+ ret = ret < 0 ? ret : -EINVAL;17881788+ goto out_free;18411789 }1842179018431791 memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));18441792 } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) {18451845- __u8 buf[18];17931793+ buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);17941794+ if (!buf)17951795+ return -ENOMEM;1846179618471797 /*18481798 * The MAC address of a Sixaxis controller connected via USB can18491799 * be retrieved with feature report 0xf2. The address begins at18501800 * offset 4.18511801 */18521852- ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf),18531853- HID_FEATURE_REPORT, HID_REQ_GET_REPORT);18021802+ ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,18031803+ SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,18041804+ HID_REQ_GET_REPORT);1854180518551855- if (ret != 18) {18061806+ if (ret != SIXAXIS_REPORT_0xF2_SIZE) {18561807 hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");18571857- return ret < 0 ? ret : -EINVAL;18081808+ ret = ret < 0 ? ret : -EINVAL;18091809+ goto out_free;18581810 }1859181118601812 /*···18751811 return 0;18761812 }1877181318781878- return sony_check_add_dev_list(sc);18141814+ ret = sony_check_add_dev_list(sc);18151815+18161816+out_free:18171817+18181818+ kfree(buf);18191819+18201820+ return ret;18791821}1880182218811823static int sony_set_device_id(struct sony_sc *sc)···19631893 if (ret) {19641894 hid_err(hdev, "hw start failed\n");19651895 return ret;18961896+ }18971897+18981898+ ret = sony_allocate_output_report(sc);18991899+ if (ret < 0) {19001900+ hid_err(hdev, "failed to allocate the output report buffer\n");19011901+ goto err_stop;19661902 }1967190319681904 ret = sony_set_device_id(sc);···20601984 if (sc->quirks & SONY_BATTERY_SUPPORT)20611985 sony_battery_remove(sc);20621986 sony_cancel_work_sync(sc);19871987+ kfree(sc->output_report_dmabuf);20631988 sony_remove_dev_list(sc);20641989 sony_release_device_id(sc);20651990 hid_hw_stop(hdev);···20802003 }2081200420822005 sony_cancel_work_sync(sc);20062006+20072007+ kfree(sc->output_report_dmabuf);2083200820842009 sony_remove_dev_list(sc);20852010···21122033 .driver_data = PS3REMOTE },21132034 /* Logitech Harmony Adapter for PS3 */21142035 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),20362036+ .driver_data = PS3REMOTE },20372037+ /* SMK-Link PS3 BD Remote Control */20382038+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),21152039 .driver_data = PS3REMOTE },21162040 /* Sony Dualshock 4 controllers for PS4 */21172041 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),