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 <asm/unaligned.h>
30#include "usbhid/usbhid.h"
31#include "hid-ids.h"
32#include "hid-logitech-dj.h"
33
34
35static const char kbd_descriptor[] = {
36 0x05, 0x01,
37 0x09, 0x06,
38 0xA1, 0x01,
39 0x85, 0x01,
40 0x95, 0x08,
41 0x75, 0x01,
42 0x15, 0x00,
43 0x25, 0x01,
44 0x05, 0x07,
45 0x19, 0xE0,
46 0x29, 0xE7,
47 0x81, 0x02,
48 0x95, 0x05,
49 0x05, 0x08,
50 0x19, 0x01,
51 0x29, 0x05,
52 0x91, 0x02,
53 0x95, 0x01,
54 0x75, 0x03,
55 0x91, 0x01,
56 0x95, 0x06,
57 0x75, 0x08,
58 0x15, 0x00,
59 0x26, 0xFF, 0x00,
60 0x05, 0x07,
61 0x19, 0x00,
62 0x2A, 0xFF, 0x00,
63 0x81, 0x00,
64 0xC0
65};
66
67
68static const char mse_descriptor[] = {
69 0x05, 0x01,
70 0x09, 0x02,
71 0xA1, 0x01,
72 0x85, 0x02,
73 0x09, 0x01,
74 0xA1, 0x00,
75 0x05, 0x09,
76 0x19, 0x01,
77 0x29, 0x10,
78 0x15, 0x00,
79 0x25, 0x01,
80 0x95, 0x10,
81 0x75, 0x01,
82 0x81, 0x02,
83 0x05, 0x01,
84 0x16, 0x01, 0xF8,
85 0x26, 0xFF, 0x07,
86 0x75, 0x0C,
87 0x95, 0x02,
88 0x09, 0x30,
89 0x09, 0x31,
90 0x81, 0x06,
91 0x15, 0x81,
92 0x25, 0x7F,
93 0x75, 0x08,
94 0x95, 0x01,
95 0x09, 0x38,
96 0x81, 0x06,
97 0x05, 0x0C,
98 0x0A, 0x38, 0x02,
99 0x95, 0x01,
100 0x81, 0x06,
101 0xC0,
102 0xC0,
103};
104
105
106static const char consumer_descriptor[] = {
107 0x05, 0x0C,
108 0x09, 0x01,
109 0xA1, 0x01,
110 0x85, 0x03,
111 0x75, 0x10,
112 0x95, 0x02,
113 0x15, 0x01,
114 0x26, 0x8C, 0x02,
115 0x19, 0x01,
116 0x2A, 0x8C, 0x02,
117 0x81, 0x00,
118 0xC0,
119};
120
121
122static const char syscontrol_descriptor[] = {
123 0x05, 0x01,
124 0x09, 0x80,
125 0xA1, 0x01,
126 0x85, 0x04,
127 0x75, 0x02,
128 0x95, 0x01,
129 0x15, 0x01,
130 0x25, 0x03,
131 0x09, 0x82,
132 0x09, 0x81,
133 0x09, 0x83,
134 0x81, 0x60,
135 0x75, 0x06,
136 0x81, 0x03,
137 0xC0,
138};
139
140
141static const char media_descriptor[] = {
142 0x06, 0xbc, 0xff,
143 0x09, 0x88,
144 0xa1, 0x01,
145 0x85, 0x08,
146 0x19, 0x01,
147 0x29, 0xff,
148 0x15, 0x01,
149 0x26, 0xff, 0x00,
150 0x75, 0x08,
151 0x95, 0x01,
152 0x81, 0x00,
153 0xc0,
154};
155
156
157#define MAX_REPORT_SIZE 8
158
159
160#define MAX_RDESC_SIZE \
161 (sizeof(kbd_descriptor) + \
162 sizeof(mse_descriptor) + \
163 sizeof(consumer_descriptor) + \
164 sizeof(syscontrol_descriptor) + \
165 sizeof(media_descriptor))
166
167
168
169
170
171
172
173
174
175
176
177
178
179#define NUMBER_OF_HID_REPORTS 32
180static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
181 [1] = 8,
182 [2] = 8,
183 [3] = 5,
184 [4] = 2,
185 [8] = 2,
186};
187
188
189#define LOGITECH_DJ_INTERFACE_NUMBER 0x02
190
191static struct hid_ll_driver logi_dj_ll_driver;
192
193static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
194 size_t count,
195 unsigned char report_type);
196static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
197
198static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
199 struct dj_report *dj_report)
200{
201
202 struct dj_device *dj_dev;
203 unsigned long flags;
204
205 spin_lock_irqsave(&djrcv_dev->lock, flags);
206 dj_dev = djrcv_dev->paired_dj_devices[dj_report->device_index];
207 djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
208 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
209
210 if (dj_dev != NULL) {
211 hid_destroy_device(dj_dev->hdev);
212 kfree(dj_dev);
213 } else {
214 dev_err(&djrcv_dev->hdev->dev, "%s: can't destroy a NULL device\n",
215 __func__);
216 }
217}
218
219static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
220 struct dj_report *dj_report)
221{
222
223 struct hid_device *djrcv_hdev = djrcv_dev->hdev;
224 struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
225 struct usb_device *usbdev = interface_to_usbdev(intf);
226 struct hid_device *dj_hiddev;
227 struct dj_device *dj_dev;
228
229
230
231
232 unsigned char tmpstr[3];
233
234 if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
235 SPFUNCTION_DEVICE_LIST_EMPTY) {
236 dbg_hid("%s: device list is empty\n", __func__);
237 djrcv_dev->querying_devices = false;
238 return;
239 }
240
241 if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
242 (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
243 dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n",
244 __func__, dj_report->device_index);
245 return;
246 }
247
248 if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
249
250 dbg_hid("%s: device is already known\n", __func__);
251 return;
252 }
253
254 dj_hiddev = hid_allocate_device();
255 if (IS_ERR(dj_hiddev)) {
256 dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
257 __func__);
258 return;
259 }
260
261 dj_hiddev->ll_driver = &logi_dj_ll_driver;
262 dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report;
263
264 dj_hiddev->dev.parent = &djrcv_hdev->dev;
265 dj_hiddev->bus = BUS_USB;
266 dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
267 dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct);
268 snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
269 "Logitech Unifying Device. Wireless PID:%02x%02x",
270 dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB],
271 dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]);
272
273 usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
274 snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
275 strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));
276
277 dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);
278
279 if (!dj_dev) {
280 dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n",
281 __func__);
282 goto dj_device_allocate_fail;
283 }
284
285 dj_dev->reports_supported = get_unaligned_le32(
286 dj_report->report_params + DEVICE_PAIRED_RF_REPORT_TYPE);
287 dj_dev->hdev = dj_hiddev;
288 dj_dev->dj_receiver_dev = djrcv_dev;
289 dj_dev->device_index = dj_report->device_index;
290 dj_hiddev->driver_data = dj_dev;
291
292 djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev;
293
294 if (hid_add_device(dj_hiddev)) {
295 dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
296 __func__);
297 goto hid_add_device_fail;
298 }
299
300 return;
301
302hid_add_device_fail:
303 djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
304 kfree(dj_dev);
305dj_device_allocate_fail:
306 hid_destroy_device(dj_hiddev);
307}
308
309static void delayedwork_callback(struct work_struct *work)
310{
311 struct dj_receiver_dev *djrcv_dev =
312 container_of(work, struct dj_receiver_dev, work);
313
314 struct dj_report dj_report;
315 unsigned long flags;
316 int count;
317 int retval;
318
319 dbg_hid("%s\n", __func__);
320
321 spin_lock_irqsave(&djrcv_dev->lock, flags);
322
323 count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report,
324 sizeof(struct dj_report));
325
326 if (count != sizeof(struct dj_report)) {
327 dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without "
328 "notifications available\n", __func__);
329 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
330 return;
331 }
332
333 if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) {
334 if (schedule_work(&djrcv_dev->work) == 0) {
335 dbg_hid("%s: did not schedule the work item, was "
336 "already queued\n", __func__);
337 }
338 }
339
340 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
341
342 switch (dj_report.report_type) {
343 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
344 logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report);
345 break;
346 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
347 logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
348 break;
349 default:
350
351
352
353
354
355
356
357 if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
358
359
360 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
361 if (!retval) {
362
363 break;
364 }
365 dev_err(&djrcv_dev->hdev->dev,
366 "%s:logi_dj_recv_query_paired_devices "
367 "error:%d\n", __func__, retval);
368 }
369 dbg_hid("%s: unexpected report type\n", __func__);
370 }
371}
372
373static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
374 struct dj_report *dj_report)
375{
376
377
378 kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
379
380 if (schedule_work(&djrcv_dev->work) == 0) {
381 dbg_hid("%s: did not schedule the work item, was already "
382 "queued\n", __func__);
383 }
384}
385
386static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
387 struct dj_report *dj_report)
388{
389
390 unsigned int i;
391 u8 reportbuffer[MAX_REPORT_SIZE];
392 struct dj_device *djdev;
393
394 djdev = djrcv_dev->paired_dj_devices[dj_report->device_index];
395
396 if (!djdev) {
397 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
398 " is NULL, index %d\n", dj_report->device_index);
399 kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
400
401 if (schedule_work(&djrcv_dev->work) == 0) {
402 dbg_hid("%s: did not schedule the work item, was already "
403 "queued\n", __func__);
404 }
405 return;
406 }
407
408 memset(reportbuffer, 0, sizeof(reportbuffer));
409
410 for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) {
411 if (djdev->reports_supported & (1 << i)) {
412 reportbuffer[0] = i;
413 if (hid_input_report(djdev->hdev,
414 HID_INPUT_REPORT,
415 reportbuffer,
416 hid_reportid_size_map[i], 1)) {
417 dbg_hid("hid_input_report error sending null "
418 "report\n");
419 }
420 }
421 }
422}
423
424static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
425 struct dj_report *dj_report)
426{
427
428 struct dj_device *dj_device;
429
430 dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index];
431
432 if (dj_device == NULL) {
433 dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
434 " is NULL, index %d\n", dj_report->device_index);
435 kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
436
437 if (schedule_work(&djrcv_dev->work) == 0) {
438 dbg_hid("%s: did not schedule the work item, was already "
439 "queued\n", __func__);
440 }
441 return;
442 }
443
444 if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) ||
445 (hid_reportid_size_map[dj_report->report_type] == 0)) {
446 dbg_hid("invalid report type:%x\n", dj_report->report_type);
447 return;
448 }
449
450 if (hid_input_report(dj_device->hdev,
451 HID_INPUT_REPORT, &dj_report->report_type,
452 hid_reportid_size_map[dj_report->report_type], 1)) {
453 dbg_hid("hid_input_report error\n");
454 }
455}
456
457
458static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
459 struct dj_report *dj_report)
460{
461 struct hid_device *hdev = djrcv_dev->hdev;
462 int sent_bytes;
463
464 if (!hdev->hid_output_raw_report) {
465 dev_err(&hdev->dev, "%s:"
466 "hid_output_raw_report is null\n", __func__);
467 return -ENODEV;
468 }
469
470 sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
471 sizeof(struct dj_report),
472 HID_OUTPUT_REPORT);
473
474 return (sent_bytes < 0) ? sent_bytes : 0;
475}
476
477static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
478{
479 struct dj_report *dj_report;
480 int retval;
481
482
483 if (djrcv_dev->querying_devices)
484 return 0;
485
486 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
487 if (!dj_report)
488 return -ENOMEM;
489 dj_report->report_id = REPORT_ID_DJ_SHORT;
490 dj_report->device_index = 0xFF;
491 dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
492 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
493 kfree(dj_report);
494 return retval;
495}
496
497
498static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
499 unsigned timeout)
500{
501 struct dj_report *dj_report;
502 int retval;
503
504 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
505 if (!dj_report)
506 return -ENOMEM;
507 dj_report->report_id = REPORT_ID_DJ_SHORT;
508 dj_report->device_index = 0xFF;
509 dj_report->report_type = REPORT_TYPE_CMD_SWITCH;
510 dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;
511 dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;
512 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
513 kfree(dj_report);
514 return retval;
515}
516
517
518static int logi_dj_ll_open(struct hid_device *hid)
519{
520 dbg_hid("%s:%s\n", __func__, hid->phys);
521 return 0;
522
523}
524
525static void logi_dj_ll_close(struct hid_device *hid)
526{
527 dbg_hid("%s:%s\n", __func__, hid->phys);
528}
529
530static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
531 size_t count,
532 unsigned char report_type)
533{
534
535 dbg_hid("%s\n", __func__);
536
537 return 0;
538}
539
540static void rdcat(char **rdesc, unsigned int *rsize, const char *data, unsigned int size)
541{
542 memcpy(*rdesc + *rsize, data, size);
543 *rsize += size;
544}
545
546static int logi_dj_ll_parse(struct hid_device *hid)
547{
548 struct dj_device *djdev = hid->driver_data;
549 unsigned int rsize = 0;
550 char *rdesc;
551 int retval;
552
553 dbg_hid("%s\n", __func__);
554
555 djdev->hdev->version = 0x0111;
556 djdev->hdev->country = 0x00;
557
558 rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL);
559 if (!rdesc)
560 return -ENOMEM;
561
562 if (djdev->reports_supported & STD_KEYBOARD) {
563 dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
564 __func__, djdev->reports_supported);
565 rdcat(&rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor));
566 }
567
568 if (djdev->reports_supported & STD_MOUSE) {
569 dbg_hid("%s: sending a mouse descriptor, reports_supported: "
570 "%x\n", __func__, djdev->reports_supported);
571 rdcat(&rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor));
572 }
573
574 if (djdev->reports_supported & MULTIMEDIA) {
575 dbg_hid("%s: sending a multimedia report descriptor: %x\n",
576 __func__, djdev->reports_supported);
577 rdcat(&rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor));
578 }
579
580 if (djdev->reports_supported & POWER_KEYS) {
581 dbg_hid("%s: sending a power keys report descriptor: %x\n",
582 __func__, djdev->reports_supported);
583 rdcat(&rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor));
584 }
585
586 if (djdev->reports_supported & MEDIA_CENTER) {
587 dbg_hid("%s: sending a media center report descriptor: %x\n",
588 __func__, djdev->reports_supported);
589 rdcat(&rdesc, &rsize, media_descriptor, sizeof(media_descriptor));
590 }
591
592 if (djdev->reports_supported & KBD_LEDS) {
593 dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
594 __func__, djdev->reports_supported);
595 }
596
597 retval = hid_parse_report(hid, rdesc, rsize);
598 kfree(rdesc);
599
600 return retval;
601}
602
603static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
604 unsigned int code, int value)
605{
606
607 struct hid_device *dj_hiddev = input_get_drvdata(dev);
608 struct dj_device *dj_dev = dj_hiddev->driver_data;
609
610 struct dj_receiver_dev *djrcv_dev =
611 dev_get_drvdata(dj_hiddev->dev.parent);
612 struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
613 struct hid_report_enum *output_report_enum;
614
615 struct hid_field *field;
616 struct hid_report *report;
617 unsigned char data[8];
618 int offset;
619
620 dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
621 __func__, dev->phys, type, code, value);
622
623 if (type != EV_LED)
624 return -1;
625
626 offset = hidinput_find_field(dj_hiddev, type, code, &field);
627
628 if (offset == -1) {
629 dev_warn(&dev->dev, "event field not found\n");
630 return -1;
631 }
632 hid_set_field(field, offset, value);
633 hid_output_report(field->report, &data[0]);
634
635 output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
636 report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
637 hid_set_field(report->field[0], 0, dj_dev->device_index);
638 hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
639 hid_set_field(report->field[0], 2, data[1]);
640
641 usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
642
643 return 0;
644
645}
646
647static int logi_dj_ll_start(struct hid_device *hid)
648{
649 dbg_hid("%s\n", __func__);
650 return 0;
651}
652
653static void logi_dj_ll_stop(struct hid_device *hid)
654{
655 dbg_hid("%s\n", __func__);
656}
657
658
659static struct hid_ll_driver logi_dj_ll_driver = {
660 .parse = logi_dj_ll_parse,
661 .start = logi_dj_ll_start,
662 .stop = logi_dj_ll_stop,
663 .open = logi_dj_ll_open,
664 .close = logi_dj_ll_close,
665 .hidinput_input_event = logi_dj_ll_input_event,
666};
667
668
669static int logi_dj_raw_event(struct hid_device *hdev,
670 struct hid_report *report, u8 *data,
671 int size)
672{
673 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
674 struct dj_report *dj_report = (struct dj_report *) data;
675 unsigned long flags;
676 bool report_processed = false;
677
678 dbg_hid("%s, size:%d\n", __func__, size);
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704 spin_lock_irqsave(&djrcv_dev->lock, flags);
705 if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
706 switch (dj_report->report_type) {
707 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
708 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
709 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
710 break;
711 case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
712 if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
713 STATUS_LINKLOSS) {
714 logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
715 }
716 break;
717 default:
718 logi_dj_recv_forward_report(djrcv_dev, dj_report);
719 }
720 report_processed = true;
721 }
722 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
723
724 return report_processed;
725}
726
727static int logi_dj_probe(struct hid_device *hdev,
728 const struct hid_device_id *id)
729{
730 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
731 struct dj_receiver_dev *djrcv_dev;
732 int retval;
733
734 if (is_dj_device((struct dj_device *)hdev->driver_data))
735 return -ENODEV;
736
737 dbg_hid("%s called for ifnum %d\n", __func__,
738 intf->cur_altsetting->desc.bInterfaceNumber);
739
740
741
742 if (intf->cur_altsetting->desc.bInterfaceNumber !=
743 LOGITECH_DJ_INTERFACE_NUMBER) {
744 dbg_hid("%s: ignoring ifnum %d\n", __func__,
745 intf->cur_altsetting->desc.bInterfaceNumber);
746 return -ENODEV;
747 }
748
749
750
751 djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
752 if (!djrcv_dev) {
753 dev_err(&hdev->dev,
754 "%s:failed allocating dj_receiver_dev\n", __func__);
755 return -ENOMEM;
756 }
757 djrcv_dev->hdev = hdev;
758 INIT_WORK(&djrcv_dev->work, delayedwork_callback);
759 spin_lock_init(&djrcv_dev->lock);
760 if (kfifo_alloc(&djrcv_dev->notif_fifo,
761 DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
762 GFP_KERNEL)) {
763 dev_err(&hdev->dev,
764 "%s:failed allocating notif_fifo\n", __func__);
765 kfree(djrcv_dev);
766 return -ENOMEM;
767 }
768 hid_set_drvdata(hdev, djrcv_dev);
769
770
771
772
773
774 retval = hid_parse(hdev);
775 if (retval) {
776 dev_err(&hdev->dev,
777 "%s:parse of interface 2 failed\n", __func__);
778 goto hid_parse_fail;
779 }
780
781
782
783 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
784 if (retval) {
785 dev_err(&hdev->dev,
786 "%s:hid_hw_start returned error\n", __func__);
787 goto hid_hw_start_fail;
788 }
789
790 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
791 if (retval < 0) {
792 dev_err(&hdev->dev,
793 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
794 __func__, retval);
795 goto switch_to_dj_mode_fail;
796 }
797
798
799 retval = hdev->ll_driver->open(hdev);
800 if (retval < 0) {
801 dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
802 "error:%d\n", __func__, retval);
803 goto llopen_failed;
804 }
805
806 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
807 if (retval < 0) {
808 dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
809 "error:%d\n", __func__, retval);
810 goto logi_dj_recv_query_paired_devices_failed;
811 }
812
813 return retval;
814
815logi_dj_recv_query_paired_devices_failed:
816 hdev->ll_driver->close(hdev);
817
818llopen_failed:
819switch_to_dj_mode_fail:
820 hid_hw_stop(hdev);
821
822hid_hw_start_fail:
823hid_parse_fail:
824 kfifo_free(&djrcv_dev->notif_fifo);
825 kfree(djrcv_dev);
826 hid_set_drvdata(hdev, NULL);
827 return retval;
828
829}
830
831#ifdef CONFIG_PM
832static int logi_dj_reset_resume(struct hid_device *hdev)
833{
834 int retval;
835 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
836
837 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
838 if (retval < 0) {
839 dev_err(&hdev->dev,
840 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
841 __func__, retval);
842 }
843
844 return 0;
845}
846#endif
847
848static void logi_dj_remove(struct hid_device *hdev)
849{
850 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
851 struct dj_device *dj_dev;
852 int i;
853
854 dbg_hid("%s\n", __func__);
855
856 cancel_work_sync(&djrcv_dev->work);
857
858 hdev->ll_driver->close(hdev);
859 hid_hw_stop(hdev);
860
861
862
863
864
865
866 for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
867 dj_dev = djrcv_dev->paired_dj_devices[i];
868 if (dj_dev != NULL) {
869 hid_destroy_device(dj_dev->hdev);
870 kfree(dj_dev);
871 djrcv_dev->paired_dj_devices[i] = NULL;
872 }
873 }
874
875 kfifo_free(&djrcv_dev->notif_fifo);
876 kfree(djrcv_dev);
877 hid_set_drvdata(hdev, NULL);
878}
879
880static int logi_djdevice_probe(struct hid_device *hdev,
881 const struct hid_device_id *id)
882{
883 int ret;
884 struct dj_device *dj_dev = hdev->driver_data;
885
886 if (!is_dj_device(dj_dev))
887 return -ENODEV;
888
889 ret = hid_parse(hdev);
890 if (!ret)
891 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
892
893 return ret;
894}
895
896static const struct hid_device_id logi_dj_receivers[] = {
897 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
898 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
899 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
900 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
901 {}
902};
903
904MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
905
906static struct hid_driver logi_djreceiver_driver = {
907 .name = "logitech-djreceiver",
908 .id_table = logi_dj_receivers,
909 .probe = logi_dj_probe,
910 .remove = logi_dj_remove,
911 .raw_event = logi_dj_raw_event,
912#ifdef CONFIG_PM
913 .reset_resume = logi_dj_reset_resume,
914#endif
915};
916
917
918static const struct hid_device_id logi_dj_devices[] = {
919 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
920 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
921 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
922 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
923 {}
924};
925
926static struct hid_driver logi_djdevice_driver = {
927 .name = "logitech-djdevice",
928 .id_table = logi_dj_devices,
929 .probe = logi_djdevice_probe,
930};
931
932
933static int __init logi_dj_init(void)
934{
935 int retval;
936
937 dbg_hid("Logitech-DJ:%s\n", __func__);
938
939 retval = hid_register_driver(&logi_djreceiver_driver);
940 if (retval)
941 return retval;
942
943 retval = hid_register_driver(&logi_djdevice_driver);
944 if (retval)
945 hid_unregister_driver(&logi_djreceiver_driver);
946
947 return retval;
948
949}
950
951static void __exit logi_dj_exit(void)
952{
953 dbg_hid("Logitech-DJ:%s\n", __func__);
954
955 hid_unregister_driver(&logi_djdevice_driver);
956 hid_unregister_driver(&logi_djreceiver_driver);
957
958}
959
960module_init(logi_dj_init);
961module_exit(logi_dj_exit);
962MODULE_LICENSE("GPL");
963MODULE_AUTHOR("Logitech");
964MODULE_AUTHOR("Nestor Lopez Casado");
965MODULE_AUTHOR("nlopezcasad@logitech.com");
966