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 struct hid_report *report;
463 struct hid_report_enum *output_report_enum;
464 u8 *data = (u8 *)(&dj_report->device_index);
465 int i;
466
467 output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
468 report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
469
470 if (!report) {
471 dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__);
472 return -ENODEV;
473 }
474
475 for (i = 0; i < report->field[0]->report_count; i++)
476 report->field[0]->value[i] = data[i];
477
478 usbhid_submit_report(hdev, report, USB_DIR_OUT);
479
480 return 0;
481}
482
483static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
484{
485 struct dj_report *dj_report;
486 int retval;
487
488
489 if (djrcv_dev->querying_devices)
490 return 0;
491
492 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
493 if (!dj_report)
494 return -ENOMEM;
495 dj_report->report_id = REPORT_ID_DJ_SHORT;
496 dj_report->device_index = 0xFF;
497 dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
498 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
499 kfree(dj_report);
500 return retval;
501}
502
503
504static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
505 unsigned timeout)
506{
507 struct dj_report *dj_report;
508 int retval;
509
510 dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
511 if (!dj_report)
512 return -ENOMEM;
513 dj_report->report_id = REPORT_ID_DJ_SHORT;
514 dj_report->device_index = 0xFF;
515 dj_report->report_type = REPORT_TYPE_CMD_SWITCH;
516 dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F;
517 dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;
518 retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
519 kfree(dj_report);
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_output_hidraw_report(struct hid_device *hid, u8 * buf,
537 size_t count,
538 unsigned char report_type)
539{
540
541 dbg_hid("%s\n", __func__);
542
543 return 0;
544}
545
546static void rdcat(char **rdesc, unsigned int *rsize, const char *data, unsigned int size)
547{
548 memcpy(*rdesc + *rsize, data, size);
549 *rsize += size;
550}
551
552static int logi_dj_ll_parse(struct hid_device *hid)
553{
554 struct dj_device *djdev = hid->driver_data;
555 unsigned int rsize = 0;
556 char *rdesc;
557 int retval;
558
559 dbg_hid("%s\n", __func__);
560
561 djdev->hdev->version = 0x0111;
562 djdev->hdev->country = 0x00;
563
564 rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL);
565 if (!rdesc)
566 return -ENOMEM;
567
568 if (djdev->reports_supported & STD_KEYBOARD) {
569 dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
570 __func__, djdev->reports_supported);
571 rdcat(&rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor));
572 }
573
574 if (djdev->reports_supported & STD_MOUSE) {
575 dbg_hid("%s: sending a mouse descriptor, reports_supported: "
576 "%x\n", __func__, djdev->reports_supported);
577 rdcat(&rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor));
578 }
579
580 if (djdev->reports_supported & MULTIMEDIA) {
581 dbg_hid("%s: sending a multimedia report descriptor: %x\n",
582 __func__, djdev->reports_supported);
583 rdcat(&rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor));
584 }
585
586 if (djdev->reports_supported & POWER_KEYS) {
587 dbg_hid("%s: sending a power keys report descriptor: %x\n",
588 __func__, djdev->reports_supported);
589 rdcat(&rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor));
590 }
591
592 if (djdev->reports_supported & MEDIA_CENTER) {
593 dbg_hid("%s: sending a media center report descriptor: %x\n",
594 __func__, djdev->reports_supported);
595 rdcat(&rdesc, &rsize, media_descriptor, sizeof(media_descriptor));
596 }
597
598 if (djdev->reports_supported & KBD_LEDS) {
599 dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
600 __func__, djdev->reports_supported);
601 }
602
603 retval = hid_parse_report(hid, rdesc, rsize);
604 kfree(rdesc);
605
606 return retval;
607}
608
609static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
610 unsigned int code, int value)
611{
612
613 struct hid_device *dj_hiddev = input_get_drvdata(dev);
614 struct dj_device *dj_dev = dj_hiddev->driver_data;
615
616 struct dj_receiver_dev *djrcv_dev =
617 dev_get_drvdata(dj_hiddev->dev.parent);
618 struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
619 struct hid_report_enum *output_report_enum;
620
621 struct hid_field *field;
622 struct hid_report *report;
623 unsigned char data[8];
624 int offset;
625
626 dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
627 __func__, dev->phys, type, code, value);
628
629 if (type != EV_LED)
630 return -1;
631
632 offset = hidinput_find_field(dj_hiddev, type, code, &field);
633
634 if (offset == -1) {
635 dev_warn(&dev->dev, "event field not found\n");
636 return -1;
637 }
638 hid_set_field(field, offset, value);
639 hid_output_report(field->report, &data[0]);
640
641 output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
642 report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
643 hid_set_field(report->field[0], 0, dj_dev->device_index);
644 hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
645 hid_set_field(report->field[0], 2, data[1]);
646
647 usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
648
649 return 0;
650
651}
652
653static int logi_dj_ll_start(struct hid_device *hid)
654{
655 dbg_hid("%s\n", __func__);
656 return 0;
657}
658
659static void logi_dj_ll_stop(struct hid_device *hid)
660{
661 dbg_hid("%s\n", __func__);
662}
663
664
665static struct hid_ll_driver logi_dj_ll_driver = {
666 .parse = logi_dj_ll_parse,
667 .start = logi_dj_ll_start,
668 .stop = logi_dj_ll_stop,
669 .open = logi_dj_ll_open,
670 .close = logi_dj_ll_close,
671 .hidinput_input_event = logi_dj_ll_input_event,
672};
673
674
675static int logi_dj_raw_event(struct hid_device *hdev,
676 struct hid_report *report, u8 *data,
677 int size)
678{
679 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
680 struct dj_report *dj_report = (struct dj_report *) data;
681 unsigned long flags;
682 bool report_processed = false;
683
684 dbg_hid("%s, size:%d\n", __func__, size);
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710 spin_lock_irqsave(&djrcv_dev->lock, flags);
711 if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
712 switch (dj_report->report_type) {
713 case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
714 case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
715 logi_dj_recv_queue_notification(djrcv_dev, dj_report);
716 break;
717 case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
718 if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
719 STATUS_LINKLOSS) {
720 logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
721 }
722 break;
723 default:
724 logi_dj_recv_forward_report(djrcv_dev, dj_report);
725 }
726 report_processed = true;
727 }
728 spin_unlock_irqrestore(&djrcv_dev->lock, flags);
729
730 return report_processed;
731}
732
733static int logi_dj_probe(struct hid_device *hdev,
734 const struct hid_device_id *id)
735{
736 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
737 struct dj_receiver_dev *djrcv_dev;
738 int retval;
739
740 if (is_dj_device((struct dj_device *)hdev->driver_data))
741 return -ENODEV;
742
743 dbg_hid("%s called for ifnum %d\n", __func__,
744 intf->cur_altsetting->desc.bInterfaceNumber);
745
746
747
748 if (intf->cur_altsetting->desc.bInterfaceNumber !=
749 LOGITECH_DJ_INTERFACE_NUMBER) {
750 dbg_hid("%s: ignoring ifnum %d\n", __func__,
751 intf->cur_altsetting->desc.bInterfaceNumber);
752 return -ENODEV;
753 }
754
755
756
757 djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
758 if (!djrcv_dev) {
759 dev_err(&hdev->dev,
760 "%s:failed allocating dj_receiver_dev\n", __func__);
761 return -ENOMEM;
762 }
763 djrcv_dev->hdev = hdev;
764 INIT_WORK(&djrcv_dev->work, delayedwork_callback);
765 spin_lock_init(&djrcv_dev->lock);
766 if (kfifo_alloc(&djrcv_dev->notif_fifo,
767 DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
768 GFP_KERNEL)) {
769 dev_err(&hdev->dev,
770 "%s:failed allocating notif_fifo\n", __func__);
771 kfree(djrcv_dev);
772 return -ENOMEM;
773 }
774 hid_set_drvdata(hdev, djrcv_dev);
775
776
777
778
779
780 retval = hid_parse(hdev);
781 if (retval) {
782 dev_err(&hdev->dev,
783 "%s:parse of interface 2 failed\n", __func__);
784 goto hid_parse_fail;
785 }
786
787
788
789 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
790 if (retval) {
791 dev_err(&hdev->dev,
792 "%s:hid_hw_start returned error\n", __func__);
793 goto hid_hw_start_fail;
794 }
795
796 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
797 if (retval < 0) {
798 dev_err(&hdev->dev,
799 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
800 __func__, retval);
801 goto switch_to_dj_mode_fail;
802 }
803
804
805 retval = hdev->ll_driver->open(hdev);
806 if (retval < 0) {
807 dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
808 "error:%d\n", __func__, retval);
809 goto llopen_failed;
810 }
811
812 retval = logi_dj_recv_query_paired_devices(djrcv_dev);
813 if (retval < 0) {
814 dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
815 "error:%d\n", __func__, retval);
816 goto logi_dj_recv_query_paired_devices_failed;
817 }
818
819 return retval;
820
821logi_dj_recv_query_paired_devices_failed:
822 hdev->ll_driver->close(hdev);
823
824llopen_failed:
825switch_to_dj_mode_fail:
826 hid_hw_stop(hdev);
827
828hid_hw_start_fail:
829hid_parse_fail:
830 kfifo_free(&djrcv_dev->notif_fifo);
831 kfree(djrcv_dev);
832 hid_set_drvdata(hdev, NULL);
833 return retval;
834
835}
836
837#ifdef CONFIG_PM
838static int logi_dj_reset_resume(struct hid_device *hdev)
839{
840 int retval;
841 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
842
843 retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
844 if (retval < 0) {
845 dev_err(&hdev->dev,
846 "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
847 __func__, retval);
848 }
849
850 return 0;
851}
852#endif
853
854static void logi_dj_remove(struct hid_device *hdev)
855{
856 struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
857 struct dj_device *dj_dev;
858 int i;
859
860 dbg_hid("%s\n", __func__);
861
862 cancel_work_sync(&djrcv_dev->work);
863
864 hdev->ll_driver->close(hdev);
865 hid_hw_stop(hdev);
866
867
868
869
870
871
872 for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
873 dj_dev = djrcv_dev->paired_dj_devices[i];
874 if (dj_dev != NULL) {
875 hid_destroy_device(dj_dev->hdev);
876 kfree(dj_dev);
877 djrcv_dev->paired_dj_devices[i] = NULL;
878 }
879 }
880
881 kfifo_free(&djrcv_dev->notif_fifo);
882 kfree(djrcv_dev);
883 hid_set_drvdata(hdev, NULL);
884}
885
886static int logi_djdevice_probe(struct hid_device *hdev,
887 const struct hid_device_id *id)
888{
889 int ret;
890 struct dj_device *dj_dev = hdev->driver_data;
891
892 if (!is_dj_device(dj_dev))
893 return -ENODEV;
894
895 ret = hid_parse(hdev);
896 if (!ret)
897 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
898
899 return ret;
900}
901
902static const struct hid_device_id logi_dj_receivers[] = {
903 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
904 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
905 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
906 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
907 {}
908};
909
910MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
911
912static struct hid_driver logi_djreceiver_driver = {
913 .name = "logitech-djreceiver",
914 .id_table = logi_dj_receivers,
915 .probe = logi_dj_probe,
916 .remove = logi_dj_remove,
917 .raw_event = logi_dj_raw_event,
918#ifdef CONFIG_PM
919 .reset_resume = logi_dj_reset_resume,
920#endif
921};
922
923
924static const struct hid_device_id logi_dj_devices[] = {
925 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
926 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
927 {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
928 USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
929 {}
930};
931
932static struct hid_driver logi_djdevice_driver = {
933 .name = "logitech-djdevice",
934 .id_table = logi_dj_devices,
935 .probe = logi_djdevice_probe,
936};
937
938
939static int __init logi_dj_init(void)
940{
941 int retval;
942
943 dbg_hid("Logitech-DJ:%s\n", __func__);
944
945 retval = hid_register_driver(&logi_djreceiver_driver);
946 if (retval)
947 return retval;
948
949 retval = hid_register_driver(&logi_djdevice_driver);
950 if (retval)
951 hid_unregister_driver(&logi_djreceiver_driver);
952
953 return retval;
954
955}
956
957static void __exit logi_dj_exit(void)
958{
959 dbg_hid("Logitech-DJ:%s\n", __func__);
960
961 hid_unregister_driver(&logi_djdevice_driver);
962 hid_unregister_driver(&logi_djreceiver_driver);
963
964}
965
966module_init(logi_dj_init);
967module_exit(logi_dj_exit);
968MODULE_LICENSE("GPL");
969MODULE_AUTHOR("Logitech");
970MODULE_AUTHOR("Nestor Lopez Casado");
971MODULE_AUTHOR("nlopezcasad@logitech.com");
972