Loading drivers/hid/hid-logitech-dj.c +47 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, size_t count, unsigned char report_type); static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) Loading Loading @@ -232,6 +233,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & SPFUNCTION_DEVICE_LIST_EMPTY) { dbg_hid("%s: device list is empty\n", __func__); djrcv_dev->querying_devices = false; return; } Loading @@ -242,6 +244,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; } if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { /* The device is already known. No need to reallocate it. */ dbg_hid("%s: device is already known\n", __func__); return; } dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", Loading Loading @@ -305,6 +313,7 @@ static void delayedwork_callback(struct work_struct *work) struct dj_report dj_report; unsigned long flags; int count; int retval; dbg_hid("%s\n", __func__); Loading Loading @@ -337,6 +346,25 @@ static void delayedwork_callback(struct work_struct *work) logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); break; default: /* A normal report (i. e. not belonging to a pair/unpair notification) * arriving here, means that the report arrived but we did not have a * paired dj_device associated to the report's device_index, this * means that the original "device paired" notification corresponding * to this dj_device never arrived to this driver. The reason is that * hid-core discards all packets coming from a device while probe() is * executing. */ if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { /* ok, we don't know the device, just re-ask the * receiver for the list of connected devices. */ retval = logi_dj_recv_query_paired_devices(djrcv_dev); if (!retval) { /* everything went fine, so just leave */ break; } dev_err(&djrcv_dev->hdev->dev, "%s:logi_dj_recv_query_paired_devices " "error:%d\n", __func__, retval); } dbg_hid("%s: unexpected report type\n", __func__); } } Loading Loading @@ -367,6 +395,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, if (!djdev) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); if (schedule_work(&djrcv_dev->work) == 0) { dbg_hid("%s: did not schedule the work item, was already " "queued\n", __func__); } return; } Loading Loading @@ -397,6 +431,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, if (dj_device == NULL) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); if (schedule_work(&djrcv_dev->work) == 0) { dbg_hid("%s: did not schedule the work item, was already " "queued\n", __func__); } return; } Loading Loading @@ -444,6 +484,12 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; /* no need to protect djrcv_dev->querying_devices */ if (djrcv_dev->querying_devices) return 0; djrcv_dev->querying_devices = true; dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; Loading @@ -455,6 +501,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) return retval; } static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, unsigned timeout) { Loading drivers/hid/hid-logitech-dj.h +1 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,7 @@ struct dj_receiver_dev { struct work_struct work; struct kfifo notif_fifo; spinlock_t lock; bool querying_devices; }; struct dj_device { Loading Loading
drivers/hid/hid-logitech-dj.c +47 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, size_t count, unsigned char report_type); static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) Loading Loading @@ -232,6 +233,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & SPFUNCTION_DEVICE_LIST_EMPTY) { dbg_hid("%s: device list is empty\n", __func__); djrcv_dev->querying_devices = false; return; } Loading @@ -242,6 +244,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; } if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { /* The device is already known. No need to reallocate it. */ dbg_hid("%s: device is already known\n", __func__); return; } dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", Loading Loading @@ -305,6 +313,7 @@ static void delayedwork_callback(struct work_struct *work) struct dj_report dj_report; unsigned long flags; int count; int retval; dbg_hid("%s\n", __func__); Loading Loading @@ -337,6 +346,25 @@ static void delayedwork_callback(struct work_struct *work) logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); break; default: /* A normal report (i. e. not belonging to a pair/unpair notification) * arriving here, means that the report arrived but we did not have a * paired dj_device associated to the report's device_index, this * means that the original "device paired" notification corresponding * to this dj_device never arrived to this driver. The reason is that * hid-core discards all packets coming from a device while probe() is * executing. */ if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { /* ok, we don't know the device, just re-ask the * receiver for the list of connected devices. */ retval = logi_dj_recv_query_paired_devices(djrcv_dev); if (!retval) { /* everything went fine, so just leave */ break; } dev_err(&djrcv_dev->hdev->dev, "%s:logi_dj_recv_query_paired_devices " "error:%d\n", __func__, retval); } dbg_hid("%s: unexpected report type\n", __func__); } } Loading Loading @@ -367,6 +395,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, if (!djdev) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); if (schedule_work(&djrcv_dev->work) == 0) { dbg_hid("%s: did not schedule the work item, was already " "queued\n", __func__); } return; } Loading Loading @@ -397,6 +431,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, if (dj_device == NULL) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); if (schedule_work(&djrcv_dev->work) == 0) { dbg_hid("%s: did not schedule the work item, was already " "queued\n", __func__); } return; } Loading Loading @@ -444,6 +484,12 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; /* no need to protect djrcv_dev->querying_devices */ if (djrcv_dev->querying_devices) return 0; djrcv_dev->querying_devices = true; dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; Loading @@ -455,6 +501,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) return retval; } static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, unsigned timeout) { Loading
drivers/hid/hid-logitech-dj.h +1 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,7 @@ struct dj_receiver_dev { struct work_struct work; struct kfifo notif_fifo; spinlock_t lock; bool querying_devices; }; struct dj_device { Loading