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
695static u8 unifying_name_query[] = {0x10, 0xff, 0x83, 0xb5, 0x40, 0x00, 0x00};
696static u8 unifying_name_answer[] = {0x11, 0xff, 0x83, 0xb5};
697
698static int logi_dj_ll_raw_request(struct hid_device *hid,
699 unsigned char reportnum, __u8 *buf,
700 size_t count, unsigned char report_type,
701 int reqtype)
702{
703 struct dj_device *djdev = hid->driver_data;
704 struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
705 u8 *out_buf;
706 int ret;
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
714
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
724 if (buf[0] != REPORT_TYPE_LEDS)
725 return -EINVAL;
726
727 out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC);
728 if (!out_buf)
729 return -ENOMEM;
730
731 if (count > DJREPORT_SHORT_LENGTH - 2)
732 count = DJREPORT_SHORT_LENGTH - 2;
733
734 out_buf[0] = REPORT_ID_DJ_SHORT;
735 out_buf[1] = djdev->device_index;
736 memcpy(out_buf + 2, buf, count);
737
738 ret = hid_hw_raw_request(djrcv_dev->hdev, out_buf[0], out_buf,
739 DJREPORT_SHORT_LENGTH, report_type, reqtype);
740
741 kfree(out_buf);
742 return ret;
743}
744
745static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size)
746{
747 memcpy(rdesc + *rsize, data, size);
748 *rsize += size;
749}
750
751static int logi_dj_ll_parse(struct hid_device *hid)
752{
753 struct dj_device *djdev = hid->driver_data;
754 unsigned int rsize = 0;
755 char *rdesc;
756 int retval;
757
758 dbg_hid("%s\n", __func__);
759
760 djdev->hdev->version = 0x0111;
761 djdev->hdev->country = 0x00;
762
763 rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL);
764 if (!rdesc)
765 return -ENOMEM;
766
767 if (djdev->reports_supported & STD_KEYBOARD) {
768 dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
769 __func__, djdev->reports_supported);
770 rdcat(rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor));
771 }
772
773 if (djdev->reports_supported & STD_MOUSE) {
774 dbg_hid("%s: sending a mouse descriptor, reports_supported: "
775 "%x\n", __func__, djdev->reports_supported);
776 rdcat(rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor));
777 }
778
779 if (djdev->reports_supported & MULTIMEDIA) {
780 dbg_hid("%s: sending a multimedia report descriptor: %x\n",
781 __func__, djdev->reports_supported);
782 rdcat(rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor));
783 }
784
785 if (djdev->reports_supported & POWER_KEYS) {
786 dbg_hid("%s: sending a power keys report descriptor: %x\n",
787 __func__, djdev->reports_supported);
788 rdcat(rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor));
789 }
790
791 if (djdev->reports_supported & MEDIA_CENTER) {
792 dbg_hid("%s: sending a media center report descriptor: %x\n",
793 __func__, djdev->reports_supported);
794 rdcat(rdesc, &rsize, media_descriptor, sizeof(media_descriptor));
795 }
796
797 if (djdev->reports_supported & KBD_LEDS) {
798 dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
799 __func__, djdev->reports_supported);
800 }
801
802 rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor));
803
804 retval = hid_parse_report(hid, rdesc, rsize);
805 kfree(rdesc);
806
807 return retval;
808}
809
810static int logi_dj_ll_start(struct hid_device *hid)
811{
812 dbg_hid("%s\n", __func__);
813 return 0;
814}
815
816static void logi_dj_ll_stop(struct hid_device *hid)
817{
818 dbg_hid("%s\n", __func__);
819}
820
821
822static struct hid_ll_driver logi_dj_ll_driver = {
823 .parse = logi_dj_ll_parse,
824 .start = logi_dj_ll_start,
825 .stop = logi_dj_ll_stop,
826 .open = logi_dj_ll_open,
827 .close = logi_dj_ll_close,
828 .raw_request = logi_dj_ll_raw_request,
829};
830
831static int logi_dj_dj_event(struct hid_device *hdev,
832 struct hid_report *report, u8 *data,
833 int size)
834{
835 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
836 struct dj_report *dj_report = (struct dj_report *) data;
837 unsigned long flags;
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857 if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
858 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
859
860
861
862
863
864 if (dj_report->device_index != DJ_RECEIVER_INDEX)
865 dev_err(&hdev->dev, "%s: invalid device index:%d\n",
866 __func__, dj_report->device_index);
867 return false;
868 }
869
870 spin_lock_irqsave(&djrcv_dev->lock, flags);
871
872 if (!djrcv_dev->paired_dj_devices[dj_report->device_index]) {
873
874 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
875 goto out;
876 }
877
878 switch (dj_report->report_type) {
879 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
880
881 break;
882 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
883 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
884 break;
885 case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
886 if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
887 STATUS_LINKLOSS) {
888 logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
889 }
890 break;
891 default:
892 logi_dj_recv_forward_report(djrcv_dev, dj_report);
893 }
894
895out:
896 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
897
898 return true;
899}
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
912
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
924
925
926
927
928
929
930 if ((device_index < DJ_DEVICE_INDEX_MIN) ||
931 (device_index > DJ_DEVICE_INDEX_MAX)) {
932
933
934
935
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
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 if (size != DJREPORT_SHORT_LENGTH) {
966 dev_err(&hdev->dev, "DJ report of bad size (%d)", size);
967 return false;
968 }
969 return logi_dj_dj_event(hdev, report, data, size);
970 case REPORT_ID_HIDPP_SHORT:
971 if (size != HIDPP_REPORT_SHORT_LENGTH) {
972 dev_err(&hdev->dev,
973 "Short HID++ report of bad size (%d)", size);
974 return false;
975 }
976 return logi_dj_hidpp_event(hdev, report, data, size);
977 case REPORT_ID_HIDPP_LONG:
978 if (size != HIDPP_REPORT_LONG_LENGTH) {
979 dev_err(&hdev->dev,
980 "Long HID++ report of bad size (%d)", size);
981 return false;
982 }
983 return logi_dj_hidpp_event(hdev, report, data, size);
984 }
985
986 return false;
987}
988
989static int logi_dj_probe(struct hid_device *hdev,
990 const struct hid_device_id *id)
991{
992 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
993 struct dj_receiver_dev *djrcv_dev;
994 int retval;
995
996 dbg_hid("%s called for ifnum %d\n", __func__,
997 intf->cur_altsetting->desc.bInterfaceNumber);
998
999
1000
1001 if (intf->cur_altsetting->desc.bInterfaceNumber !=
1002 LOGITECH_DJ_INTERFACE_NUMBER) {
1003 dbg_hid("%s: ignoring ifnum %d\n", __func__,
1004 intf->cur_altsetting->desc.bInterfaceNumber);
1005 return -ENODEV;
1006 }
1007
1008
1009
1010 djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
1011 if (!djrcv_dev) {
1012 dev_err(&hdev->dev,
1013 "%s:failed allocating dj_receiver_dev\n", __func__);
1014 return -ENOMEM;
1015 }
1016 djrcv_dev->hdev = hdev;
1017 INIT_WORK(&djrcv_dev->work, delayedwork_callback);
1018 spin_lock_init(&djrcv_dev->lock);
1019 if (kfifo_alloc(&djrcv_dev->notif_fifo,
1020 DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
1021 GFP_KERNEL)) {
1022 dev_err(&hdev->dev,
1023 "%s:failed allocating notif_fifo\n", __func__);
1024 kfree(djrcv_dev);
1025 return -ENOMEM;
1026 }
1027 hid_set_drvdata(hdev, djrcv_dev);
1028
1029
1030
1031
1032
1033 retval = hid_parse(hdev);
1034 if (retval) {
1035 dev_err(&hdev->dev,
1036 "%s:parse of interface 2 failed\n", __func__);
1037 goto hid_parse_fail;
1038 }
1039
1040 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT,
1041 0, DJREPORT_SHORT_LENGTH - 1)) {
1042 retval = -ENODEV;
1043 goto hid_parse_fail;
1044 }
1045
1046
1047
1048 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
1049 if (retval) {
1050 dev_err(&hdev->dev,
1051 "%s:hid_hw_start returned error\n", __func__);
1052 goto hid_hw_start_fail;
1053 }
1054
1055 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
1056 if (retval < 0) {
1057 dev_err(&hdev->dev,
1058 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
1059 __func__, retval);
1060 goto switch_to_dj_mode_fail;
1061 }
1062
1063
1064 retval = hid_hw_open(hdev);
1065 if (retval < 0) {
1066 dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n",
1067 __func__, retval);
1068 goto llopen_failed;
1069 }
1070
1071
1072 hid_device_io_start(hdev);
1073
1074 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
1075 if (retval < 0) {
1076 dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
1077 "error:%d\n", __func__, retval);
1078 goto logi_dj_recv_query_paired_devices_failed;
1079 }
1080
1081 return retval;
1082
1083logi_dj_recv_query_paired_devices_failed:
1084 hid_hw_close(hdev);
1085
1086llopen_failed:
1087switch_to_dj_mode_fail:
1088 hid_hw_stop(hdev);
1089
1090hid_hw_start_fail:
1091hid_parse_fail:
1092 kfifo_free(&djrcv_dev->notif_fifo);
1093 kfree(djrcv_dev);
1094 hid_set_drvdata(hdev, NULL);
1095 return retval;
1096
1097}
1098
1099#ifdef CONFIG_PM
1100static int logi_dj_reset_resume(struct hid_device *hdev)
1101{
1102 int retval;
1103 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1104
1105 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
1106 if (retval < 0) {
1107 dev_err(&hdev->dev,
1108 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
1109 __func__, retval);
1110 }
1111
1112 return 0;
1113}
1114#endif
1115
1116static void logi_dj_remove(struct hid_device *hdev)
1117{
1118 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
1119 struct dj_device *dj_dev;
1120 int i;
1121
1122 dbg_hid("%s\n", __func__);
1123
1124 cancel_work_sync(&djrcv_dev->work);
1125
1126 hid_hw_close(hdev);
1127 hid_hw_stop(hdev);
1128
1129
1130
1131
1132
1133
1134 for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
1135 dj_dev = djrcv_dev->paired_dj_devices[i];
1136 if (dj_dev != NULL) {
1137 hid_destroy_device(dj_dev->hdev);
1138 kfree(dj_dev);
1139 djrcv_dev->paired_dj_devices[i] = NULL;
1140 }
1141 }
1142
1143 kfifo_free(&djrcv_dev->notif_fifo);
1144 kfree(djrcv_dev);
1145 hid_set_drvdata(hdev, NULL);
1146}
1147
1148static const struct hid_device_id logi_dj_receivers[] = {
1149 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1150 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
1151 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1152 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
1153 {}
1154};
1155
1156MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
1157
1158static struct hid_driver logi_djreceiver_driver = {
1159 .name = "logitech-djreceiver",
1160 .id_table = logi_dj_receivers,
1161 .probe = logi_dj_probe,
1162 .remove = logi_dj_remove,
1163 .raw_event = logi_dj_raw_event,
1164#ifdef CONFIG_PM
1165 .reset_resume = logi_dj_reset_resume,
1166#endif
1167};
1168
1169module_hid_driver(logi_djreceiver_driver);
1170
1171MODULE_LICENSE("GPL");
1172MODULE_AUTHOR("Logitech");
1173MODULE_AUTHOR("Nestor Lopez Casado");
1174MODULE_AUTHOR("nlopezcasad@logitech.com");
1175