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