diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 12:56:24 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 12:56:24 -0400 |
| commit | ee5f68e6c2f183e6aade0e9c57af13d5eff44f2f (patch) | |
| tree | de4132918ec7b033c4981e2ba4aea9027816bdb9 /net/bluetooth/hidp | |
| parent | f74346a04b79c9a5e50a2ee5e923b94195975d17 (diff) | |
| parent | 0a7f364e812285246cd617a51194a3f8bd0e8daa (diff) | |
Merge branch 'for-3.15/ll-driver-new-callbacks' into for-linus
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 d9fb93451442..450a0b999614 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; |
| @@ -739,6 +827,8 @@ static struct hid_ll_driver hidp_hid_driver = { | |||
| 739 | .stop = hidp_stop, | 827 | .stop = hidp_stop, |
| 740 | .open = hidp_open, | 828 | .open = hidp_open, |
| 741 | .close = hidp_close, | 829 | .close = hidp_close, |
| 830 | .raw_request = hidp_raw_request, | ||
| 831 | .output_report = hidp_output_report, | ||
| 742 | .hidinput_input_event = hidp_hidinput_event, | 832 | .hidinput_input_event = hidp_hidinput_event, |
| 743 | }; | 833 | }; |
| 744 | 834 | ||
