diff options
author | Frank Praznik <frank.praznik@oh.rr.com> | 2014-01-22 13:49:44 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-01-29 08:23:43 -0500 |
commit | 0a7f364e812285246cd617a51194a3f8bd0e8daa (patch) | |
tree | 018f78b306e0b46a2a94f1df5a737fa4b23b0032 /net/bluetooth/hidp | |
parent | 596cfdd80ab8ad11c750511da2c8c9a33f188ba0 (diff) |
HID: Add the transport-driver functions to the HIDP driver.
Add raw_request, set_raw_report and output_report transport-driver functions to
the HIDP driver.
Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
Acked-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'net/bluetooth/hidp')
-rw-r--r-- | net/bluetooth/hidp/core.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 292e619db896..b062cee3f319 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -353,6 +353,71 @@ err: | |||
353 | return ret; | 353 | return ret; |
354 | } | 354 | } |
355 | 355 | ||
356 | static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum, | ||
357 | unsigned char *data, size_t count, | ||
358 | unsigned char report_type) | ||
359 | { | ||
360 | struct hidp_session *session = hid->driver_data; | ||
361 | int ret; | ||
362 | |||
363 | switch (report_type) { | ||
364 | case HID_FEATURE_REPORT: | ||
365 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; | ||
366 | break; | ||
367 | case HID_INPUT_REPORT: | ||
368 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_INPUT; | ||
369 | break; | ||
370 | case HID_OUTPUT_REPORT: | ||
371 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT; | ||
372 | break; | ||
373 | default: | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | |||
377 | if (mutex_lock_interruptible(&session->report_mutex)) | ||
378 | return -ERESTARTSYS; | ||
379 | |||
380 | /* Set up our wait, and send the report request to the device. */ | ||
381 | data[0] = reportnum; | ||
382 | set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); | ||
383 | ret = hidp_send_ctrl_message(session, report_type, data, count); | ||
384 | if (ret) | ||
385 | goto err; | ||
386 | |||
387 | /* Wait for the ACK from the device. */ | ||
388 | while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) && | ||
389 | !atomic_read(&session->terminate)) { | ||
390 | int res; | ||
391 | |||
392 | res = wait_event_interruptible_timeout(session->report_queue, | ||
393 | !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) | ||
394 | || atomic_read(&session->terminate), | ||
395 | 10*HZ); | ||
396 | if (res == 0) { | ||
397 | /* timeout */ | ||
398 | ret = -EIO; | ||
399 | goto err; | ||
400 | } | ||
401 | if (res < 0) { | ||
402 | /* signal */ | ||
403 | ret = -ERESTARTSYS; | ||
404 | goto err; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | if (!session->output_report_success) { | ||
409 | ret = -EIO; | ||
410 | goto err; | ||
411 | } | ||
412 | |||
413 | ret = count; | ||
414 | |||
415 | err: | ||
416 | clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); | ||
417 | mutex_unlock(&session->report_mutex); | ||
418 | return ret; | ||
419 | } | ||
420 | |||
356 | static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, | 421 | static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, |
357 | unsigned char report_type) | 422 | unsigned char report_type) |
358 | { | 423 | { |
@@ -411,6 +476,29 @@ err: | |||
411 | return ret; | 476 | return ret; |
412 | } | 477 | } |
413 | 478 | ||
479 | static int hidp_raw_request(struct hid_device *hid, unsigned char reportnum, | ||
480 | __u8 *buf, size_t len, unsigned char rtype, | ||
481 | int reqtype) | ||
482 | { | ||
483 | switch (reqtype) { | ||
484 | case HID_REQ_GET_REPORT: | ||
485 | return hidp_get_raw_report(hid, reportnum, buf, len, rtype); | ||
486 | case HID_REQ_SET_REPORT: | ||
487 | return hidp_set_raw_report(hid, reportnum, buf, len, rtype); | ||
488 | default: | ||
489 | return -EIO; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | static int hidp_output_report(struct hid_device *hid, __u8 *data, size_t count) | ||
494 | { | ||
495 | struct hidp_session *session = hid->driver_data; | ||
496 | |||
497 | return hidp_send_intr_message(session, | ||
498 | HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT, | ||
499 | data, count); | ||
500 | } | ||
501 | |||
414 | static void hidp_idle_timeout(unsigned long arg) | 502 | static void hidp_idle_timeout(unsigned long arg) |
415 | { | 503 | { |
416 | struct hidp_session *session = (struct hidp_session *) arg; | 504 | struct hidp_session *session = (struct hidp_session *) arg; |
@@ -727,6 +815,8 @@ static struct hid_ll_driver hidp_hid_driver = { | |||
727 | .stop = hidp_stop, | 815 | .stop = hidp_stop, |
728 | .open = hidp_open, | 816 | .open = hidp_open, |
729 | .close = hidp_close, | 817 | .close = hidp_close, |
818 | .raw_request = hidp_raw_request, | ||
819 | .output_report = hidp_output_report, | ||
730 | .hidinput_input_event = hidp_hidinput_event, | 820 | .hidinput_input_event = hidp_hidinput_event, |
731 | }; | 821 | }; |
732 | 822 | ||