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