1
2
3
4
5
6
7
8
9
10#include <linux/device.h>
11#include <linux/hid.h>
12#include <linux/module.h>
13#include <linux/kfifo.h>
14#include <linux/delay.h>
15#include <linux/usb.h>
16#include <asm/unaligned.h>
17#include "hid-ids.h"
18
19#define DJ_MAX_PAIRED_DEVICES 7
20#define DJ_MAX_NUMBER_NOTIFS 8
21#define DJ_RECEIVER_INDEX 0
22#define DJ_DEVICE_INDEX_MIN 1
23#define DJ_DEVICE_INDEX_MAX 7
24
25#define DJREPORT_SHORT_LENGTH 15
26#define DJREPORT_LONG_LENGTH 32
27
28#define REPORT_ID_DJ_SHORT 0x20
29#define REPORT_ID_DJ_LONG 0x21
30
31#define REPORT_ID_HIDPP_SHORT 0x10
32#define REPORT_ID_HIDPP_LONG 0x11
33#define REPORT_ID_HIDPP_VERY_LONG 0x12
34
35#define HIDPP_REPORT_SHORT_LENGTH 7
36#define HIDPP_REPORT_LONG_LENGTH 20
37
38#define HIDPP_RECEIVER_INDEX 0xff
39
40#define REPORT_TYPE_RFREPORT_FIRST 0x01
41#define REPORT_TYPE_RFREPORT_LAST 0x1F
42
43
44#define REPORT_TYPE_CMD_SWITCH 0x80
45#define CMD_SWITCH_PARAM_DEVBITFIELD 0x00
46#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01
47#define TIMEOUT_NO_KEEPALIVE 0x00
48
49
50#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81
51
52
53#define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41
54#define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01
55#define SPFUNCTION_DEVICE_LIST_EMPTY 0x02
56#define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00
57#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01
58#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02
59#define DEVICE_PAIRED_RF_REPORT_TYPE 0x03
60
61
62#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40
63
64
65#define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42
66#define CONNECTION_STATUS_PARAM_STATUS 0x00
67#define STATUS_LINKLOSS 0x01
68
69
70#define REPORT_TYPE_NOTIF_ERROR 0x7F
71#define NOTIF_ERROR_PARAM_ETYPE 0x00
72#define ETYPE_KEEPALIVE_TIMEOUT 0x01
73
74
75#define REPORT_TYPE_KEYBOARD 0x01
76#define REPORT_TYPE_MOUSE 0x02
77#define REPORT_TYPE_CONSUMER_CONTROL 0x03
78#define REPORT_TYPE_SYSTEM_CONTROL 0x04
79#define REPORT_TYPE_MEDIA_CENTER 0x08
80#define REPORT_TYPE_LEDS 0x0E
81
82
83#define STD_KEYBOARD BIT(1)
84#define STD_MOUSE BIT(2)
85#define MULTIMEDIA BIT(3)
86#define POWER_KEYS BIT(4)
87#define KBD_MOUSE BIT(5)
88#define MEDIA_CENTER BIT(8)
89#define KBD_LEDS BIT(14)
90
91#define HIDPP BIT_ULL(63)
92
93
94#define REPORT_TYPE_NOTIF_DEVICE_CONNECTED 0x41
95#define HIDPP_PARAM_PROTO_TYPE 0x00
96#define HIDPP_PARAM_DEVICE_INFO 0x01
97#define HIDPP_PARAM_EQUAD_LSB 0x02
98#define HIDPP_PARAM_EQUAD_MSB 0x03
99#define HIDPP_PARAM_27MHZ_DEVID 0x03
100#define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0)
101#define HIDPP_LINK_STATUS_MASK BIT(6)
102#define HIDPP_MANUFACTURER_MASK BIT(7)
103#define HIDPP_27MHZ_SECURE_MASK BIT(7)
104
105#define HIDPP_DEVICE_TYPE_KEYBOARD 1
106#define HIDPP_DEVICE_TYPE_MOUSE 2
107
108#define HIDPP_SET_REGISTER 0x80
109#define HIDPP_GET_LONG_REGISTER 0x83
110#define HIDPP_REG_CONNECTION_STATE 0x02
111#define HIDPP_REG_PAIRING_INFORMATION 0xB5
112#define HIDPP_PAIRING_INFORMATION 0x20
113#define HIDPP_FAKE_DEVICE_ARRIVAL 0x02
114
115enum recvr_type {
116 recvr_type_dj,
117 recvr_type_hidpp,
118 recvr_type_gaming_hidpp,
119 recvr_type_mouse_only,
120 recvr_type_27mhz,
121 recvr_type_bluetooth,
122 recvr_type_dinovo,
123};
124
125struct dj_report {
126 u8 report_id;
127 u8 device_index;
128 u8 report_type;
129 u8 report_params[DJREPORT_SHORT_LENGTH - 3];
130};
131
132struct hidpp_event {
133 u8 report_id;
134 u8 device_index;
135 u8 sub_id;
136 u8 params[HIDPP_REPORT_LONG_LENGTH - 3U];
137} __packed;
138
139struct dj_receiver_dev {
140 struct hid_device *mouse;
141 struct hid_device *keyboard;
142 struct hid_device *hidpp;
143 struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +
144 DJ_DEVICE_INDEX_MIN];
145 struct list_head list;
146 struct kref kref;
147 struct work_struct work;
148 struct kfifo notif_fifo;
149 unsigned long last_query;
150 bool ready;
151 enum recvr_type type;
152 unsigned int unnumbered_application;
153 spinlock_t lock;
154};
155
156struct dj_device {
157 struct hid_device *hdev;
158 struct dj_receiver_dev *dj_receiver_dev;
159 u64 reports_supported;
160 u8 device_index;
161};
162
163#define WORKITEM_TYPE_EMPTY 0
164#define WORKITEM_TYPE_PAIRED 1
165#define WORKITEM_TYPE_UNPAIRED 2
166#define WORKITEM_TYPE_UNKNOWN 255
167
168struct dj_workitem {
169 u8 type;
170 u8 device_index;
171 u8 device_type;
172 u8 quad_id_msb;
173 u8 quad_id_lsb;
174 u64 reports_supported;
175};
176
177
178static const char kbd_descriptor[] = {
179 0x05, 0x01,
180 0x09, 0x06,
181 0xA1, 0x01,
182 0x85, 0x01,
183 0x95, 0x08,
184 0x75, 0x01,
185 0x15, 0x00,
186 0x25, 0x01,
187 0x05, 0x07,
188 0x19, 0xE0,
189 0x29, 0xE7,
190 0x81, 0x02,
191 0x95, 0x06,
192 0x75, 0x08,
193 0x15, 0x00,
194 0x26, 0xFF, 0x00,
195 0x05, 0x07,
196 0x19, 0x00,
197 0x2A, 0xFF, 0x00,
198 0x81, 0x00,
199 0x85, 0x0e,
200 0x05, 0x08,
201 0x95, 0x05,
202 0x75, 0x01,
203 0x15, 0x00,
204 0x25, 0x01,
205 0x19, 0x01,
206 0x29, 0x05,
207 0x91, 0x02,
208 0x95, 0x01,
209 0x75, 0x03,
210 0x91, 0x01,
211 0xC0
212};
213
214
215static const char mse_descriptor[] = {
216 0x05, 0x01,
217 0x09, 0x02,
218 0xA1, 0x01,
219 0x85, 0x02,
220 0x09, 0x01,
221 0xA1, 0x00,
222 0x05, 0x09,
223 0x19, 0x01,
224 0x29, 0x10,
225 0x15, 0x00,
226 0x25, 0x01,
227 0x95, 0x10,
228 0x75, 0x01,
229 0x81, 0x02,
230 0x05, 0x01,
231 0x16, 0x01, 0xF8,
232 0x26, 0xFF, 0x07,
233 0x75, 0x0C,
234 0x95, 0x02,
235 0x09, 0x30,
236 0x09, 0x31,
237 0x81, 0x06,
238 0x15, 0x81,
239 0x25, 0x7F,
240 0x75, 0x08,
241 0x95, 0x01,
242 0x09, 0x38,
243 0x81, 0x06,
244 0x05, 0x0C,
245 0x0A, 0x38, 0x02,
246 0x95, 0x01,
247 0x81, 0x06,
248 0xC0,
249 0xC0,
250};
251
252
253static const char mse_27mhz_descriptor[] = {
254 0x05, 0x01,
255 0x09, 0x02,
256 0xA1, 0x01,
257 0x85, 0x02,
258 0x09, 0x01,
259 0xA1, 0x00,
260 0x05, 0x09,
261 0x19, 0x01,
262 0x29, 0x08,
263 0x15, 0x00,
264 0x25, 0x01,
265 0x95, 0x08,
266 0x75, 0x01,
267 0x81, 0x02,
268 0x05, 0x01,
269 0x16, 0x01, 0xF8,
270 0x26, 0xFF, 0x07,
271 0x75, 0x0C,
272 0x95, 0x02,
273 0x09, 0x30,
274 0x09, 0x31,
275 0x81, 0x06,
276 0x15, 0x81,
277 0x25, 0x7F,
278 0x75, 0x08,
279 0x95, 0x01,
280 0x09, 0x38,
281 0x81, 0x06,
282 0x05, 0x0C,
283 0x0A, 0x38, 0x02,
284 0x95, 0x01,
285 0x81, 0x06,
286 0xC0,
287 0xC0,
288};
289
290
291static const char mse_bluetooth_descriptor[] = {
292 0x05, 0x01,
293 0x09, 0x02,
294 0xA1, 0x01,
295 0x85, 0x02,
296 0x09, 0x01,
297 0xA1, 0x00,
298 0x05, 0x09,
299 0x19, 0x01,
300 0x29, 0x08,
301 0x15, 0x00,
302 0x25, 0x01,
303 0x95, 0x08,
304 0x75, 0x01,
305 0x81, 0x02,
306 0x05, 0x01,
307 0x16, 0x01, 0xF8,
308 0x26, 0xFF, 0x07,
309 0x75, 0x0C,
310 0x95, 0x02,
311 0x09, 0x30,
312 0x09, 0x31,
313 0x81, 0x06,
314 0x15, 0x81,
315 0x25, 0x7F,
316 0x75, 0x08,
317 0x95, 0x01,
318 0x09, 0x38,
319 0x81, 0x06,
320 0x05, 0x0C,
321 0x0A, 0x38, 0x02,
322 0x15, 0xF9,
323 0x25, 0x07,
324 0x75, 0x04,
325 0x95, 0x01,
326 0x81, 0x06,
327 0x05, 0x09,
328 0x19, 0x09,
329 0x29, 0x0C,
330 0x15, 0x00,
331 0x25, 0x01,
332 0x75, 0x01,
333 0x95, 0x04,
334 0x81, 0x02,
335 0xC0,
336 0xC0,
337};
338
339
340static const char mse5_bluetooth_descriptor[] = {
341 0x05, 0x01,
342 0x09, 0x02,
343 0xa1, 0x01,
344 0x85, 0x05,
345 0x09, 0x01,
346 0xa1, 0x00,
347 0x05, 0x09,
348 0x19, 0x01,
349 0x29, 0x08,
350 0x15, 0x00,
351 0x25, 0x01,
352 0x95, 0x08,
353 0x75, 0x01,
354 0x81, 0x02,
355 0x05, 0x01,
356 0x16, 0x01, 0xf8,
357 0x26, 0xff, 0x07,
358 0x75, 0x0c,
359 0x95, 0x02,
360 0x09, 0x30,
361 0x09, 0x31,
362 0x81, 0x06,
363 0x15, 0x81,
364 0x25, 0x7f,
365 0x75, 0x08,
366 0x95, 0x01,
367 0x09, 0x38,
368 0x81, 0x06,
369 0x05, 0x0c,
370 0x0a, 0x38, 0x02,
371 0x15, 0x81,
372 0x25, 0x7f,
373 0x75, 0x08,
374 0x95, 0x01,
375 0x81, 0x06,
376 0xc0,
377 0xc0,
378};
379
380
381static const char mse_high_res_descriptor[] = {
382 0x05, 0x01,
383 0x09, 0x02,
384 0xA1, 0x01,
385 0x85, 0x02,
386 0x09, 0x01,
387 0xA1, 0x00,
388 0x05, 0x09,
389 0x19, 0x01,
390 0x29, 0x10,
391 0x15, 0x00,
392 0x25, 0x01,
393 0x95, 0x10,
394 0x75, 0x01,
395 0x81, 0x02,
396 0x05, 0x01,
397 0x16, 0x01, 0x80,
398 0x26, 0xFF, 0x7F,
399 0x75, 0x10,
400 0x95, 0x02,
401 0x09, 0x30,
402 0x09, 0x31,
403 0x81, 0x06,
404 0x15, 0x81,
405 0x25, 0x7F,
406 0x75, 0x08,
407 0x95, 0x01,
408 0x09, 0x38,
409 0x81, 0x06,
410 0x05, 0x0C,
411 0x0A, 0x38, 0x02,
412 0x95, 0x01,
413 0x81, 0x06,
414 0xC0,
415 0xC0,
416};
417
418
419static const char consumer_descriptor[] = {
420 0x05, 0x0C,
421 0x09, 0x01,
422 0xA1, 0x01,
423 0x85, 0x03,
424 0x75, 0x10,
425 0x95, 0x02,
426 0x15, 0x01,
427 0x26, 0xFF, 0x02,
428 0x19, 0x01,
429 0x2A, 0xFF, 0x02,
430 0x81, 0x00,
431 0xC0,
432};
433
434
435static const char syscontrol_descriptor[] = {
436 0x05, 0x01,
437 0x09, 0x80,
438 0xA1, 0x01,
439 0x85, 0x04,
440 0x75, 0x02,
441 0x95, 0x01,
442 0x15, 0x01,
443 0x25, 0x03,
444 0x09, 0x82,
445 0x09, 0x81,
446 0x09, 0x83,
447 0x81, 0x60,
448 0x75, 0x06,
449 0x81, 0x03,
450 0xC0,
451};
452
453
454static const char media_descriptor[] = {
455 0x06, 0xbc, 0xff,
456 0x09, 0x88,
457 0xa1, 0x01,
458 0x85, 0x08,
459 0x19, 0x01,
460 0x29, 0xff,
461 0x15, 0x01,
462 0x26, 0xff, 0x00,
463 0x75, 0x08,
464 0x95, 0x01,
465 0x81, 0x00,
466 0xc0,
467};
468
469
470static const char hidpp_descriptor[] = {
471 0x06, 0x00, 0xff,
472 0x09, 0x01,
473 0xa1, 0x01,
474 0x85, 0x10,
475 0x75, 0x08,
476 0x95, 0x06,
477 0x15, 0x00,
478 0x26, 0xff, 0x00,
479 0x09, 0x01,
480 0x81, 0x00,
481 0x09, 0x01,
482 0x91, 0x00,
483 0xc0,
484 0x06, 0x00, 0xff,
485 0x09, 0x02,
486 0xa1, 0x01,
487 0x85, 0x11,
488 0x75, 0x08,
489 0x95, 0x13,
490 0x15, 0x00,
491 0x26, 0xff, 0x00,
492 0x09, 0x02,
493 0x81, 0x00,
494 0x09, 0x02,
495 0x91, 0x00,
496 0xc0,
497 0x06, 0x00, 0xff,
498 0x09, 0x04,
499 0xa1, 0x01,
500 0x85, 0x20,
501 0x75, 0x08,
502 0x95, 0x0e,
503 0x15, 0x00,
504 0x26, 0xff, 0x00,
505 0x09, 0x41,
506 0x81, 0x00,
507 0x09, 0x41,
508 0x91, 0x00,
509 0x85, 0x21,
510 0x95, 0x1f,
511 0x15, 0x00,
512 0x26, 0xff, 0x00,
513 0x09, 0x42,
514 0x81, 0x00,
515 0x09, 0x42,
516 0x91, 0x00,
517 0xc0,
518};
519
520
521#define MAX_REPORT_SIZE 8
522
523
524#define MAX_RDESC_SIZE \
525 (sizeof(kbd_descriptor) + \
526 sizeof(mse_bluetooth_descriptor) + \
527 sizeof(mse5_bluetooth_descriptor) + \
528 sizeof(consumer_descriptor) + \
529 sizeof(syscontrol_descriptor) + \
530 sizeof(media_descriptor) + \
531 sizeof(hidpp_descriptor))
532
533
534
535
536
537
538
539
540
541
542
543
544
545#define NUMBER_OF_HID_REPORTS 32
546static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
547 [1] = 8,
548 [2] = 8,
549 [3] = 5,
550 [4] = 2,
551 [8] = 2,
552};
553
554
555#define LOGITECH_DJ_INTERFACE_NUMBER 0x02
556
557static struct hid_ll_driver logi_dj_ll_driver;
558
559static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
560static void delayedwork_callback(struct work_struct *work);
561
562static LIST_HEAD(dj_hdev_list);
563static DEFINE_MUTEX(dj_hdev_list_lock);
564
565static bool recvr_type_is_bluetooth(enum recvr_type type)
566{
567 return type == recvr_type_bluetooth || type == recvr_type_dinovo;
568}
569
570
571
572
573
574
575
576
577static struct dj_receiver_dev *dj_find_receiver_dev(struct hid_device *hdev,
578 enum recvr_type type)
579{
580 struct dj_receiver_dev *djrcv_dev;
581 char sep;
582
583
584
585
586
587 sep = recvr_type_is_bluetooth(type) ? '.' : '/';
588
589
590 list_for_each_entry(djrcv_dev, &dj_hdev_list, list) {
591 if (djrcv_dev->mouse &&
592 hid_compare_device_paths(hdev, djrcv_dev->mouse, sep)) {
593 kref_get(&djrcv_dev->kref);
594 return djrcv_dev;
595 }
596 if (djrcv_dev->keyboard &&
597 hid_compare_device_paths(hdev, djrcv_dev->keyboard, sep)) {
598 kref_get(&djrcv_dev->kref);
599 return djrcv_dev;
600 }
601 if (djrcv_dev->hidpp &&
602 hid_compare_device_paths(hdev, djrcv_dev->hidpp, sep)) {
603 kref_get(&djrcv_dev->kref);
604 return djrcv_dev;
605 }
606 }
607
608 return NULL;
609}
610
611static void dj_release_receiver_dev(struct kref *kref)
612{
613 struct dj_receiver_dev *djrcv_dev = container_of(kref, struct dj_receiver_dev, kref);
614
615 list_del(&djrcv_dev->list);
616 kfifo_free(&djrcv_dev->notif_fifo);
617 kfree(djrcv_dev);
618}
619
620static void dj_put_receiver_dev(struct hid_device *hdev)
621{
622 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
623
624 mutex_lock(&dj_hdev_list_lock);
625
626 if (djrcv_dev->mouse == hdev)
627 djrcv_dev->mouse = NULL;
628 if (djrcv_dev->keyboard == hdev)
629 djrcv_dev->keyboard = NULL;
630 if (djrcv_dev->hidpp == hdev)
631 djrcv_dev->hidpp = NULL;
632
633 kref_put(&djrcv_dev->kref, dj_release_receiver_dev);
634
635 mutex_unlock(&dj_hdev_list_lock);
636}
637
638static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev,
639 enum recvr_type type,
640 unsigned int application,
641 bool is_hidpp)
642{
643 struct dj_receiver_dev *djrcv_dev;
644
645 mutex_lock(&dj_hdev_list_lock);
646
647 djrcv_dev = dj_find_receiver_dev(hdev, type);
648 if (!djrcv_dev) {
649 djrcv_dev = kzalloc(sizeof(*djrcv_dev), GFP_KERNEL);
650 if (!djrcv_dev)
651 goto out;
652
653 INIT_WORK(&djrcv_dev->work, delayedwork_callback);
654 spin_lock_init(&djrcv_dev->lock);
655 if (kfifo_alloc(&djrcv_dev->notif_fifo,
656 DJ_MAX_NUMBER_NOTIFS * sizeof(struct dj_workitem),
657 GFP_KERNEL)) {
658 kfree(djrcv_dev);
659 djrcv_dev = NULL;
660 goto out;
661 }
662 kref_init(&djrcv_dev->kref);
663 list_add_tail(&djrcv_dev->list, &dj_hdev_list);
664 djrcv_dev->last_query = jiffies;
665 djrcv_dev->type = type;
666 }
667
668 if (application == HID_GD_KEYBOARD)
669 djrcv_dev->keyboard = hdev;
670 if (application == HID_GD_MOUSE)
671 djrcv_dev->mouse = hdev;
672 if (is_hidpp)
673 djrcv_dev->hidpp = hdev;
674
675 hid_set_drvdata(hdev, djrcv_dev);
676out:
677 mutex_unlock(&dj_hdev_list_lock);
678 return djrcv_dev;
679}
680
681static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
682 struct dj_workitem *workitem)
683{
684
685 struct dj_device *dj_dev;
686 unsigned long flags;
687
688 spin_lock_irqsave(&djrcv_dev->lock, flags);
689 dj_dev = djrcv_dev->paired_dj_devices[workitem->device_index];
690 djrcv_dev->paired_dj_devices[workitem->device_index] = NULL;
691 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
692
693 if (dj_dev != NULL) {
694 hid_destroy_device(dj_dev->hdev);
695 kfree(dj_dev);
696 } else {
697 hid_err(djrcv_dev->hidpp, "%s: can't destroy a NULL device\n",
698 __func__);
699 }
700}
701
702static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
703 struct dj_workitem *workitem)
704{
705
706 struct hid_device *djrcv_hdev = djrcv_dev->hidpp;
707 struct hid_device *dj_hiddev;
708 struct dj_device *dj_dev;
709 u8 device_index = workitem->device_index;
710 unsigned long flags;
711
712
713
714
715 unsigned char tmpstr[3];
716
717
718 if (djrcv_dev->paired_dj_devices[device_index]) {
719
720 dbg_hid("%s: device is already known\n", __func__);
721 return;
722 }
723
724 dj_hiddev = hid_allocate_device();
725 if (IS_ERR(dj_hiddev)) {
726 hid_err(djrcv_hdev, "%s: hid_allocate_dev failed\n", __func__);
727 return;
728 }
729
730 dj_hiddev->ll_driver = &logi_dj_ll_driver;
731
732 dj_hiddev->dev.parent = &djrcv_hdev->dev;
733 dj_hiddev->bus = BUS_USB;
734 dj_hiddev->vendor = djrcv_hdev->vendor;
735 dj_hiddev->product = (workitem->quad_id_msb << 8) |
736 workitem->quad_id_lsb;
737 if (workitem->device_type) {
738 const char *type_str = "Device";
739
740 switch (workitem->device_type) {
741 case 0x01: type_str = "Keyboard"; break;
742 case 0x02: type_str = "Mouse"; break;
743 case 0x03: type_str = "Numpad"; break;
744 case 0x04: type_str = "Presenter"; break;
745 case 0x07: type_str = "Remote Control"; break;
746 case 0x08: type_str = "Trackball"; break;
747 case 0x09: type_str = "Touchpad"; break;
748 }
749 snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
750 "Logitech Wireless %s PID:%04x",
751 type_str, dj_hiddev->product);
752 } else {
753 snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
754 "Logitech Wireless Device PID:%04x",
755 dj_hiddev->product);
756 }
757
758 if (djrcv_dev->type == recvr_type_27mhz)
759 dj_hiddev->group = HID_GROUP_LOGITECH_27MHZ_DEVICE;
760 else
761 dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE;
762
763 memcpy(dj_hiddev->phys, djrcv_hdev->phys, sizeof(djrcv_hdev->phys));
764 snprintf(tmpstr, sizeof(tmpstr), ":%d", device_index);
765 strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));
766
767 dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);
768
769 if (!dj_dev) {
770 hid_err(djrcv_hdev, "%s: failed allocating dj_dev\n", __func__);
771 goto dj_device_allocate_fail;
772 }
773
774 dj_dev->reports_supported = workitem->reports_supported;
775 dj_dev->hdev = dj_hiddev;
776 dj_dev->dj_receiver_dev = djrcv_dev;
777 dj_dev->device_index = device_index;
778 dj_hiddev->driver_data = dj_dev;
779
780 spin_lock_irqsave(&djrcv_dev->lock, flags);
781 djrcv_dev->paired_dj_devices[device_index] = dj_dev;
782 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
783
784 if (hid_add_device(dj_hiddev)) {
785 hid_err(djrcv_hdev, "%s: failed adding dj_device\n", __func__);
786 goto hid_add_device_fail;
787 }
788
789 return;
790
791hid_add_device_fail:
792 spin_lock_irqsave(&djrcv_dev->lock, flags);
793 djrcv_dev->paired_dj_devices[device_index] = NULL;
794 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
795 kfree(dj_dev);
796dj_device_allocate_fail:
797 hid_destroy_device(dj_hiddev);
798}
799
800static void delayedwork_callback(struct work_struct *work)
801{
802 struct dj_receiver_dev *djrcv_dev =
803 container_of(work, struct dj_receiver_dev, work);
804
805 struct dj_workitem workitem;
806 unsigned long flags;
807 int count;
808 int retval;
809
810 dbg_hid("%s\n", __func__);
811
812 spin_lock_irqsave(&djrcv_dev->lock, flags);
813
814
815
816
817
818 if (!djrcv_dev->ready) {
819 pr_warn("%s: delayedwork queued before hidpp interface was enumerated\n",
820 __func__);
821 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
822 return;
823 }
824
825 count = kfifo_out(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
826
827 if (count != sizeof(workitem)) {
828 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
829 return;
830 }
831
832 if (!kfifo_is_empty(&djrcv_dev->notif_fifo))
833 schedule_work(&djrcv_dev->work);
834
835 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
836
837 switch (workitem.type) {
838 case WORKITEM_TYPE_PAIRED:
839 logi_dj_recv_add_djhid_device(djrcv_dev, &workitem);
840 break;
841 case WORKITEM_TYPE_UNPAIRED:
842 logi_dj_recv_destroy_djhid_device(djrcv_dev, &workitem);
843 break;
844 case WORKITEM_TYPE_UNKNOWN:
845 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
846 if (retval) {
847 hid_err(djrcv_dev->hidpp, "%s: logi_dj_recv_query_paired_devices error: %d\n",
848 __func__, retval);
849 }
850 break;
851 case WORKITEM_TYPE_EMPTY:
852 dbg_hid("%s: device list is empty\n", __func__);
853 break;
854 }
855}
856
857
858
859
860
861
862
863
864
865
866
867
868
869static void logi_dj_recv_queue_unknown_work(struct dj_receiver_dev *djrcv_dev)
870{
871 struct dj_workitem workitem = { .type = WORKITEM_TYPE_UNKNOWN };
872
873
874 if (time_before(jiffies, djrcv_dev->last_query + HZ / 2))
875 return;
876
877 kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
878 schedule_work(&djrcv_dev->work);
879}
880
881static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
882 struct dj_report *dj_report)
883{
884
885 struct dj_workitem workitem = {
886 .device_index = dj_report->device_index,
887 };
888
889 switch (dj_report->report_type) {
890 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
891 workitem.type = WORKITEM_TYPE_PAIRED;
892 if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
893 SPFUNCTION_DEVICE_LIST_EMPTY) {
894 workitem.type = WORKITEM_TYPE_EMPTY;
895 break;
896 }
897 fallthrough;
898 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
899 workitem.quad_id_msb =
900 dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB];
901 workitem.quad_id_lsb =
902 dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB];
903 workitem.reports_supported = get_unaligned_le32(
904 dj_report->report_params +
905 DEVICE_PAIRED_RF_REPORT_TYPE);
906 workitem.reports_supported |= HIDPP;
907 if (dj_report->report_type == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED)
908 workitem.type = WORKITEM_TYPE_UNPAIRED;
909 break;
910 default:
911 logi_dj_recv_queue_unknown_work(djrcv_dev);
912 return;
913 }
914
915 kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
916 schedule_work(&djrcv_dev->work);
917}
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934static const u16 kbd_builtin_touchpad_ids[] = {
935 0xb309,
936 0xb30c,
937};
938
939static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
940 struct hidpp_event *hidpp_report,
941 struct dj_workitem *workitem)
942{
943 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
944 int i, id;
945
946 workitem->type = WORKITEM_TYPE_PAIRED;
947 workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
948 HIDPP_DEVICE_TYPE_MASK;
949 workitem->quad_id_msb = hidpp_report->params[HIDPP_PARAM_EQUAD_MSB];
950 workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_EQUAD_LSB];
951 switch (workitem->device_type) {
952 case REPORT_TYPE_KEYBOARD:
953 workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
954 POWER_KEYS | MEDIA_CENTER |
955 HIDPP;
956 id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb;
957 for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) {
958 if (id == kbd_builtin_touchpad_ids[i]) {
959 if (djrcv_dev->type == recvr_type_dinovo)
960 workitem->reports_supported |= KBD_MOUSE;
961 else
962 workitem->reports_supported |= STD_MOUSE;
963 break;
964 }
965 }
966 break;
967 case REPORT_TYPE_MOUSE:
968 workitem->reports_supported |= STD_MOUSE | HIDPP;
969 if (djrcv_dev->type == recvr_type_mouse_only)
970 workitem->reports_supported |= MULTIMEDIA;
971 break;
972 }
973}
974
975static void logi_hidpp_dev_conn_notif_27mhz(struct hid_device *hdev,
976 struct hidpp_event *hidpp_report,
977 struct dj_workitem *workitem)
978{
979 workitem->type = WORKITEM_TYPE_PAIRED;
980 workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID];
981 switch (hidpp_report->device_index) {
982 case 1:
983 case 2:
984 workitem->device_type = HIDPP_DEVICE_TYPE_MOUSE;
985 workitem->reports_supported |= STD_MOUSE | HIDPP;
986 break;
987 case 3:
988 if (hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & HIDPP_27MHZ_SECURE_MASK) {
989 hid_info(hdev, "Keyboard connection is encrypted\n");
990 } else {
991 hid_warn(hdev, "Keyboard events are send over the air in plain-text / unencrypted\n");
992 hid_warn(hdev, "See: https://gitlab.freedesktop.org/jwrdegoede/logitech-27mhz-keyboard-encryption-setup/\n");
993 }
994 fallthrough;
995 case 4:
996 workitem->device_type = HIDPP_DEVICE_TYPE_KEYBOARD;
997 workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
998 POWER_KEYS | HIDPP;
999 break;
1000 default:
1001 hid_warn(hdev, "%s: unexpected device-index %d", __func__,
1002 hidpp_report->device_index);
1003 }
1004}
1005
1006static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
1007 struct hidpp_event *hidpp_report)
1008{
1009
1010 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1011 const char *device_type = "UNKNOWN";
1012 struct dj_workitem workitem = {
1013 .type = WORKITEM_TYPE_EMPTY,
1014 .device_index = hidpp_report->device_index,
1015 };
1016
1017 switch (hidpp_report->params[HIDPP_PARAM_PROTO_TYPE]) {
1018 case 0x01:
1019 device_type = "Bluetooth";
1020
1021 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1022 if (!(hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
1023 HIDPP_MANUFACTURER_MASK)) {
1024 hid_info(hdev, "Non Logitech device connected on slot %d\n",
1025 hidpp_report->device_index);
1026 workitem.reports_supported &= ~HIDPP;
1027 }
1028 break;
1029 case 0x02:
1030 device_type = "27 Mhz";
1031 logi_hidpp_dev_conn_notif_27mhz(hdev, hidpp_report, &workitem);
1032 break;
1033 case 0x03:
1034 device_type = "QUAD or eQUAD";
1035 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1036 break;
1037 case 0x04:
1038 device_type = "eQUAD step 4 DJ";
1039 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1040 break;
1041 case 0x05:
1042 device_type = "DFU Lite";
1043 break;
1044 case 0x06:
1045 device_type = "eQUAD step 4 Lite";
1046 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1047 break;
1048 case 0x07:
1049 device_type = "eQUAD step 4 Gaming";
1050 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1051 workitem.reports_supported |= STD_KEYBOARD;
1052 break;
1053 case 0x08:
1054 device_type = "eQUAD step 4 for gamepads";
1055 break;
1056 case 0x0a:
1057 device_type = "eQUAD nano Lite";
1058 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1059 break;
1060 case 0x0c:
1061 device_type = "eQUAD Lightspeed 1";
1062 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1063 workitem.reports_supported |= STD_KEYBOARD;
1064 break;
1065 case 0x0d:
1066 device_type = "eQUAD Lightspeed 1.1";
1067 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1068 workitem.reports_supported |= STD_KEYBOARD;
1069 break;
1070 case 0x0f:
1071 case 0x11:
1072 device_type = "eQUAD Lightspeed 1.2";
1073 logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
1074 workitem.reports_supported |= STD_KEYBOARD;
1075 break;
1076 }
1077
1078
1079 if (hidpp_report->device_index == 7) {
1080 workitem.reports_supported |= HIDPP;
1081 }
1082
1083 if (workitem.type == WORKITEM_TYPE_EMPTY) {
1084 hid_warn(hdev,
1085 "unusable device of type %s (0x%02x) connected on slot %d",
1086 device_type,
1087 hidpp_report->params[HIDPP_PARAM_PROTO_TYPE],
1088 hidpp_report->device_index);
1089 return;
1090 }
1091
1092 hid_info(hdev, "device of type %s (0x%02x) connected on slot %d",
1093 device_type, hidpp_report->params[HIDPP_PARAM_PROTO_TYPE],
1094 hidpp_report->device_index);
1095
1096 kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
1097 schedule_work(&djrcv_dev->work);
1098}
1099
1100static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
1101 struct dj_report *dj_report)
1102{
1103
1104 unsigned int i;
1105 u8 reportbuffer[MAX_REPORT_SIZE];
1106 struct dj_device *djdev;
1107
1108 djdev = djrcv_dev->paired_dj_devices[dj_report->device_index];
1109
1110 memset(reportbuffer, 0, sizeof(reportbuffer));
1111
1112 for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) {
1113 if (djdev->reports_supported & (1 << i)) {
1114 reportbuffer[0] = i;
1115 if (hid_input_report(djdev->hdev,
1116 HID_INPUT_REPORT,
1117 reportbuffer,
1118 hid_reportid_size_map[i], 1)) {
1119 dbg_hid("hid_input_report error sending null "
1120 "report\n");
1121 }
1122 }
1123 }
1124}
1125
1126static void logi_dj_recv_forward_dj(struct dj_receiver_dev *djrcv_dev,
1127 struct dj_report *dj_report)
1128{
1129
1130 struct dj_device *dj_device;
1131
1132 dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index];
1133
1134 if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) ||
1135 (hid_reportid_size_map[dj_report->report_type] == 0)) {
1136 dbg_hid("invalid report type:%x\n", dj_report->report_type);
1137 return;
1138 }
1139
1140 if (hid_input_report(dj_device->hdev,
1141 HID_INPUT_REPORT, &dj_report->report_type,
1142 hid_reportid_size_map[dj_report->report_type], 1)) {
1143 dbg_hid("hid_input_report error\n");
1144 }
1145}
1146
1147static void logi_dj_recv_forward_report(struct dj_device *dj_dev, u8 *data,
1148 int size)
1149{
1150
1151 if (hid_input_report(dj_dev->hdev, HID_INPUT_REPORT, data, size, 1))
1152 dbg_hid("hid_input_report error\n");
1153}
1154
1155static void logi_dj_recv_forward_input_report(struct hid_device *hdev,
1156 u8 *data, int size)
1157{
1158 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1159 struct dj_device *dj_dev;
1160 unsigned long flags;
1161 u8 report = data[0];
1162 int i;
1163
1164 if (report > REPORT_TYPE_RFREPORT_LAST) {
1165 hid_err(hdev, "Unexpected input report number %d\n", report);
1166 return;
1167 }
1168
1169 spin_lock_irqsave(&djrcv_dev->lock, flags);
1170 for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
1171 dj_dev = djrcv_dev->paired_dj_devices[i];
1172 if (dj_dev && (dj_dev->reports_supported & BIT(report))) {
1173 logi_dj_recv_forward_report(dj_dev, data, size);
1174 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
1175 return;
1176 }
1177 }
1178
1179 logi_dj_recv_queue_unknown_work(djrcv_dev);
1180 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
1181
1182 dbg_hid("No dj-devs handling input report number %d\n", report);
1183}
1184
1185static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
1186 struct dj_report *dj_report)
1187{
1188 struct hid_device *hdev = djrcv_dev->hidpp;
1189 struct hid_report *report;
1190 struct hid_report_enum *output_report_enum;
1191 u8 *data = (u8 *)(&dj_report->device_index);
1192 unsigned int i;
1193
1194 output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
1195 report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
1196
1197 if (!report) {
1198 hid_err(hdev, "%s: unable to find dj report\n", __func__);
1199 return -ENODEV;
1200 }
1201
1202 for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++)
1203 report->field[0]->value[i] = data[i];
1204
1205 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
1206
1207 return 0;
1208}
1209
1210static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev)
1211{
1212 static const u8 template[] = {
1213 REPORT_ID_HIDPP_SHORT,
1214 HIDPP_RECEIVER_INDEX,
1215 HIDPP_SET_REGISTER,
1216 HIDPP_REG_CONNECTION_STATE,
1217 HIDPP_FAKE_DEVICE_ARRIVAL,
1218 0x00, 0x00
1219 };
1220 u8 *hidpp_report;
1221 int retval;
1222
1223 hidpp_report = kmemdup(template, sizeof(template), GFP_KERNEL);
1224 if (!hidpp_report)
1225 return -ENOMEM;
1226
1227 retval = hid_hw_raw_request(djrcv_dev->hidpp,
1228 REPORT_ID_HIDPP_SHORT,
1229 hidpp_report, sizeof(template),
1230 HID_OUTPUT_REPORT,
1231 HID_REQ_SET_REPORT);
1232
1233 kfree(hidpp_report);
1234 return (retval < 0) ? retval : 0;
1235}
1236
1237static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
1238{
1239 struct dj_report *dj_report;
1240 int retval;
1241
1242 djrcv_dev->last_query = jiffies;
1243
1244 if (djrcv_dev->type != recvr_type_dj)
1245 return logi_dj_recv_query_hidpp_devices(djrcv_dev);
1246
1247 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
1248 if (!dj_report)
1249 return -ENOMEM;
1250 dj_report->report_id = REPORT_ID_DJ_SHORT;
1251 dj_report->device_index = HIDPP_RECEIVER_INDEX;
1252 dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
1253 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
1254 kfree(dj_report);
1255 return retval;
1256}
1257
1258
1259static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
1260 unsigned timeout)
1261{
1262 struct hid_device *hdev = djrcv_dev->hidpp;
1263 struct dj_report *dj_report;
1264 u8 *buf;
1265 int retval = 0;
1266
1267 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
1268 if (!dj_report)
1269 return -ENOMEM;
1270
1271 if (djrcv_dev->type == recvr_type_dj) {
1272 dj_report->report_id = REPORT_ID_DJ_SHORT;
1273 dj_report->device_index = HIDPP_RECEIVER_INDEX;
1274 dj_report->report_type = REPORT_TYPE_CMD_SWITCH;
1275 dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;
1276 dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] =
1277 (u8)timeout;
1278
1279 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
1280
1281
1282
1283
1284
1285
1286
1287 msleep(50);
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297 buf = (u8 *)dj_report;
1298
1299 memset(buf, 0, HIDPP_REPORT_SHORT_LENGTH);
1300
1301 buf[0] = REPORT_ID_HIDPP_SHORT;
1302 buf[1] = HIDPP_RECEIVER_INDEX;
1303 buf[2] = 0x80;
1304 buf[3] = 0x00;
1305 buf[4] = 0x00;
1306 buf[5] = 0x09;
1307 buf[6] = 0x00;
1308
1309 hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf,
1310 HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,
1311 HID_REQ_SET_REPORT);
1312
1313 kfree(dj_report);
1314 return retval;
1315}
1316
1317
1318static int logi_dj_ll_open(struct hid_device *hid)
1319{
1320 dbg_hid("%s: %s\n", __func__, hid->phys);
1321 return 0;
1322
1323}
1324
1325static void logi_dj_ll_close(struct hid_device *hid)
1326{
1327 dbg_hid("%s: %s\n", __func__, hid->phys);
1328}
1329
1330
1331
1332
1333
1334static u8 unifying_pairing_query[] = { REPORT_ID_HIDPP_SHORT,
1335 HIDPP_RECEIVER_INDEX,
1336 HIDPP_GET_LONG_REGISTER,
1337 HIDPP_REG_PAIRING_INFORMATION };
1338static u8 unifying_pairing_answer[] = { REPORT_ID_HIDPP_LONG,
1339 HIDPP_RECEIVER_INDEX,
1340 HIDPP_GET_LONG_REGISTER,
1341 HIDPP_REG_PAIRING_INFORMATION };
1342
1343static int logi_dj_ll_raw_request(struct hid_device *hid,
1344 unsigned char reportnum, __u8 *buf,
1345 size_t count, unsigned char report_type,
1346 int reqtype)
1347{
1348 struct dj_device *djdev = hid->driver_data;
1349 struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
1350 u8 *out_buf;
1351 int ret;
1352
1353 if ((buf[0] == REPORT_ID_HIDPP_SHORT) ||
1354 (buf[0] == REPORT_ID_HIDPP_LONG) ||
1355 (buf[0] == REPORT_ID_HIDPP_VERY_LONG)) {
1356 if (count < 2)
1357 return -EINVAL;
1358
1359
1360
1361 if (count == 7 && !memcmp(buf, unifying_pairing_query,
1362 sizeof(unifying_pairing_query)))
1363 buf[4] = (buf[4] & 0xf0) | (djdev->device_index - 1);
1364 else
1365 buf[1] = djdev->device_index;
1366 return hid_hw_raw_request(djrcv_dev->hidpp, reportnum, buf,
1367 count, report_type, reqtype);
1368 }
1369
1370 if (buf[0] != REPORT_TYPE_LEDS)
1371 return -EINVAL;
1372
1373 if (djrcv_dev->type != recvr_type_dj && count >= 2) {
1374 if (!djrcv_dev->keyboard) {
1375 hid_warn(hid, "Received REPORT_TYPE_LEDS request before the keyboard interface was enumerated\n");
1376 return 0;
1377 }
1378
1379 return hid_hw_raw_request(djrcv_dev->keyboard, 0, buf, count,
1380 report_type, reqtype);
1381 }
1382
1383 out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC);
1384 if (!out_buf)
1385 return -ENOMEM;
1386
1387 if (count > DJREPORT_SHORT_LENGTH - 2)
1388 count = DJREPORT_SHORT_LENGTH - 2;
1389
1390 out_buf[0] = REPORT_ID_DJ_SHORT;
1391 out_buf[1] = djdev->device_index;
1392 memcpy(out_buf + 2, buf, count);
1393
1394 ret = hid_hw_raw_request(djrcv_dev->hidpp, out_buf[0], out_buf,
1395 DJREPORT_SHORT_LENGTH, report_type, reqtype);
1396
1397 kfree(out_buf);
1398 return ret;
1399}
1400
1401static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size)
1402{
1403 memcpy(rdesc + *rsize, data, size);
1404 *rsize += size;
1405}
1406
1407static int logi_dj_ll_parse(struct hid_device *hid)
1408{
1409 struct dj_device *djdev = hid->driver_data;
1410 unsigned int rsize = 0;
1411 char *rdesc;
1412 int retval;
1413
1414 dbg_hid("%s\n", __func__);
1415
1416 djdev->hdev->version = 0x0111;
1417 djdev->hdev->country = 0x00;
1418
1419 rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL);
1420 if (!rdesc)
1421 return -ENOMEM;
1422
1423 if (djdev->reports_supported & STD_KEYBOARD) {
1424 dbg_hid("%s: sending a kbd descriptor, reports_supported: %llx\n",
1425 __func__, djdev->reports_supported);
1426 rdcat(rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor));
1427 }
1428
1429 if (djdev->reports_supported & STD_MOUSE) {
1430 dbg_hid("%s: sending a mouse descriptor, reports_supported: %llx\n",
1431 __func__, djdev->reports_supported);
1432 if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp ||
1433 djdev->dj_receiver_dev->type == recvr_type_mouse_only)
1434 rdcat(rdesc, &rsize, mse_high_res_descriptor,
1435 sizeof(mse_high_res_descriptor));
1436 else if (djdev->dj_receiver_dev->type == recvr_type_27mhz)
1437 rdcat(rdesc, &rsize, mse_27mhz_descriptor,
1438 sizeof(mse_27mhz_descriptor));
1439 else if (recvr_type_is_bluetooth(djdev->dj_receiver_dev->type))
1440 rdcat(rdesc, &rsize, mse_bluetooth_descriptor,
1441 sizeof(mse_bluetooth_descriptor));
1442 else
1443 rdcat(rdesc, &rsize, mse_descriptor,
1444 sizeof(mse_descriptor));
1445 }
1446
1447 if (djdev->reports_supported & KBD_MOUSE) {
1448 dbg_hid("%s: sending a kbd-mouse descriptor, reports_supported: %llx\n",
1449 __func__, djdev->reports_supported);
1450 rdcat(rdesc, &rsize, mse5_bluetooth_descriptor,
1451 sizeof(mse5_bluetooth_descriptor));
1452 }
1453
1454 if (djdev->reports_supported & MULTIMEDIA) {
1455 dbg_hid("%s: sending a multimedia report descriptor: %llx\n",
1456 __func__, djdev->reports_supported);
1457 rdcat(rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor));
1458 }
1459
1460 if (djdev->reports_supported & POWER_KEYS) {
1461 dbg_hid("%s: sending a power keys report descriptor: %llx\n",
1462 __func__, djdev->reports_supported);
1463 rdcat(rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor));
1464 }
1465
1466 if (djdev->reports_supported & MEDIA_CENTER) {
1467 dbg_hid("%s: sending a media center report descriptor: %llx\n",
1468 __func__, djdev->reports_supported);
1469 rdcat(rdesc, &rsize, media_descriptor, sizeof(media_descriptor));
1470 }
1471
1472 if (djdev->reports_supported & KBD_LEDS) {
1473 dbg_hid("%s: need to send kbd leds report descriptor: %llx\n",
1474 __func__, djdev->reports_supported);
1475 }
1476
1477 if (djdev->reports_supported & HIDPP) {
1478 dbg_hid("%s: sending a HID++ descriptor, reports_supported: %llx\n",
1479 __func__, djdev->reports_supported);
1480 rdcat(rdesc, &rsize, hidpp_descriptor,
1481 sizeof(hidpp_descriptor));
1482 }
1483
1484 retval = hid_parse_report(hid, rdesc, rsize);
1485 kfree(rdesc);
1486
1487 return retval;
1488}
1489
1490static int logi_dj_ll_start(struct hid_device *hid)
1491{
1492 dbg_hid("%s\n", __func__);
1493 return 0;
1494}
1495
1496static void logi_dj_ll_stop(struct hid_device *hid)
1497{
1498 dbg_hid("%s\n", __func__);
1499}
1500
1501static bool logi_dj_ll_may_wakeup(struct hid_device *hid)
1502{
1503 struct dj_device *djdev = hid->driver_data;
1504 struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
1505
1506 return hid_hw_may_wakeup(djrcv_dev->hidpp);
1507}
1508
1509static struct hid_ll_driver logi_dj_ll_driver = {
1510 .parse = logi_dj_ll_parse,
1511 .start = logi_dj_ll_start,
1512 .stop = logi_dj_ll_stop,
1513 .open = logi_dj_ll_open,
1514 .close = logi_dj_ll_close,
1515 .raw_request = logi_dj_ll_raw_request,
1516 .may_wakeup = logi_dj_ll_may_wakeup,
1517};
1518
1519static int logi_dj_dj_event(struct hid_device *hdev,
1520 struct hid_report *report, u8 *data,
1521 int size)
1522{
1523 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1524 struct dj_report *dj_report = (struct dj_report *) data;
1525 unsigned long flags;
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545 if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
1546 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
1547
1548
1549
1550
1551
1552 if (dj_report->device_index != DJ_RECEIVER_INDEX)
1553 hid_err(hdev, "%s: invalid device index:%d\n",
1554 __func__, dj_report->device_index);
1555 return false;
1556 }
1557
1558 spin_lock_irqsave(&djrcv_dev->lock, flags);
1559
1560 if (!djrcv_dev->paired_dj_devices[dj_report->device_index]) {
1561
1562 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
1563 goto out;
1564 }
1565
1566 switch (dj_report->report_type) {
1567 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
1568
1569 break;
1570 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
1571 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
1572 break;
1573 case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
1574 if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
1575 STATUS_LINKLOSS) {
1576 logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
1577 }
1578 break;
1579 default:
1580 logi_dj_recv_forward_dj(djrcv_dev, dj_report);
1581 }
1582
1583out:
1584 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
1585
1586 return true;
1587}
1588
1589static int logi_dj_hidpp_event(struct hid_device *hdev,
1590 struct hid_report *report, u8 *data,
1591 int size)
1592{
1593 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1594 struct hidpp_event *hidpp_report = (struct hidpp_event *) data;
1595 struct dj_device *dj_dev;
1596 unsigned long flags;
1597 u8 device_index = hidpp_report->device_index;
1598
1599 if (device_index == HIDPP_RECEIVER_INDEX) {
1600
1601
1602 if (size == HIDPP_REPORT_LONG_LENGTH &&
1603 !memcmp(data, unifying_pairing_answer,
1604 sizeof(unifying_pairing_answer)))
1605 device_index = (data[4] & 0x0F) + 1;
1606 else
1607 return false;
1608 }
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618 if ((device_index < DJ_DEVICE_INDEX_MIN) ||
1619 (device_index > DJ_DEVICE_INDEX_MAX)) {
1620
1621
1622
1623
1624
1625 hid_err(hdev, "%s: invalid device index:%d\n", __func__,
1626 hidpp_report->device_index);
1627 return false;
1628 }
1629
1630 spin_lock_irqsave(&djrcv_dev->lock, flags);
1631
1632 dj_dev = djrcv_dev->paired_dj_devices[device_index];
1633
1634
1635
1636
1637
1638 if (djrcv_dev->type == recvr_type_27mhz && dj_dev &&
1639 hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_CONNECTED &&
1640 hidpp_report->params[HIDPP_PARAM_PROTO_TYPE] == 0x02 &&
1641 hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID] !=
1642 dj_dev->hdev->product) {
1643 struct dj_workitem workitem = {
1644 .device_index = hidpp_report->device_index,
1645 .type = WORKITEM_TYPE_UNPAIRED,
1646 };
1647 kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
1648
1649 dj_dev = NULL;
1650 }
1651
1652 if (dj_dev) {
1653 logi_dj_recv_forward_report(dj_dev, data, size);
1654 } else {
1655 if (hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_CONNECTED)
1656 logi_hidpp_recv_queue_notif(hdev, hidpp_report);
1657 else
1658 logi_dj_recv_queue_unknown_work(djrcv_dev);
1659 }
1660
1661 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
1662
1663 return false;
1664}
1665
1666static int logi_dj_raw_event(struct hid_device *hdev,
1667 struct hid_report *report, u8 *data,
1668 int size)
1669{
1670 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1671 dbg_hid("%s, size:%d\n", __func__, size);
1672
1673 if (!djrcv_dev)
1674 return 0;
1675
1676 if (!hdev->report_enum[HID_INPUT_REPORT].numbered) {
1677
1678 if (djrcv_dev->unnumbered_application == HID_GD_KEYBOARD) {
1679
1680
1681
1682
1683
1684 data[1] = data[0];
1685 data[0] = REPORT_TYPE_KEYBOARD;
1686
1687 logi_dj_recv_forward_input_report(hdev, data, size);
1688
1689
1690 data[0] = data[1];
1691 data[1] = 0;
1692 }
1693
1694
1695
1696
1697 if (djrcv_dev->unnumbered_application == HID_GD_MOUSE &&
1698 size <= 8) {
1699 u8 mouse_report[9];
1700
1701
1702 mouse_report[0] = REPORT_TYPE_MOUSE;
1703 memcpy(mouse_report + 1, data, size);
1704 logi_dj_recv_forward_input_report(hdev, mouse_report,
1705 size + 1);
1706 }
1707
1708 return false;
1709 }
1710
1711 switch (data[0]) {
1712 case REPORT_ID_DJ_SHORT:
1713 if (size != DJREPORT_SHORT_LENGTH) {
1714 hid_err(hdev, "Short DJ report bad size (%d)", size);
1715 return false;
1716 }
1717 return logi_dj_dj_event(hdev, report, data, size);
1718 case REPORT_ID_DJ_LONG:
1719 if (size != DJREPORT_LONG_LENGTH) {
1720 hid_err(hdev, "Long DJ report bad size (%d)", size);
1721 return false;
1722 }
1723 return logi_dj_dj_event(hdev, report, data, size);
1724 case REPORT_ID_HIDPP_SHORT:
1725 if (size != HIDPP_REPORT_SHORT_LENGTH) {
1726 hid_err(hdev, "Short HID++ report bad size (%d)", size);
1727 return false;
1728 }
1729 return logi_dj_hidpp_event(hdev, report, data, size);
1730 case REPORT_ID_HIDPP_LONG:
1731 if (size != HIDPP_REPORT_LONG_LENGTH) {
1732 hid_err(hdev, "Long HID++ report bad size (%d)", size);
1733 return false;
1734 }
1735 return logi_dj_hidpp_event(hdev, report, data, size);
1736 }
1737
1738 logi_dj_recv_forward_input_report(hdev, data, size);
1739
1740 return false;
1741}
1742
1743static int logi_dj_probe(struct hid_device *hdev,
1744 const struct hid_device_id *id)
1745{
1746 struct hid_report_enum *rep_enum;
1747 struct hid_report *rep;
1748 struct dj_receiver_dev *djrcv_dev;
1749 struct usb_interface *intf;
1750 unsigned int no_dj_interfaces = 0;
1751 bool has_hidpp = false;
1752 unsigned long flags;
1753 int retval;
1754
1755
1756
1757
1758
1759
1760 retval = hid_parse(hdev);
1761 if (retval) {
1762 hid_err(hdev, "%s: parse failed\n", __func__);
1763 return retval;
1764 }
1765
1766
1767
1768
1769
1770
1771
1772 switch (id->driver_data) {
1773 case recvr_type_dj: no_dj_interfaces = 3; break;
1774 case recvr_type_hidpp: no_dj_interfaces = 2; break;
1775 case recvr_type_gaming_hidpp: no_dj_interfaces = 3; break;
1776 case recvr_type_mouse_only: no_dj_interfaces = 2; break;
1777 case recvr_type_27mhz: no_dj_interfaces = 2; break;
1778 case recvr_type_bluetooth: no_dj_interfaces = 2; break;
1779 case recvr_type_dinovo: no_dj_interfaces = 2; break;
1780 }
1781 if (hid_is_usb(hdev)) {
1782 intf = to_usb_interface(hdev->dev.parent);
1783 if (intf && intf->altsetting->desc.bInterfaceNumber >=
1784 no_dj_interfaces) {
1785 hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
1786 return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
1787 }
1788 }
1789
1790 rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
1791
1792
1793 if (list_empty(&rep_enum->report_list))
1794 return -ENODEV;
1795
1796
1797
1798
1799
1800
1801 list_for_each_entry(rep, &rep_enum->report_list, list) {
1802 if (rep->application == 0xff000001)
1803 has_hidpp = true;
1804 }
1805
1806
1807
1808
1809
1810 if (!has_hidpp && id->driver_data == recvr_type_dj)
1811 return -ENODEV;
1812
1813
1814 rep = list_first_entry(&rep_enum->report_list, struct hid_report, list);
1815 djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data,
1816 rep->application, has_hidpp);
1817 if (!djrcv_dev) {
1818 hid_err(hdev, "%s: dj_get_receiver_dev failed\n", __func__);
1819 return -ENOMEM;
1820 }
1821
1822 if (!rep_enum->numbered)
1823 djrcv_dev->unnumbered_application = rep->application;
1824
1825
1826
1827 retval = hid_hw_start(hdev, HID_CONNECT_HIDRAW|HID_CONNECT_HIDDEV);
1828 if (retval) {
1829 hid_err(hdev, "%s: hid_hw_start returned error\n", __func__);
1830 goto hid_hw_start_fail;
1831 }
1832
1833 if (has_hidpp) {
1834 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
1835 if (retval < 0) {
1836 hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
1837 __func__, retval);
1838 goto switch_to_dj_mode_fail;
1839 }
1840 }
1841
1842
1843 retval = hid_hw_open(hdev);
1844 if (retval < 0) {
1845 hid_err(hdev, "%s: hid_hw_open returned error:%d\n",
1846 __func__, retval);
1847 goto llopen_failed;
1848 }
1849
1850
1851 hid_device_io_start(hdev);
1852
1853 if (has_hidpp) {
1854 spin_lock_irqsave(&djrcv_dev->lock, flags);
1855 djrcv_dev->ready = true;
1856 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
1857 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
1858 if (retval < 0) {
1859 hid_err(hdev, "%s: logi_dj_recv_query_paired_devices error:%d\n",
1860 __func__, retval);
1861
1862
1863
1864
1865 }
1866 }
1867
1868 return 0;
1869
1870llopen_failed:
1871switch_to_dj_mode_fail:
1872 hid_hw_stop(hdev);
1873
1874hid_hw_start_fail:
1875 dj_put_receiver_dev(hdev);
1876 return retval;
1877}
1878
1879#ifdef CONFIG_PM
1880static int logi_dj_reset_resume(struct hid_device *hdev)
1881{
1882 int retval;
1883 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1884
1885 if (!djrcv_dev || djrcv_dev->hidpp != hdev)
1886 return 0;
1887
1888 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
1889 if (retval < 0) {
1890 hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
1891 __func__, retval);
1892 }
1893
1894 return 0;
1895}
1896#endif
1897
1898static void logi_dj_remove(struct hid_device *hdev)
1899{
1900 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1901 struct dj_device *dj_dev;
1902 unsigned long flags;
1903 int i;
1904
1905 dbg_hid("%s\n", __func__);
1906
1907 if (!djrcv_dev)
1908 return hid_hw_stop(hdev);
1909
1910
1911
1912
1913
1914 spin_lock_irqsave(&djrcv_dev->lock, flags);
1915 djrcv_dev->ready = false;
1916 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
1917
1918 cancel_work_sync(&djrcv_dev->work);
1919
1920 hid_hw_close(hdev);
1921 hid_hw_stop(hdev);
1922
1923
1924
1925
1926
1927
1928
1929
1930 for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
1931 spin_lock_irqsave(&djrcv_dev->lock, flags);
1932 dj_dev = djrcv_dev->paired_dj_devices[i];
1933 djrcv_dev->paired_dj_devices[i] = NULL;
1934 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
1935 if (dj_dev != NULL) {
1936 hid_destroy_device(dj_dev->hdev);
1937 kfree(dj_dev);
1938 }
1939 }
1940
1941 dj_put_receiver_dev(hdev);
1942}
1943
1944static const struct hid_device_id logi_dj_receivers[] = {
1945 {
1946 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1947 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER),
1948 .driver_data = recvr_type_dj},
1949 {
1950 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1951 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2),
1952 .driver_data = recvr_type_dj},
1953
1954 {
1955 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1956 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER),
1957 .driver_data = recvr_type_mouse_only},
1958 {
1959 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1960 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2),
1961 .driver_data = recvr_type_hidpp},
1962
1963 {
1964 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1965 USB_DEVICE_ID_LOGITECH_G700_RECEIVER),
1966 .driver_data = recvr_type_gaming_hidpp},
1967 {
1968 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1969 0xc537),
1970 .driver_data = recvr_type_gaming_hidpp},
1971 {
1972 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1973 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1),
1974 .driver_data = recvr_type_gaming_hidpp},
1975 {
1976 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1977 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY),
1978 .driver_data = recvr_type_gaming_hidpp},
1979 {
1980 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1981 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1),
1982 .driver_data = recvr_type_gaming_hidpp},
1983
1984 {
1985 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
1986 .driver_data = recvr_type_27mhz},
1987 {
1988 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1989 USB_DEVICE_ID_S510_RECEIVER_2),
1990 .driver_data = recvr_type_27mhz},
1991 {
1992 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1993 USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER),
1994 .driver_data = recvr_type_27mhz},
1995
1996 {
1997 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1998 USB_DEVICE_ID_MX5000_RECEIVER_KBD_DEV),
1999 .driver_data = recvr_type_bluetooth},
2000 {
2001 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
2002 USB_DEVICE_ID_MX5000_RECEIVER_MOUSE_DEV),
2003 .driver_data = recvr_type_bluetooth},
2004 {
2005 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
2006 USB_DEVICE_ID_MX5500_RECEIVER_KBD_DEV),
2007 .driver_data = recvr_type_bluetooth},
2008 {
2009 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
2010 USB_DEVICE_ID_MX5500_RECEIVER_MOUSE_DEV),
2011 .driver_data = recvr_type_bluetooth},
2012
2013 {
2014 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
2015 USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_KBD_DEV),
2016 .driver_data = recvr_type_dinovo},
2017 {
2018 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
2019 USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_MOUSE_DEV),
2020 .driver_data = recvr_type_dinovo},
2021 {
2022 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
2023 USB_DEVICE_ID_DINOVO_MINI_RECEIVER_KBD_DEV),
2024 .driver_data = recvr_type_dinovo},
2025 {
2026 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
2027 USB_DEVICE_ID_DINOVO_MINI_RECEIVER_MOUSE_DEV),
2028 .driver_data = recvr_type_dinovo},
2029 {}
2030};
2031
2032MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
2033
2034static struct hid_driver logi_djreceiver_driver = {
2035 .name = "logitech-djreceiver",
2036 .id_table = logi_dj_receivers,
2037 .probe = logi_dj_probe,
2038 .remove = logi_dj_remove,
2039 .raw_event = logi_dj_raw_event,
2040#ifdef CONFIG_PM
2041 .reset_resume = logi_dj_reset_resume,
2042#endif
2043};
2044
2045module_hid_driver(logi_djreceiver_driver);
2046
2047MODULE_LICENSE("GPL");
2048MODULE_AUTHOR("Logitech");
2049MODULE_AUTHOR("Nestor Lopez Casado");
2050MODULE_AUTHOR("nlopezcasad@logitech.com");
2051