diff options
| -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 | ||
