aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hidp/core.c197
-rw-r--r--net/bluetooth/hidp/hidp.h15
2 files changed, 196 insertions, 16 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 29544c21f4b5..3c036b0933c1 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -36,6 +36,7 @@
36#include <linux/file.h> 36#include <linux/file.h>
37#include <linux/init.h> 37#include <linux/init.h>
38#include <linux/wait.h> 38#include <linux/wait.h>
39#include <linux/mutex.h>
39#include <net/sock.h> 40#include <net/sock.h>
40 41
41#include <linux/input.h> 42#include <linux/input.h>
@@ -313,24 +314,144 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
313 return hidp_queue_report(session, buf, rsize); 314 return hidp_queue_report(session, buf, rsize);
314} 315}
315 316
317static int hidp_get_raw_report(struct hid_device *hid,
318 unsigned char report_number,
319 unsigned char *data, size_t count,
320 unsigned char report_type)
321{
322 struct hidp_session *session = hid->driver_data;
323 struct sk_buff *skb;
324 size_t len;
325 int numbered_reports = hid->report_enum[report_type].numbered;
326
327 switch (report_type) {
328 case HID_FEATURE_REPORT:
329 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
330 break;
331 case HID_INPUT_REPORT:
332 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
333 break;
334 case HID_OUTPUT_REPORT:
335 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
336 break;
337 default:
338 return -EINVAL;
339 }
340
341 if (mutex_lock_interruptible(&session->report_mutex))
342 return -ERESTARTSYS;
343
344 /* Set up our wait, and send the report request to the device. */
345 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
346 session->waiting_report_number = numbered_reports ? report_number : -1;
347 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
348 data[0] = report_number;
349 if (hidp_send_ctrl_message(hid->driver_data, report_type, data, 1))
350 goto err_eio;
351
352 /* Wait for the return of the report. The returned report
353 gets put in session->report_return. */
354 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
355 int res;
356
357 res = wait_event_interruptible_timeout(session->report_queue,
358 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
359 5*HZ);
360 if (res == 0) {
361 /* timeout */
362 goto err_eio;
363 }
364 if (res < 0) {
365 /* signal */
366 goto err_restartsys;
367 }
368 }
369
370 skb = session->report_return;
371 if (skb) {
372 len = skb->len < count ? skb->len : count;
373 memcpy(data, skb->data, len);
374
375 kfree_skb(skb);
376 session->report_return = NULL;
377 } else {
378 /* Device returned a HANDSHAKE, indicating protocol error. */
379 len = -EIO;
380 }
381
382 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
383 mutex_unlock(&session->report_mutex);
384
385 return len;
386
387err_restartsys:
388 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
389 mutex_unlock(&session->report_mutex);
390 return -ERESTARTSYS;
391err_eio:
392 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
393 mutex_unlock(&session->report_mutex);
394 return -EIO;
395}
396
316static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, 397static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
317 unsigned char report_type) 398 unsigned char report_type)
318{ 399{
400 struct hidp_session *session = hid->driver_data;
401 int ret;
402
319 switch (report_type) { 403 switch (report_type) {
320 case HID_FEATURE_REPORT: 404 case HID_FEATURE_REPORT:
321 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; 405 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
322 break; 406 break;
323 case HID_OUTPUT_REPORT: 407 case HID_OUTPUT_REPORT:
324 report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; 408 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
325 break; 409 break;
326 default: 410 default:
327 return -EINVAL; 411 return -EINVAL;
328 } 412 }
329 413
414 if (mutex_lock_interruptible(&session->report_mutex))
415 return -ERESTARTSYS;
416
417 /* Set up our wait, and send the report request to the device. */
418 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
330 if (hidp_send_ctrl_message(hid->driver_data, report_type, 419 if (hidp_send_ctrl_message(hid->driver_data, report_type,
331 data, count)) 420 data, count)) {
332 return -ENOMEM; 421 ret = -ENOMEM;
333 return count; 422 goto err;
423 }
424
425 /* Wait for the ACK from the device. */
426 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
427 int res;
428
429 res = wait_event_interruptible_timeout(session->report_queue,
430 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
431 10*HZ);
432 if (res == 0) {
433 /* timeout */
434 ret = -EIO;
435 goto err;
436 }
437 if (res < 0) {
438 /* signal */
439 ret = -ERESTARTSYS;
440 goto err;
441 }
442 }
443
444 if (!session->output_report_success) {
445 ret = -EIO;
446 goto err;
447 }
448
449 ret = count;
450
451err:
452 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
453 mutex_unlock(&session->report_mutex);
454 return ret;
334} 455}
335 456
336static void hidp_idle_timeout(unsigned long arg) 457static void hidp_idle_timeout(unsigned long arg)
@@ -357,16 +478,22 @@ static void hidp_process_handshake(struct hidp_session *session,
357 unsigned char param) 478 unsigned char param)
358{ 479{
359 BT_DBG("session %p param 0x%02x", session, param); 480 BT_DBG("session %p param 0x%02x", session, param);
481 session->output_report_success = 0; /* default condition */
360 482
361 switch (param) { 483 switch (param) {
362 case HIDP_HSHK_SUCCESSFUL: 484 case HIDP_HSHK_SUCCESSFUL:
363 /* FIXME: Call into SET_ GET_ handlers here */ 485 /* FIXME: Call into SET_ GET_ handlers here */
486 session->output_report_success = 1;
364 break; 487 break;
365 488
366 case HIDP_HSHK_NOT_READY: 489 case HIDP_HSHK_NOT_READY:
367 case HIDP_HSHK_ERR_INVALID_REPORT_ID: 490 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
368 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST: 491 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
369 case HIDP_HSHK_ERR_INVALID_PARAMETER: 492 case HIDP_HSHK_ERR_INVALID_PARAMETER:
493 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
494 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
495 wake_up_interruptible(&session->report_queue);
496 }
370 /* FIXME: Call into SET_ GET_ handlers here */ 497 /* FIXME: Call into SET_ GET_ handlers here */
371 break; 498 break;
372 499
@@ -385,6 +512,12 @@ static void hidp_process_handshake(struct hidp_session *session,
385 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); 512 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
386 break; 513 break;
387 } 514 }
515
516 /* Wake up the waiting thread. */
517 if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
518 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
519 wake_up_interruptible(&session->report_queue);
520 }
388} 521}
389 522
390static void hidp_process_hid_control(struct hidp_session *session, 523static void hidp_process_hid_control(struct hidp_session *session,
@@ -403,9 +536,11 @@ static void hidp_process_hid_control(struct hidp_session *session,
403 } 536 }
404} 537}
405 538
406static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, 539/* Returns true if the passed-in skb should be freed by the caller. */
540static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
407 unsigned char param) 541 unsigned char param)
408{ 542{
543 int done_with_skb = 1;
409 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param); 544 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
410 545
411 switch (param) { 546 switch (param) {
@@ -417,7 +552,6 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
417 552
418 if (session->hid) 553 if (session->hid)
419 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0); 554 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
420
421 break; 555 break;
422 556
423 case HIDP_DATA_RTYPE_OTHER: 557 case HIDP_DATA_RTYPE_OTHER:
@@ -429,12 +563,27 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
429 __hidp_send_ctrl_message(session, 563 __hidp_send_ctrl_message(session,
430 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); 564 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
431 } 565 }
566
567 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
568 param == session->waiting_report_type) {
569 if (session->waiting_report_number < 0 ||
570 session->waiting_report_number == skb->data[0]) {
571 /* hidp_get_raw_report() is waiting on this report. */
572 session->report_return = skb;
573 done_with_skb = 0;
574 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
575 wake_up_interruptible(&session->report_queue);
576 }
577 }
578
579 return done_with_skb;
432} 580}
433 581
434static void hidp_recv_ctrl_frame(struct hidp_session *session, 582static void hidp_recv_ctrl_frame(struct hidp_session *session,
435 struct sk_buff *skb) 583 struct sk_buff *skb)
436{ 584{
437 unsigned char hdr, type, param; 585 unsigned char hdr, type, param;
586 int free_skb = 1;
438 587
439 BT_DBG("session %p skb %p len %d", session, skb, skb->len); 588 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
440 589
@@ -454,7 +603,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
454 break; 603 break;
455 604
456 case HIDP_TRANS_DATA: 605 case HIDP_TRANS_DATA:
457 hidp_process_data(session, skb, param); 606 free_skb = hidp_process_data(session, skb, param);
458 break; 607 break;
459 608
460 default: 609 default:
@@ -463,7 +612,8 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
463 break; 612 break;
464 } 613 }
465 614
466 kfree_skb(skb); 615 if (free_skb)
616 kfree_skb(skb);
467} 617}
468 618
469static void hidp_recv_intr_frame(struct hidp_session *session, 619static void hidp_recv_intr_frame(struct hidp_session *session,
@@ -563,6 +713,8 @@ static int hidp_session(void *arg)
563 init_waitqueue_entry(&intr_wait, current); 713 init_waitqueue_entry(&intr_wait, current);
564 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); 714 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
565 add_wait_queue(sk_sleep(intr_sk), &intr_wait); 715 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
716 session->waiting_for_startup = 0;
717 wake_up_interruptible(&session->startup_queue);
566 while (!atomic_read(&session->terminate)) { 718 while (!atomic_read(&session->terminate)) {
567 set_current_state(TASK_INTERRUPTIBLE); 719 set_current_state(TASK_INTERRUPTIBLE);
568 720
@@ -754,6 +906,8 @@ static struct hid_ll_driver hidp_hid_driver = {
754 .hidinput_input_event = hidp_hidinput_event, 906 .hidinput_input_event = hidp_hidinput_event,
755}; 907};
756 908
909/* This function sets up the hid device. It does not add it
910 to the HID system. That is done in hidp_add_connection(). */
757static int hidp_setup_hid(struct hidp_session *session, 911static int hidp_setup_hid(struct hidp_session *session,
758 struct hidp_connadd_req *req) 912 struct hidp_connadd_req *req)
759{ 913{
@@ -793,18 +947,11 @@ static int hidp_setup_hid(struct hidp_session *session,
793 hid->dev.parent = hidp_get_device(session); 947 hid->dev.parent = hidp_get_device(session);
794 hid->ll_driver = &hidp_hid_driver; 948 hid->ll_driver = &hidp_hid_driver;
795 949
950 hid->hid_get_raw_report = hidp_get_raw_report;
796 hid->hid_output_raw_report = hidp_output_raw_report; 951 hid->hid_output_raw_report = hidp_output_raw_report;
797 952
798 err = hid_add_device(hid);
799 if (err < 0)
800 goto failed;
801
802 return 0; 953 return 0;
803 954
804failed:
805 hid_destroy_device(hid);
806 session->hid = NULL;
807
808fault: 955fault:
809 kfree(session->rd_data); 956 kfree(session->rd_data);
810 session->rd_data = NULL; 957 session->rd_data = NULL;
@@ -853,6 +1000,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
853 skb_queue_head_init(&session->ctrl_transmit); 1000 skb_queue_head_init(&session->ctrl_transmit);
854 skb_queue_head_init(&session->intr_transmit); 1001 skb_queue_head_init(&session->intr_transmit);
855 1002
1003 mutex_init(&session->report_mutex);
1004 init_waitqueue_head(&session->report_queue);
1005 init_waitqueue_head(&session->startup_queue);
1006 session->waiting_for_startup = 1;
856 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); 1007 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
857 session->idle_to = req->idle_to; 1008 session->idle_to = req->idle_to;
858 1009
@@ -875,6 +1026,14 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
875 err = kernel_thread(hidp_session, session, CLONE_KERNEL); 1026 err = kernel_thread(hidp_session, session, CLONE_KERNEL);
876 if (err < 0) 1027 if (err < 0)
877 goto unlink; 1028 goto unlink;
1029 while (session->waiting_for_startup) {
1030 wait_event_interruptible(session->startup_queue,
1031 !session->waiting_for_startup);
1032 }
1033
1034 err = hid_add_device(session->hid);
1035 if (err < 0)
1036 goto err_add_device;
878 1037
879 if (session->input) { 1038 if (session->input) {
880 hidp_send_ctrl_message(session, 1039 hidp_send_ctrl_message(session,
@@ -888,6 +1047,12 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
888 up_write(&hidp_session_sem); 1047 up_write(&hidp_session_sem);
889 return 0; 1048 return 0;
890 1049
1050err_add_device:
1051 hid_destroy_device(session->hid);
1052 session->hid = NULL;
1053 atomic_inc(&session->terminate);
1054 hidp_schedule(session);
1055
891unlink: 1056unlink:
892 hidp_del_timer(session); 1057 hidp_del_timer(session);
893 1058
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 8d934a19da0a..13de5fa03480 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -80,6 +80,8 @@
80#define HIDP_VIRTUAL_CABLE_UNPLUG 0 80#define HIDP_VIRTUAL_CABLE_UNPLUG 0
81#define HIDP_BOOT_PROTOCOL_MODE 1 81#define HIDP_BOOT_PROTOCOL_MODE 1
82#define HIDP_BLUETOOTH_VENDOR_ID 9 82#define HIDP_BLUETOOTH_VENDOR_ID 9
83#define HIDP_WAITING_FOR_RETURN 10
84#define HIDP_WAITING_FOR_SEND_ACK 11
83 85
84struct hidp_connadd_req { 86struct hidp_connadd_req {
85 int ctrl_sock; // Connected control socket 87 int ctrl_sock; // Connected control socket
@@ -154,9 +156,22 @@ struct hidp_session {
154 struct sk_buff_head ctrl_transmit; 156 struct sk_buff_head ctrl_transmit;
155 struct sk_buff_head intr_transmit; 157 struct sk_buff_head intr_transmit;
156 158
159 /* Used in hidp_get_raw_report() */
160 int waiting_report_type; /* HIDP_DATA_RTYPE_* */
161 int waiting_report_number; /* -1 for not numbered */
162 struct mutex report_mutex;
163 struct sk_buff *report_return;
164 wait_queue_head_t report_queue;
165
166 /* Used in hidp_output_raw_report() */
167 int output_report_success; /* boolean */
168
157 /* Report descriptor */ 169 /* Report descriptor */
158 __u8 *rd_data; 170 __u8 *rd_data;
159 uint rd_size; 171 uint rd_size;
172
173 wait_queue_head_t startup_queue;
174 int waiting_for_startup;
160}; 175};
161 176
162static inline void hidp_schedule(struct hidp_session *session) 177static inline void hidp_schedule(struct hidp_session *session)