diff options
author | Jiri Kosina <jkosina@suse.cz> | 2013-09-04 04:49:39 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-09-04 04:49:57 -0400 |
commit | efd15f5f4ff63f6ac5d80850686e3d2cc8c4481b (patch) | |
tree | 40024adbe77a3d660662e639fd765097133d648c /drivers/hid/hid-logitech-dj.c | |
parent | 6c2794a2984f4c17a58117a68703cc7640f01c5a (diff) | |
parent | 58c59bc997d86593f0bea41845885917cf304d22 (diff) |
Merge branch 'master' into for-3.12/upstream
Sync with Linus' tree to be able to apply fixup patch on top
of 9d9a04ee75 ("HID: apple: Add support for the 2013 Macbook Air")
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-logitech-dj.c')
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index d318222c6315..d0e5963c1ba1 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
@@ -192,6 +192,7 @@ static struct hid_ll_driver logi_dj_ll_driver; | |||
192 | static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, | 192 | static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, |
193 | size_t count, | 193 | size_t count, |
194 | unsigned char report_type); | 194 | unsigned char report_type); |
195 | static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); | ||
195 | 196 | ||
196 | static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, | 197 | static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, |
197 | struct dj_report *dj_report) | 198 | struct dj_report *dj_report) |
@@ -232,6 +233,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, | |||
232 | if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & | 233 | if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & |
233 | SPFUNCTION_DEVICE_LIST_EMPTY) { | 234 | SPFUNCTION_DEVICE_LIST_EMPTY) { |
234 | dbg_hid("%s: device list is empty\n", __func__); | 235 | dbg_hid("%s: device list is empty\n", __func__); |
236 | djrcv_dev->querying_devices = false; | ||
235 | return; | 237 | return; |
236 | } | 238 | } |
237 | 239 | ||
@@ -242,6 +244,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, | |||
242 | return; | 244 | return; |
243 | } | 245 | } |
244 | 246 | ||
247 | if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { | ||
248 | /* The device is already known. No need to reallocate it. */ | ||
249 | dbg_hid("%s: device is already known\n", __func__); | ||
250 | return; | ||
251 | } | ||
252 | |||
245 | dj_hiddev = hid_allocate_device(); | 253 | dj_hiddev = hid_allocate_device(); |
246 | if (IS_ERR(dj_hiddev)) { | 254 | if (IS_ERR(dj_hiddev)) { |
247 | dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", | 255 | dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", |
@@ -305,6 +313,7 @@ static void delayedwork_callback(struct work_struct *work) | |||
305 | struct dj_report dj_report; | 313 | struct dj_report dj_report; |
306 | unsigned long flags; | 314 | unsigned long flags; |
307 | int count; | 315 | int count; |
316 | int retval; | ||
308 | 317 | ||
309 | dbg_hid("%s\n", __func__); | 318 | dbg_hid("%s\n", __func__); |
310 | 319 | ||
@@ -337,6 +346,25 @@ static void delayedwork_callback(struct work_struct *work) | |||
337 | logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); | 346 | logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); |
338 | break; | 347 | break; |
339 | default: | 348 | default: |
349 | /* A normal report (i. e. not belonging to a pair/unpair notification) | ||
350 | * arriving here, means that the report arrived but we did not have a | ||
351 | * paired dj_device associated to the report's device_index, this | ||
352 | * means that the original "device paired" notification corresponding | ||
353 | * to this dj_device never arrived to this driver. The reason is that | ||
354 | * hid-core discards all packets coming from a device while probe() is | ||
355 | * executing. */ | ||
356 | if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { | ||
357 | /* ok, we don't know the device, just re-ask the | ||
358 | * receiver for the list of connected devices. */ | ||
359 | retval = logi_dj_recv_query_paired_devices(djrcv_dev); | ||
360 | if (!retval) { | ||
361 | /* everything went fine, so just leave */ | ||
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 | } | ||
340 | dbg_hid("%s: unexpected report type\n", __func__); | 368 | dbg_hid("%s: unexpected report type\n", __func__); |
341 | } | 369 | } |
342 | } | 370 | } |
@@ -367,6 +395,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, | |||
367 | if (!djdev) { | 395 | if (!djdev) { |
368 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" | 396 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" |
369 | " is NULL, index %d\n", 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 | } | ||
370 | return; | 404 | return; |
371 | } | 405 | } |
372 | 406 | ||
@@ -397,6 +431,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, | |||
397 | if (dj_device == NULL) { | 431 | if (dj_device == NULL) { |
398 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" | 432 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" |
399 | " is NULL, index %d\n", 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 | } | ||
400 | return; | 440 | return; |
401 | } | 441 | } |
402 | 442 | ||
@@ -444,6 +484,10 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) | |||
444 | struct dj_report *dj_report; | 484 | struct dj_report *dj_report; |
445 | int retval; | 485 | int retval; |
446 | 486 | ||
487 | /* no need to protect djrcv_dev->querying_devices */ | ||
488 | if (djrcv_dev->querying_devices) | ||
489 | return 0; | ||
490 | |||
447 | dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); | 491 | dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); |
448 | if (!dj_report) | 492 | if (!dj_report) |
449 | return -ENOMEM; | 493 | return -ENOMEM; |
@@ -455,6 +499,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) | |||
455 | return retval; | 499 | return retval; |
456 | } | 500 | } |
457 | 501 | ||
502 | |||
458 | static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, | 503 | static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, |
459 | unsigned timeout) | 504 | unsigned timeout) |
460 | { | 505 | { |