aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-logitech-dj.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-logitech-dj.c')
-rw-r--r--drivers/hid/hid-logitech-dj.c397
1 files changed, 300 insertions, 97 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 71f569292cab..c917ab61aafa 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -26,9 +26,104 @@
26#include <linux/hid.h> 26#include <linux/hid.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/usb.h> 28#include <linux/usb.h>
29#include <linux/kfifo.h>
29#include <asm/unaligned.h> 30#include <asm/unaligned.h>
30#include "hid-ids.h" 31#include "hid-ids.h"
31#include "hid-logitech-dj.h" 32
33#define DJ_MAX_PAIRED_DEVICES 6
34#define DJ_MAX_NUMBER_NOTIFICATIONS 8
35#define DJ_RECEIVER_INDEX 0
36#define DJ_DEVICE_INDEX_MIN 1
37#define DJ_DEVICE_INDEX_MAX 6
38
39#define DJREPORT_SHORT_LENGTH 15
40#define DJREPORT_LONG_LENGTH 32
41
42#define REPORT_ID_DJ_SHORT 0x20
43#define REPORT_ID_DJ_LONG 0x21
44
45#define REPORT_ID_HIDPP_SHORT 0x10
46#define REPORT_ID_HIDPP_LONG 0x11
47
48#define HIDPP_REPORT_SHORT_LENGTH 7
49#define HIDPP_REPORT_LONG_LENGTH 20
50
51#define HIDPP_RECEIVER_INDEX 0xff
52
53#define REPORT_TYPE_RFREPORT_FIRST 0x01
54#define REPORT_TYPE_RFREPORT_LAST 0x1F
55
56/* Command Switch to DJ mode */
57#define REPORT_TYPE_CMD_SWITCH 0x80
58#define CMD_SWITCH_PARAM_DEVBITFIELD 0x00
59#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01
60#define TIMEOUT_NO_KEEPALIVE 0x00
61
62/* Command to Get the list of Paired devices */
63#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81
64
65/* Device Paired Notification */
66#define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41
67#define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01
68#define SPFUNCTION_DEVICE_LIST_EMPTY 0x02
69#define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00
70#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01
71#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02
72#define DEVICE_PAIRED_RF_REPORT_TYPE 0x03
73
74/* Device Un-Paired Notification */
75#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40
76
77
78/* Connection Status Notification */
79#define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42
80#define CONNECTION_STATUS_PARAM_STATUS 0x00
81#define STATUS_LINKLOSS 0x01
82
83/* Error Notification */
84#define REPORT_TYPE_NOTIF_ERROR 0x7F
85#define NOTIF_ERROR_PARAM_ETYPE 0x00
86#define ETYPE_KEEPALIVE_TIMEOUT 0x01
87
88/* supported DJ HID && RF report types */
89#define REPORT_TYPE_KEYBOARD 0x01
90#define REPORT_TYPE_MOUSE 0x02
91#define REPORT_TYPE_CONSUMER_CONTROL 0x03
92#define REPORT_TYPE_SYSTEM_CONTROL 0x04
93#define REPORT_TYPE_MEDIA_CENTER 0x08
94#define REPORT_TYPE_LEDS 0x0E
95
96/* RF Report types bitfield */
97#define STD_KEYBOARD 0x00000002
98#define STD_MOUSE 0x00000004
99#define MULTIMEDIA 0x00000008
100#define POWER_KEYS 0x00000010
101#define MEDIA_CENTER 0x00000100
102#define KBD_LEDS 0x00004000
103
104struct dj_report {
105 u8 report_id;
106 u8 device_index;
107 u8 report_type;
108 u8 report_params[DJREPORT_SHORT_LENGTH - 3];
109};
110
111struct dj_receiver_dev {
112 struct hid_device *hdev;
113 struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +
114 DJ_DEVICE_INDEX_MIN];
115 struct work_struct work;
116 struct kfifo notif_fifo;
117 spinlock_t lock;
118 bool querying_devices;
119};
120
121struct dj_device {
122 struct hid_device *hdev;
123 struct dj_receiver_dev *dj_receiver_dev;
124 u32 reports_supported;
125 u8 device_index;
126};
32 127
33/* Keyboard descriptor (1) */ 128/* Keyboard descriptor (1) */
34static const char kbd_descriptor[] = { 129static const char kbd_descriptor[] = {
@@ -156,6 +251,57 @@ static const char media_descriptor[] = {
156 0xc0, /* EndCollection */ 251 0xc0, /* EndCollection */
157}; /* */ 252}; /* */
158 253
254/* HIDPP descriptor */
255static const char hidpp_descriptor[] = {
256 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
257 0x09, 0x01, /* Usage (Vendor Usage 1) */
258 0xa1, 0x01, /* Collection (Application) */
259 0x85, 0x10, /* Report ID (16) */
260 0x75, 0x08, /* Report Size (8) */
261 0x95, 0x06, /* Report Count (6) */
262 0x15, 0x00, /* Logical Minimum (0) */
263 0x26, 0xff, 0x00, /* Logical Maximum (255) */
264 0x09, 0x01, /* Usage (Vendor Usage 1) */
265 0x81, 0x00, /* Input (Data,Arr,Abs) */
266 0x09, 0x01, /* Usage (Vendor Usage 1) */
267 0x91, 0x00, /* Output (Data,Arr,Abs) */
268 0xc0, /* End Collection */
269 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
270 0x09, 0x02, /* Usage (Vendor Usage 2) */
271 0xa1, 0x01, /* Collection (Application) */
272 0x85, 0x11, /* Report ID (17) */
273 0x75, 0x08, /* Report Size (8) */
274 0x95, 0x13, /* Report Count (19) */
275 0x15, 0x00, /* Logical Minimum (0) */
276 0x26, 0xff, 0x00, /* Logical Maximum (255) */
277 0x09, 0x02, /* Usage (Vendor Usage 2) */
278 0x81, 0x00, /* Input (Data,Arr,Abs) */
279 0x09, 0x02, /* Usage (Vendor Usage 2) */
280 0x91, 0x00, /* Output (Data,Arr,Abs) */
281 0xc0, /* End Collection */
282 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
283 0x09, 0x04, /* Usage (Vendor Usage 0x04) */
284 0xa1, 0x01, /* Collection (Application) */
285 0x85, 0x20, /* Report ID (32) */
286 0x75, 0x08, /* Report Size (8) */
287 0x95, 0x0e, /* Report Count (14) */
288 0x15, 0x00, /* Logical Minimum (0) */
289 0x26, 0xff, 0x00, /* Logical Maximum (255) */
290 0x09, 0x41, /* Usage (Vendor Usage 0x41) */
291 0x81, 0x00, /* Input (Data,Arr,Abs) */
292 0x09, 0x41, /* Usage (Vendor Usage 0x41) */
293 0x91, 0x00, /* Output (Data,Arr,Abs) */
294 0x85, 0x21, /* Report ID (33) */
295 0x95, 0x1f, /* Report Count (31) */
296 0x15, 0x00, /* Logical Minimum (0) */
297 0x26, 0xff, 0x00, /* Logical Maximum (255) */
298 0x09, 0x42, /* Usage (Vendor Usage 0x42) */
299 0x81, 0x00, /* Input (Data,Arr,Abs) */
300 0x09, 0x42, /* Usage (Vendor Usage 0x42) */
301 0x91, 0x00, /* Output (Data,Arr,Abs) */
302 0xc0, /* End Collection */
303};
304
159/* Maximum size of all defined hid reports in bytes (including report id) */ 305/* Maximum size of all defined hid reports in bytes (including report id) */
160#define MAX_REPORT_SIZE 8 306#define MAX_REPORT_SIZE 8
161 307
@@ -165,7 +311,8 @@ static const char media_descriptor[] = {
165 sizeof(mse_descriptor) + \ 311 sizeof(mse_descriptor) + \
166 sizeof(consumer_descriptor) + \ 312 sizeof(consumer_descriptor) + \
167 sizeof(syscontrol_descriptor) + \ 313 sizeof(syscontrol_descriptor) + \
168 sizeof(media_descriptor)) 314 sizeof(media_descriptor) + \
315 sizeof(hidpp_descriptor))
169 316
170/* Number of possible hid report types that can be created by this driver. 317/* Number of possible hid report types that can be created by this driver.
171 * 318 *
@@ -256,11 +403,15 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
256 dj_hiddev->dev.parent = &djrcv_hdev->dev; 403 dj_hiddev->dev.parent = &djrcv_hdev->dev;
257 dj_hiddev->bus = BUS_USB; 404 dj_hiddev->bus = BUS_USB;
258 dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor); 405 dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
259 dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct); 406 dj_hiddev->product =
407 (dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB]
408 << 8) |
409 dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB];
260 snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), 410 snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
261 "Logitech Unifying Device. Wireless PID:%02x%02x", 411 "Logitech Unifying Device. Wireless PID:%04x",
262 dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB], 412 dj_hiddev->product);
263 dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]); 413
414 dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE;
264 415
265 usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys)); 416 usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
266 snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); 417 snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
@@ -422,6 +573,13 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
422 } 573 }
423} 574}
424 575
576static void logi_dj_recv_forward_hidpp(struct dj_device *dj_dev, u8 *data,
577 int size)
578{
579 /* We are called from atomic context (tasklet && djrcv->lock held) */
580 if (hid_input_report(dj_dev->hdev, HID_INPUT_REPORT, data, size, 1))
581 dbg_hid("hid_input_report error\n");
582}
425 583
426static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, 584static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
427 struct dj_report *dj_report) 585 struct dj_report *dj_report)
@@ -472,7 +630,9 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
472static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, 630static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
473 unsigned timeout) 631 unsigned timeout)
474{ 632{
633 struct hid_device *hdev = djrcv_dev->hdev;
475 struct dj_report *dj_report; 634 struct dj_report *dj_report;
635 u8 *buf;
476 int retval; 636 int retval;
477 637
478 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); 638 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
@@ -484,7 +644,6 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
484 dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F; 644 dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;
485 dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout; 645 dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;
486 retval = logi_dj_recv_send_report(djrcv_dev, dj_report); 646 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
487 kfree(dj_report);
488 647
489 /* 648 /*
490 * Ugly sleep to work around a USB 3.0 bug when the receiver is still 649 * Ugly sleep to work around a USB 3.0 bug when the receiver is still
@@ -493,6 +652,30 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
493 */ 652 */
494 msleep(50); 653 msleep(50);
495 654
655 /*
656 * Magical bits to set up hidpp notifications when the dj devices
657 * are connected/disconnected.
658 *
659 * We can reuse dj_report because HIDPP_REPORT_SHORT_LENGTH is smaller
660 * than DJREPORT_SHORT_LENGTH.
661 */
662 buf = (u8 *)dj_report;
663
664 memset(buf, 0, HIDPP_REPORT_SHORT_LENGTH);
665
666 buf[0] = REPORT_ID_HIDPP_SHORT;
667 buf[1] = 0xFF;
668 buf[2] = 0x80;
669 buf[3] = 0x00;
670 buf[4] = 0x00;
671 buf[5] = 0x09;
672 buf[6] = 0x00;
673
674 hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf,
675 HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,
676 HID_REQ_SET_REPORT);
677
678 kfree(dj_report);
496 return retval; 679 return retval;
497} 680}
498 681
@@ -509,6 +692,9 @@ static void logi_dj_ll_close(struct hid_device *hid)
509 dbg_hid("%s:%s\n", __func__, hid->phys); 692 dbg_hid("%s:%s\n", __func__, hid->phys);
510} 693}
511 694
695static u8 unifying_name_query[] = {0x10, 0xff, 0x83, 0xb5, 0x40, 0x00, 0x00};
696static u8 unifying_name_answer[] = {0x11, 0xff, 0x83, 0xb5};
697
512static int logi_dj_ll_raw_request(struct hid_device *hid, 698static int logi_dj_ll_raw_request(struct hid_device *hid,
513 unsigned char reportnum, __u8 *buf, 699 unsigned char reportnum, __u8 *buf,
514 size_t count, unsigned char report_type, 700 size_t count, unsigned char report_type,
@@ -519,6 +705,22 @@ static int logi_dj_ll_raw_request(struct hid_device *hid,
519 u8 *out_buf; 705 u8 *out_buf;
520 int ret; 706 int ret;
521 707
708 if ((buf[0] == REPORT_ID_HIDPP_SHORT) ||
709 (buf[0] == REPORT_ID_HIDPP_LONG)) {
710 if (count < 2)
711 return -EINVAL;
712
713 /* special case where we should not overwrite
714 * the device_index */
715 if (count == 7 && !memcmp(buf, unifying_name_query,
716 sizeof(unifying_name_query)))
717 buf[4] |= djdev->device_index - 1;
718 else
719 buf[1] = djdev->device_index;
720 return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf,
721 count, report_type, reqtype);
722 }
723
522 if (buf[0] != REPORT_TYPE_LEDS) 724 if (buf[0] != REPORT_TYPE_LEDS)
523 return -EINVAL; 725 return -EINVAL;
524 726
@@ -597,6 +799,8 @@ static int logi_dj_ll_parse(struct hid_device *hid)
597 __func__, djdev->reports_supported); 799 __func__, djdev->reports_supported);
598 } 800 }
599 801
802 rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor));
803
600 retval = hid_parse_report(hid, rdesc, rsize); 804 retval = hid_parse_report(hid, rdesc, rsize);
601 kfree(rdesc); 805 kfree(rdesc);
602 806
@@ -624,8 +828,7 @@ static struct hid_ll_driver logi_dj_ll_driver = {
624 .raw_request = logi_dj_ll_raw_request, 828 .raw_request = logi_dj_ll_raw_request,
625}; 829};
626 830
627 831static int logi_dj_dj_event(struct hid_device *hdev,
628static int logi_dj_raw_event(struct hid_device *hdev,
629 struct hid_report *report, u8 *data, 832 struct hid_report *report, u8 *data,
630 int size) 833 int size)
631{ 834{
@@ -633,36 +836,24 @@ static int logi_dj_raw_event(struct hid_device *hdev,
633 struct dj_report *dj_report = (struct dj_report *) data; 836 struct dj_report *dj_report = (struct dj_report *) data;
634 unsigned long flags; 837 unsigned long flags;
635 838
636 dbg_hid("%s, size:%d\n", __func__, size); 839 /*
637 840 * Here we receive all data coming from iface 2, there are 3 cases:
638 /* Here we receive all data coming from iface 2, there are 4 cases:
639 *
640 * 1) Data should continue its normal processing i.e. data does not
641 * come from the DJ collection, in which case we do nothing and
642 * return 0, so hid-core can continue normal processing (will forward
643 * to associated hidraw device)
644 * 841 *
645 * 2) Data is from DJ collection, and is intended for this driver i. e. 842 * 1) Data is intended for this driver i. e. data contains arrival,
646 * data contains arrival, departure, etc notifications, in which case 843 * departure, etc notifications, in which case we queue them for delayed
647 * we queue them for delayed processing by the work queue. We return 1 844 * processing by the work queue. We return 1 to hid-core as no further
648 * to hid-core as no further processing is required from it. 845 * processing is required from it.
649 * 846 *
650 * 3) Data is from DJ collection, and informs a connection change, 847 * 2) Data informs a connection change, if the change means rf link
651 * if the change means rf link loss, then we must send a null report 848 * loss, then we must send a null report to the upper layer to discard
652 * to the upper layer to discard potentially pressed keys that may be 849 * potentially pressed keys that may be repeated forever by the input
653 * repeated forever by the input layer. Return 1 to hid-core as no 850 * layer. Return 1 to hid-core as no further processing is required.
654 * further processing is required.
655 * 851 *
656 * 4) Data is from DJ collection and is an actual input event from 852 * 3) Data is an actual input event from a paired DJ device in which
657 * a paired DJ device in which case we forward it to the correct hid 853 * case we forward it to the correct hid device (via hid_input_report()
658 * device (via hid_input_report() ) and return 1 so hid-core does not do 854 * ) and return 1 so hid-core does not anything else with it.
659 * anything else with it.
660 */ 855 */
661 856
662 /* case 1) */
663 if (data[0] != REPORT_ID_DJ_SHORT)
664 return false;
665
666 if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || 857 if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
667 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { 858 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
668 /* 859 /*
@@ -707,6 +898,80 @@ out:
707 return true; 898 return true;
708} 899}
709 900
901static int logi_dj_hidpp_event(struct hid_device *hdev,
902 struct hid_report *report, u8 *data,
903 int size)
904{
905 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
906 struct dj_report *dj_report = (struct dj_report *) data;
907 unsigned long flags;
908 u8 device_index = dj_report->device_index;
909
910 if (device_index == HIDPP_RECEIVER_INDEX) {
911 /* special case were the device wants to know its unifying
912 * name */
913 if (size == HIDPP_REPORT_LONG_LENGTH &&
914 !memcmp(data, unifying_name_answer,
915 sizeof(unifying_name_answer)) &&
916 ((data[4] & 0xF0) == 0x40))
917 device_index = (data[4] & 0x0F) + 1;
918 else
919 return false;
920 }
921
922 /*
923 * Data is from the HID++ collection, in this case, we forward the
924 * data to the corresponding child dj device and return 0 to hid-core
925 * so he data also goes to the hidraw device of the receiver. This
926 * allows a user space application to implement the full HID++ routing
927 * via the receiver.
928 */
929
930 if ((device_index < DJ_DEVICE_INDEX_MIN) ||
931 (device_index > DJ_DEVICE_INDEX_MAX)) {
932 /*
933 * Device index is wrong, bail out.
934 * This driver can ignore safely the receiver notifications,
935 * so ignore those reports too.
936 */
937 dev_err(&hdev->dev, "%s: invalid device index:%d\n",
938 __func__, dj_report->device_index);
939 return false;
940 }
941
942 spin_lock_irqsave(&djrcv_dev->lock, flags);
943
944 if (!djrcv_dev->paired_dj_devices[device_index])
945 /* received an event for an unknown device, bail out */
946 goto out;
947
948 logi_dj_recv_forward_hidpp(djrcv_dev->paired_dj_devices[device_index],
949 data, size);
950
951out:
952 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
953
954 return false;
955}
956
957static int logi_dj_raw_event(struct hid_device *hdev,
958 struct hid_report *report, u8 *data,
959 int size)
960{
961 dbg_hid("%s, size:%d\n", __func__, size);
962
963 switch (data[0]) {
964 case REPORT_ID_DJ_SHORT:
965 return logi_dj_dj_event(hdev, report, data, size);
966 case REPORT_ID_HIDPP_SHORT:
967 /* intentional fallthrough */
968 case REPORT_ID_HIDPP_LONG:
969 return logi_dj_hidpp_event(hdev, report, data, size);
970 }
971
972 return false;
973}
974
710static int logi_dj_probe(struct hid_device *hdev, 975static int logi_dj_probe(struct hid_device *hdev,
711 const struct hid_device_id *id) 976 const struct hid_device_id *id)
712{ 977{
@@ -714,9 +979,6 @@ static int logi_dj_probe(struct hid_device *hdev,
714 struct dj_receiver_dev *djrcv_dev; 979 struct dj_receiver_dev *djrcv_dev;
715 int retval; 980 int retval;
716 981
717 if (is_dj_device((struct dj_device *)hdev->driver_data))
718 return -ENODEV;
719
720 dbg_hid("%s called for ifnum %d\n", __func__, 982 dbg_hid("%s called for ifnum %d\n", __func__,
721 intf->cur_altsetting->desc.bInterfaceNumber); 983 intf->cur_altsetting->desc.bInterfaceNumber);
722 984
@@ -869,22 +1131,6 @@ static void logi_dj_remove(struct hid_device *hdev)
869 hid_set_drvdata(hdev, NULL); 1131 hid_set_drvdata(hdev, NULL);
870} 1132}
871 1133
872static int logi_djdevice_probe(struct hid_device *hdev,
873 const struct hid_device_id *id)
874{
875 int ret;
876 struct dj_device *dj_dev = hdev->driver_data;
877
878 if (!is_dj_device(dj_dev))
879 return -ENODEV;
880
881 ret = hid_parse(hdev);
882 if (!ret)
883 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
884
885 return ret;
886}
887
888static const struct hid_device_id logi_dj_receivers[] = { 1134static const struct hid_device_id logi_dj_receivers[] = {
889 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1135 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
890 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)}, 1136 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
@@ -906,51 +1152,8 @@ static struct hid_driver logi_djreceiver_driver = {
906#endif 1152#endif
907}; 1153};
908 1154
1155module_hid_driver(logi_djreceiver_driver);
909 1156
910static const struct hid_device_id logi_dj_devices[] = {
911 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
912 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
913 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
914 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
915 {}
916};
917
918static struct hid_driver logi_djdevice_driver = {
919 .name = "logitech-djdevice",
920 .id_table = logi_dj_devices,
921 .probe = logi_djdevice_probe,
922};
923
924
925static int __init logi_dj_init(void)
926{
927 int retval;
928
929 dbg_hid("Logitech-DJ:%s\n", __func__);
930
931 retval = hid_register_driver(&logi_djreceiver_driver);
932 if (retval)
933 return retval;
934
935 retval = hid_register_driver(&logi_djdevice_driver);
936 if (retval)
937 hid_unregister_driver(&logi_djreceiver_driver);
938
939 return retval;
940
941}
942
943static void __exit logi_dj_exit(void)
944{
945 dbg_hid("Logitech-DJ:%s\n", __func__);
946
947 hid_unregister_driver(&logi_djdevice_driver);
948 hid_unregister_driver(&logi_djreceiver_driver);
949
950}
951
952module_init(logi_dj_init);
953module_exit(logi_dj_exit);
954MODULE_LICENSE("GPL"); 1157MODULE_LICENSE("GPL");
955MODULE_AUTHOR("Logitech"); 1158MODULE_AUTHOR("Logitech");
956MODULE_AUTHOR("Nestor Lopez Casado"); 1159MODULE_AUTHOR("Nestor Lopez Casado");