1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/device.h>
26#include <linux/hid.h>
27#include <linux/module.h>
28#include <linux/usb.h>
29#include <linux/kfifo.h>
30#include <asm/unaligned.h>
31#include "hid-ids.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
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
63#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81
64
65
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
75#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40
76
77
78
79#define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42
80#define CONNECTION_STATUS_PARAM_STATUS 0x00
81#define STATUS_LINKLOSS 0x01
82
83
84#define REPORT_TYPE_NOTIF_ERROR 0x7F
85#define NOTIF_ERROR_PARAM_ETYPE 0x00
86#define ETYPE_KEEPALIVE_TIMEOUT 0x01
87
88
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
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};
127
128
129static const char kbd_descriptor[] = {
130 0x05, 0x01,
131 0x09, 0x06,
132 0xA1, 0x01,
133 0x85, 0x01,
134 0x95, 0x08,
135 0x75, 0x01,
136 0x15, 0x00,
137 0x25, 0x01,
138 0x05, 0x07,
139 0x19, 0xE0,
140 0x29, 0xE7,
141 0x81, 0x02,
142 0x95, 0x06,
143 0x75, 0x08,
144 0x15, 0x00,
145 0x26, 0xFF, 0x00,
146 0x05, 0x07,
147 0x19, 0x00,
148 0x2A, 0xFF, 0x00,
149 0x81, 0x00,
150 0x85, 0x0e,
151 0x05, 0x08,
152 0x95, 0x05,
153 0x75, 0x01,
154 0x15, 0x00,
155 0x25, 0x01,
156 0x19, 0x01,
157 0x29, 0x05,
158 0x91, 0x02,
159 0x95, 0x01,
160 0x75, 0x03,
161 0x91, 0x01,
162 0xC0
163};
164
165
166static const char mse_descriptor[] = {
167 0x05, 0x01,
168 0x09, 0x02,
169 0xA1, 0x01,
170 0x85, 0x02,
171 0x09, 0x01,
172 0xA1, 0x00,
173 0x05, 0x09,
174 0x19, 0x01,
175 0x29, 0x10,
176 0x15, 0x00,
177 0x25, 0x01,
178 0x95, 0x10,
179 0x75, 0x01,
180 0x81, 0x02,
181 0x05, 0x01,
182 0x16, 0x01, 0xF8,
183 0x26, 0xFF, 0x07,
184 0x75, 0x0C,
185 0x95, 0x02,
186 0x09, 0x30,
187 0x09, 0x31,
188 0x81, 0x06,
189 0x15, 0x81,
190 0x25, 0x7F,
191 0x75, 0x08,
192 0x95, 0x01,
193 0x09, 0x38,
194 0x81, 0x06,
195 0x05, 0x0C,
196 0x0A, 0x38, 0x02,
197 0x95, 0x01,
198 0x81, 0x06,
199 0xC0,
200 0xC0,
201};
202
203
204static const char consumer_descriptor[] = {
205 0x05, 0x0C,
206 0x09, 0x01,
207 0xA1, 0x01,
208 0x85, 0x03,
209 0x75, 0x10,
210 0x95, 0x02,
211 0x15, 0x01,
212 0x26, 0x8C, 0x02,
213 0x19, 0x01,
214 0x2A, 0x8C, 0x02,
215 0x81, 0x00,
216 0xC0,
217};
218
219
220static const char syscontrol_descriptor[] = {
221 0x05, 0x01,
222 0x09, 0x80,
223 0xA1, 0x01,
224 0x85, 0x04,
225 0x75, 0x02,
226 0x95, 0x01,
227 0x15, 0x01,
228 0x25, 0x03,
229 0x09, 0x82,
230 0x09, 0x81,
231 0x09, 0x83,
232 0x81, 0x60,
233 0x75, 0x06,
234 0x81, 0x03,
235 0xC0,
236};
237
238
239static const char media_descriptor[] = {
240 0x06, 0xbc, 0xff,
241 0x09, 0x88,
242 0xa1, 0x01,
243 0x85, 0x08,
244 0x19, 0x01,
245 0x29, 0xff,
246 0x15, 0x01,
247 0x26, 0xff, 0x00,
248 0x75, 0x08,
249 0x95, 0x01,
250 0x81, 0x00,
251 0xc0,
252};
253
254
255static const char hidpp_descriptor[] = {
256 0x06, 0x00, 0xff,
257 0x09, 0x01,
258 0xa1, 0x01,
259 0x85, 0x10,
260 0x75, 0x08,
261 0x95, 0x06,
262 0x15, 0x00,
263 0x26, 0xff, 0x00,
264 0x09, 0x01,
265 0x81, 0x00,
266 0x09, 0x01,
267 0x91, 0x00,
268 0xc0,
269 0x06, 0x00, 0xff,
270 0x09, 0x02,
271 0xa1, 0x01,
272 0x85, 0x11,
273 0x75, 0x08,
274 0x95, 0x13,
275 0x15, 0x00,
276 0x26, 0xff, 0x00,
277 0x09, 0x02,
278 0x81, 0x00,
279 0x09, 0x02,
280 0x91, 0x00,
281 0xc0,
282 0x06, 0x00, 0xff,
283 0x09, 0x04,
284 0xa1, 0x01,
285 0x85, 0x20,
286 0x75, 0x08,
287 0x95, 0x0e,
288 0x15, 0x00,
289 0x26, 0xff, 0x00,
290 0x09, 0x41,
291 0x81, 0x00,
292 0x09, 0x41,
293 0x91, 0x00,
294 0x85, 0x21,
295 0x95, 0x1f,
296 0x15, 0x00,
297 0x26, 0xff, 0x00,
298 0x09, 0x42,
299 0x81, 0x00,
300 0x09, 0x42,
301 0x91, 0x00,
302 0xc0,
303};
304
305
306#define MAX_REPORT_SIZE 8
307
308
309#define MAX_RDESC_SIZE \
310 (sizeof(kbd_descriptor) + \
311 sizeof(mse_descriptor) + \
312 sizeof(consumer_descriptor) + \
313 sizeof(syscontrol_descriptor) + \
314 sizeof(media_descriptor) + \
315 sizeof(hidpp_descriptor))
316
317
318
319
320
321
322
323
324
325
326
327
328
329#define NUMBER_OF_HID_REPORTS 32
330static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
331 [1] = 8,
332 [2] = 8,
333 [3] = 5,
334 [4] = 2,
335 [8] = 2,
336};
337
338
339#define LOGITECH_DJ_INTERFACE_NUMBER 0x02
340
341static struct hid_ll_driver logi_dj_ll_driver;
342
343static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
344
345static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
346 struct dj_report *dj_report)
347{
348
349 struct dj_device *dj_dev;
350 unsigned long flags;
351
352 spin_lock_irqsave(&djrcv_dev->lock, flags);
353 dj_dev = djrcv_dev->paired_dj_devices[dj_report->device_index];
354 djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
355 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
356
357 if (dj_dev != NULL) {
358 hid_destroy_device(dj_dev->hdev);
359 kfree(dj_dev);
360 } else {
361 dev_err(&djrcv_dev->hdev->dev, "%s: can't destroy a NULL device\n",
362 __func__);
363 }
364}
365
366static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
367 struct dj_report *dj_report)
368{
369
370 struct hid_device *djrcv_hdev = djrcv_dev->hdev;
371 struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
372 struct usb_device *usbdev = interface_to_usbdev(intf);
373 struct hid_device *dj_hiddev;
374 struct dj_device *dj_dev;
375
376
377
378
379 unsigned char tmpstr[3];
380
381 if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
382 SPFUNCTION_DEVICE_LIST_EMPTY) {
383 dbg_hid("%s: device list is empty\n", __func__);
384 djrcv_dev->querying_devices = false;
385 return;
386 }
387
388 if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
389
390 dbg_hid("%s: device is already known\n", __func__);
391 return;
392 }
393
394 dj_hiddev = hid_allocate_device();
395 if (IS_ERR(dj_hiddev)) {
396 dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
397 __func__);
398 return;
399 }
400
401 dj_hiddev->ll_driver = &logi_dj_ll_driver;
402
403 dj_hiddev->dev.parent = &djrcv_hdev->dev;
404 dj_hiddev->bus = BUS_USB;
405 dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
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];
410 snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
411 "Logitech Unifying Device. Wireless PID:%04x",
412 dj_hiddev->product);
413
414 dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE;
415
416 usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
417 snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
418 strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));
419
420 dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);
421
422 if (!dj_dev) {
423 dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n",
424 __func__);
425 goto dj_device_allocate_fail;
426 }
427
428 dj_dev->reports_supported = get_unaligned_le32(
429 dj_report->report_params + DEVICE_PAIRED_RF_REPORT_TYPE);
430 dj_dev->hdev = dj_hiddev;
431 dj_dev->dj_receiver_dev = djrcv_dev;
432 dj_dev->device_index = dj_report->device_index;
433 dj_hiddev->driver_data = dj_dev;
434
435 djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev;
436
437 if (hid_add_device(dj_hiddev)) {
438 dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
439 __func__);
440 goto hid_add_device_fail;
441 }
442
443 return;
444
445hid_add_device_fail:
446 djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
447 kfree(dj_dev);
448dj_device_allocate_fail:
449 hid_destroy_device(dj_hiddev);
450}
451
452static void delayedwork_callback(struct work_struct *work)
453{
454 struct dj_receiver_dev *djrcv_dev =
455 container_of(work, struct dj_receiver_dev, work);
456
457 struct dj_report dj_report;
458 unsigned long flags;
459 int count;
460 int retval;
461
462 dbg_hid("%s\n", __func__);
463
464 spin_lock_irqsave(&djrcv_dev->lock, flags);
465
466 count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report,
467 sizeof(struct dj_report));
468
469 if (count != sizeof(struct dj_report)) {
470 dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without "
471 "notifications available\n", __func__);
472 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
473 return;
474 }
475
476 if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) {
477 if (schedule_work(&djrcv_dev->work) == 0) {
478 dbg_hid("%s: did not schedule the work item, was "
479 "already queued\n", __func__);
480 }
481 }
482
483 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
484
485 switch (dj_report.report_type) {
486 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
487 logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report);
488 break;
489 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
490 logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
491 break;
492 default:
493
494
495
496
497
498
499
500 if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
501
502
503 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
504 if (!retval) {
505
506 break;
507 }
508 dev_err(&djrcv_dev->hdev->dev,
509 "%s:logi_dj_recv_query_paired_devices "
510 "error:%d\n", __func__, retval);
511 }
512 dbg_hid("%s: unexpected report type\n", __func__);
513 }
514}
515
516static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
517 struct dj_report *dj_report)
518{
519
520
521 kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
522
523 if (schedule_work(&djrcv_dev->work) == 0) {
524 dbg_hid("%s: did not schedule the work item, was already "
525 "queued\n", __func__);
526 }
527}
528
529static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
530 struct dj_report *dj_report)
531{
532
533 unsigned int i;
534 u8 reportbuffer[MAX_REPORT_SIZE];
535 struct dj_device *djdev;
536
537 djdev = djrcv_dev->paired_dj_devices[dj_report->device_index];
538
539 memset(reportbuffer, 0, sizeof(reportbuffer));
540
541 for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) {
542 if (djdev->reports_supported & (1 << i)) {
543 reportbuffer[0] = i;
544 if (hid_input_report(djdev->hdev,
545 HID_INPUT_REPORT,
546 reportbuffer,
547 hid_reportid_size_map[i], 1)) {
548 dbg_hid("hid_input_report error sending null "
549 "report\n");
550 }
551 }
552 }
553}
554
555static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
556 struct dj_report *dj_report)
557{
558
559 struct dj_device *dj_device;
560
561 dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index];
562
563 if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) ||
564 (hid_reportid_size_map[dj_report->report_type] == 0)) {
565 dbg_hid("invalid report type:%x\n", dj_report->report_type);
566 return;
567 }
568
569 if (hid_input_report(dj_device->hdev,
570 HID_INPUT_REPORT, &dj_report->report_type,
571 hid_reportid_size_map[dj_report->report_type], 1)) {
572 dbg_hid("hid_input_report error\n");
573 }
574}
575
576static void logi_dj_recv_forward_hidpp(struct dj_device *dj_dev, u8 *data,
577 int size)
578{
579
580 if (hid_input_report(dj_dev->hdev, HID_INPUT_REPORT, data, size, 1))
581 dbg_hid("hid_input_report error\n");
582}
583
584static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
585 struct dj_report *dj_report)
586{
587 struct hid_device *hdev = djrcv_dev->hdev;
588 struct hid_report *report;
589 struct hid_report_enum *output_report_enum;
590 u8 *data = (u8 *)(&dj_report->device_index);
591 unsigned int i;
592
593 output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
594 report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
595
596 if (!report) {
597 dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__);
598 return -ENODEV;
599 }
600
601 for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++)
602 report->field[0]->value[i] = data[i];
603
604 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
605
606 return 0;
607}
608
609static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
610{
611 struct dj_report *dj_report;
612 int retval;
613
614
615 if (djrcv_dev->querying_devices)
616 return 0;
617
618 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
619 if (!dj_report)
620 return -ENOMEM;
621 dj_report->report_id = REPORT_ID_DJ_SHORT;
622 dj_report->device_index = 0xFF;
623 dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
624 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
625 kfree(dj_report);
626 return retval;
627}
628
629
630static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
631 unsigned timeout)
632{
633 struct hid_device *hdev = djrcv_dev->hdev;
634 struct dj_report *dj_report;
635 u8 *buf;
636 int retval;
637
638 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
639 if (!dj_report)
640 return -ENOMEM;
641 dj_report->report_id = REPORT_ID_DJ_SHORT;
642 dj_report->device_index = 0xFF;
643 dj_report->report_type = REPORT_TYPE_CMD_SWITCH;
644 dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;
645 dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;
646 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
647
648
649
650
651
652
653 msleep(50);
654
655
656
657
658
659
660
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);
679 return retval;
680}
681
682
683static int logi_dj_ll_open(struct hid_device *hid)
684{
685 dbg_hid("%s:%s\n", __func__, hid->phys);
686 return 0;
687
688}
689
690static void logi_dj_ll_close(struct hid_device *hid)
691{
692 dbg_hid("%s:%s\n", __func__, hid->phys);
693}
694
695
696
697
698
699static u8 unifying_pairing_query[] = {0x10, 0xff, 0x83, 0xb5};
700static u8 unifying_pairing_answer[] = {0x11, 0xff, 0x83, 0xb5};
701
702static int logi_dj_ll_raw_request(struct hid_device *hid,
703 unsigned char reportnum, __u8 *buf,
704 size_t count, unsigned char report_type,
705 int reqtype)
706{
707 struct dj_device *djdev = hid->driver_data;
708 struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
709 u8 *out_buf;
710 int ret;
711
712 if ((buf[0] == REPORT_ID_HIDPP_SHORT) ||
713 (buf[0] == REPORT_ID_HIDPP_LONG)) {
714 if (count < 2)
715 return -EINVAL;
716
717
718
719 if (count == 7 && !memcmp(buf, unifying_pairing_query,
720 sizeof(unifying_pairing_query)))
721 buf[4] = (buf[4] & 0xf0) | (djdev->device_index - 1);
722 else
723 buf[1] = djdev->device_index;
724 return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf,
725 count, report_type, reqtype);
726 }
727
728 if (buf[0] != REPORT_TYPE_LEDS)
729 return -EINVAL;
730
731 out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC);
732 if (!out_buf)
733 return -ENOMEM;
734
735 if (count > DJREPORT_SHORT_LENGTH - 2)
736 count = DJREPORT_SHORT_LENGTH - 2;
737
738 out_buf[0] = REPORT_ID_DJ_SHORT;
739 out_buf[1] = djdev->device_index;
740 memcpy(out_buf + 2, buf, count);
741
742 ret = hid_hw_raw_request(djrcv_dev->hdev, out_buf[0], out_buf,
743 DJREPORT_SHORT_LENGTH, report_type, reqtype);
744
745 kfree(out_buf);
746 return ret;
747}
748
749static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size)
750{
751 memcpy(rdesc + *rsize, data, size);
752 *rsize += size;
753}
754
755static int logi_dj_ll_parse(struct hid_device *hid)
756{
757 struct dj_device *djdev = hid->driver_data;
758 unsigned int rsize = 0;
759 char *rdesc;
760 int retval;
761
762 dbg_hid("%s\n", __func__);
763
764 djdev->hdev->version = 0x0111;
765 djdev->hdev->country = 0x00;
766
767 rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL);
768 if (!rdesc)
769 return -ENOMEM;
770
771 if (djdev->reports_supported & STD_KEYBOARD) {
772 dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
773 __func__, djdev->reports_supported);
774 rdcat(rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor));
775 }
776
777 if (djdev->reports_supported & STD_MOUSE) {
778 dbg_hid("%s: sending a mouse descriptor, reports_supported: "
779 "%x\n", __func__, djdev->reports_supported);
780 rdcat(rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor));
781 }
782
783 if (djdev->reports_supported & MULTIMEDIA) {
784 dbg_hid("%s: sending a multimedia report descriptor: %x\n",
785 __func__, djdev->reports_supported);
786 rdcat(rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor));
787 }
788
789 if (djdev->reports_supported & POWER_KEYS) {
790 dbg_hid("%s: sending a power keys report descriptor: %x\n",
791 __func__, djdev->reports_supported);
792 rdcat(rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor));
793 }
794
795 if (djdev->reports_supported & MEDIA_CENTER) {
796 dbg_hid("%s: sending a media center report descriptor: %x\n",
797 __func__, djdev->reports_supported);
798 rdcat(rdesc, &rsize, media_descriptor, sizeof(media_descriptor));
799 }
800
801 if (djdev->reports_supported & KBD_LEDS) {
802 dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
803 __func__, djdev->reports_supported);
804 }
805
806 rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor));
807
808 retval = hid_parse_report(hid, rdesc, rsize);
809 kfree(rdesc);
810
811 return retval;
812}
813
814static int logi_dj_ll_start(struct hid_device *hid)
815{
816 dbg_hid("%s\n", __func__);
817 return 0;
818}
819
820static void logi_dj_ll_stop(struct hid_device *hid)
821{
822 dbg_hid("%s\n", __func__);
823}
824
825
826static struct hid_ll_driver logi_dj_ll_driver = {
827 .parse = logi_dj_ll_parse,
828 .start = logi_dj_ll_start,
829 .stop = logi_dj_ll_stop,
830 .open = logi_dj_ll_open,
831 .close = logi_dj_ll_close,
832 .raw_request = logi_dj_ll_raw_request,
833};
834
835static int logi_dj_dj_event(struct hid_device *hdev,
836 struct hid_report *report, u8 *data,
837 int size)
838{
839 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
840 struct dj_report *dj_report = (struct dj_report *) data;
841 unsigned long flags;
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861 if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
862 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
863
864
865
866
867
868 if (dj_report->device_index != DJ_RECEIVER_INDEX)
869 dev_err(&hdev->dev, "%s: invalid device index:%d\n",
870 __func__, dj_report->device_index);
871 return false;
872 }
873
874 spin_lock_irqsave(&djrcv_dev->lock, flags);
875
876 if (!djrcv_dev->paired_dj_devices[dj_report->device_index]) {
877
878 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
879 goto out;
880 }
881
882 switch (dj_report->report_type) {
883 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
884
885 break;
886 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
887 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
888 break;
889 case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
890 if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
891 STATUS_LINKLOSS) {
892 logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
893 }
894 break;
895 default:
896 logi_dj_recv_forward_report(djrcv_dev, dj_report);
897 }
898
899out:
900 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
901
902 return true;
903}
904
905static int logi_dj_hidpp_event(struct hid_device *hdev,
906 struct hid_report *report, u8 *data,
907 int size)
908{
909 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
910 struct dj_report *dj_report = (struct dj_report *) data;
911 unsigned long flags;
912 u8 device_index = dj_report->device_index;
913
914 if (device_index == HIDPP_RECEIVER_INDEX) {
915
916
917 if (size == HIDPP_REPORT_LONG_LENGTH &&
918 !memcmp(data, unifying_pairing_answer,
919 sizeof(unifying_pairing_answer)))
920 device_index = (data[4] & 0x0F) + 1;
921 else
922 return false;
923 }
924
925
926
927
928
929
930
931
932
933 if ((device_index < DJ_DEVICE_INDEX_MIN) ||
934 (device_index > DJ_DEVICE_INDEX_MAX)) {
935
936
937
938
939
940 dev_err(&hdev->dev, "%s: invalid device index:%d\n",
941 __func__, dj_report->device_index);
942 return false;
943 }
944
945 spin_lock_irqsave(&djrcv_dev->lock, flags);
946
947 if (!djrcv_dev->paired_dj_devices[device_index])
948
949 goto out;
950
951 logi_dj_recv_forward_hidpp(djrcv_dev->paired_dj_devices[device_index],
952 data, size);
953
954out:
955 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
956
957 return false;
958}
959
960static int logi_dj_raw_event(struct hid_device *hdev,
961 struct hid_report *report, u8 *data,
962 int size)
963{
964 dbg_hid("%s, size:%d\n", __func__, size);
965
966 switch (data[0]) {
967 case REPORT_ID_DJ_SHORT:
968 if (size != DJREPORT_SHORT_LENGTH) {
969 dev_err(&hdev->dev, "DJ report of bad size (%d)", size);
970 return false;
971 }
972 return logi_dj_dj_event(hdev, report, data, size);
973 case REPORT_ID_HIDPP_SHORT:
974 if (size != HIDPP_REPORT_SHORT_LENGTH) {
975 dev_err(&hdev->dev,
976 "Short HID++ report of bad size (%d)", size);
977 return false;
978 }
979 return logi_dj_hidpp_event(hdev, report, data, size);
980 case REPORT_ID_HIDPP_LONG:
981 if (size != HIDPP_REPORT_LONG_LENGTH) {
982 dev_err(&hdev->dev,
983 "Long HID++ report of bad size (%d)", size);
984 return false;
985 }
986 return logi_dj_hidpp_event(hdev, report, data, size);
987 }
988
989 return false;
990}
991
992static int logi_dj_probe(struct hid_device *hdev,
993 const struct hid_device_id *id)
994{
995 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
996 struct dj_receiver_dev *djrcv_dev;
997 int retval;
998
999 dbg_hid("%s called for ifnum %d\n", __func__,
1000 intf->cur_altsetting->desc.bInterfaceNumber);
1001
1002
1003
1004 if (intf->cur_altsetting->desc.bInterfaceNumber !=
1005 LOGITECH_DJ_INTERFACE_NUMBER) {
1006 dbg_hid("%s: ignoring ifnum %d\n", __func__,
1007 intf->cur_altsetting->desc.bInterfaceNumber);
1008 return -ENODEV;
1009 }
1010
1011
1012
1013 djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
1014 if (!djrcv_dev) {
1015 dev_err(&hdev->dev,
1016 "%s:failed allocating dj_receiver_dev\n", __func__);
1017 return -ENOMEM;
1018 }
1019 djrcv_dev->hdev = hdev;
1020 INIT_WORK(&djrcv_dev->work, delayedwork_callback);
1021 spin_lock_init(&djrcv_dev->lock);
1022 if (kfifo_alloc(&djrcv_dev->notif_fifo,
1023 DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
1024 GFP_KERNEL)) {
1025 dev_err(&hdev->dev,
1026 "%s:failed allocating notif_fifo\n", __func__);
1027 kfree(djrcv_dev);
1028 return -ENOMEM;
1029 }
1030 hid_set_drvdata(hdev, djrcv_dev);
1031
1032
1033
1034
1035
1036 retval = hid_parse(hdev);
1037 if (retval) {
1038 dev_err(&hdev->dev,
1039 "%s:parse of interface 2 failed\n", __func__);
1040 goto hid_parse_fail;
1041 }
1042
1043 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT,
1044 0, DJREPORT_SHORT_LENGTH - 1)) {
1045 retval = -ENODEV;
1046 goto hid_parse_fail;
1047 }
1048
1049
1050
1051 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
1052 if (retval) {
1053 dev_err(&hdev->dev,
1054 "%s:hid_hw_start returned error\n", __func__);
1055 goto hid_hw_start_fail;
1056 }
1057
1058 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
1059 if (retval < 0) {
1060 dev_err(&hdev->dev,
1061 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
1062 __func__, retval);
1063 goto switch_to_dj_mode_fail;
1064 }
1065
1066
1067 retval = hid_hw_open(hdev);
1068 if (retval < 0) {
1069 dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n",
1070 __func__, retval);
1071 goto llopen_failed;
1072 }
1073
1074
1075 hid_device_io_start(hdev);
1076
1077 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
1078 if (retval < 0) {
1079 dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
1080 "error:%d\n", __func__, retval);
1081 goto logi_dj_recv_query_paired_devices_failed;
1082 }
1083
1084 return retval;
1085
1086logi_dj_recv_query_paired_devices_failed:
1087 hid_hw_close(hdev);
1088
1089llopen_failed:
1090switch_to_dj_mode_fail:
1091 hid_hw_stop(hdev);
1092
1093hid_hw_start_fail:
1094hid_parse_fail:
1095 kfifo_free(&djrcv_dev->notif_fifo);
1096 kfree(djrcv_dev);
1097 hid_set_drvdata(hdev, NULL);
1098 return retval;
1099
1100}
1101
1102#ifdef CONFIG_PM
1103static int logi_dj_reset_resume(struct hid_device *hdev)
1104{
1105 int retval;
1106 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1107
1108 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
1109 if (retval < 0) {
1110 dev_err(&hdev->dev,
1111 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
1112 __func__, retval);
1113 }
1114
1115 return 0;
1116}
1117#endif
1118
1119static void logi_dj_remove(struct hid_device *hdev)
1120{
1121 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1122 struct dj_device *dj_dev;
1123 int i;
1124
1125 dbg_hid("%s\n", __func__);
1126
1127 cancel_work_sync(&djrcv_dev->work);
1128
1129 hid_hw_close(hdev);
1130 hid_hw_stop(hdev);
1131
1132
1133
1134
1135
1136
1137 for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
1138 dj_dev = djrcv_dev->paired_dj_devices[i];
1139 if (dj_dev != NULL) {
1140 hid_destroy_device(dj_dev->hdev);
1141 kfree(dj_dev);
1142 djrcv_dev->paired_dj_devices[i] = NULL;
1143 }
1144 }
1145
1146 kfifo_free(&djrcv_dev->notif_fifo);
1147 kfree(djrcv_dev);
1148 hid_set_drvdata(hdev, NULL);
1149}
1150
1151static const struct hid_device_id logi_dj_receivers[] = {
1152 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1153 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
1154 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1155 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
1156 {}
1157};
1158
1159MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
1160
1161static struct hid_driver logi_djreceiver_driver = {
1162 .name = "logitech-djreceiver",
1163 .id_table = logi_dj_receivers,
1164 .probe = logi_dj_probe,
1165 .remove = logi_dj_remove,
1166 .raw_event = logi_dj_raw_event,
1167#ifdef CONFIG_PM
1168 .reset_resume = logi_dj_reset_resume,
1169#endif
1170};
1171
1172module_hid_driver(logi_djreceiver_driver);
1173
1174MODULE_LICENSE("GPL");
1175MODULE_AUTHOR("Logitech");
1176MODULE_AUTHOR("Nestor Lopez Casado");
1177MODULE_AUTHOR("nlopezcasad@logitech.com");
1178