aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hidp/core.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-04-12 16:18:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-12 16:18:44 -0400
commit252f4bf400df1712408fe83ba199a66a1b57ab1d (patch)
treee07fa00abdd55b31e22567786c78635f32c6a66c /net/bluetooth/hidp/core.c
parent6ba1037c3d871ab70e342631516dbf841c35b086 (diff)
parentb37e3b6d64358604960b35e8ecbb7aed22e0926e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/ath/ar9170/main.c drivers/net/wireless/ath/ar9170/phy.c drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
Diffstat (limited to 'net/bluetooth/hidp/core.c')
-rw-r--r--net/bluetooth/hidp/core.c90
1 files changed, 44 insertions, 46 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 5ec12971af6..ae6ebc6c348 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -37,6 +37,7 @@
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 <linux/mutex.h>
40#include <linux/kthread.h>
40#include <net/sock.h> 41#include <net/sock.h>
41 42
42#include <linux/input.h> 43#include <linux/input.h>
@@ -55,22 +56,24 @@ static DECLARE_RWSEM(hidp_session_sem);
55static LIST_HEAD(hidp_session_list); 56static LIST_HEAD(hidp_session_list);
56 57
57static unsigned char hidp_keycode[256] = { 58static unsigned char hidp_keycode[256] = {
58 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 59 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36,
59 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, 60 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45,
60 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, 61 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1,
61 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 62 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52,
62 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, 63 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88,
63 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 64 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69,
64 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 65 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73,
65 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 66 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190,
66 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, 67 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135,
67 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68 136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69 95, 0, 0, 0, 122, 123, 90, 91, 85, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 150,158,159,128,136,177,178,176,142,152,173,140 74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115,
76 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140
74}; 77};
75 78
76static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; 79static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
@@ -461,8 +464,7 @@ static void hidp_idle_timeout(unsigned long arg)
461{ 464{
462 struct hidp_session *session = (struct hidp_session *) arg; 465 struct hidp_session *session = (struct hidp_session *) arg;
463 466
464 atomic_inc(&session->terminate); 467 kthread_stop(session->task);
465 hidp_schedule(session);
466} 468}
467 469
468static void hidp_set_timer(struct hidp_session *session) 470static void hidp_set_timer(struct hidp_session *session)
@@ -533,9 +535,7 @@ static void hidp_process_hid_control(struct hidp_session *session,
533 skb_queue_purge(&session->ctrl_transmit); 535 skb_queue_purge(&session->ctrl_transmit);
534 skb_queue_purge(&session->intr_transmit); 536 skb_queue_purge(&session->intr_transmit);
535 537
536 /* Kill session thread */ 538 kthread_stop(session->task);
537 atomic_inc(&session->terminate);
538 hidp_schedule(session);
539 } 539 }
540} 540}
541 541
@@ -694,22 +694,10 @@ static int hidp_session(void *arg)
694 struct sock *ctrl_sk = session->ctrl_sock->sk; 694 struct sock *ctrl_sk = session->ctrl_sock->sk;
695 struct sock *intr_sk = session->intr_sock->sk; 695 struct sock *intr_sk = session->intr_sock->sk;
696 struct sk_buff *skb; 696 struct sk_buff *skb;
697 int vendor = 0x0000, product = 0x0000;
698 wait_queue_t ctrl_wait, intr_wait; 697 wait_queue_t ctrl_wait, intr_wait;
699 698
700 BT_DBG("session %p", session); 699 BT_DBG("session %p", session);
701 700
702 if (session->input) {
703 vendor = session->input->id.vendor;
704 product = session->input->id.product;
705 }
706
707 if (session->hid) {
708 vendor = session->hid->vendor;
709 product = session->hid->product;
710 }
711
712 daemonize("khidpd_%04x%04x", vendor, product);
713 set_user_nice(current, -15); 701 set_user_nice(current, -15);
714 702
715 init_waitqueue_entry(&ctrl_wait, current); 703 init_waitqueue_entry(&ctrl_wait, current);
@@ -718,10 +706,11 @@ static int hidp_session(void *arg)
718 add_wait_queue(sk_sleep(intr_sk), &intr_wait); 706 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
719 session->waiting_for_startup = 0; 707 session->waiting_for_startup = 0;
720 wake_up_interruptible(&session->startup_queue); 708 wake_up_interruptible(&session->startup_queue);
721 while (!atomic_read(&session->terminate)) { 709 while (!kthread_should_stop()) {
722 set_current_state(TASK_INTERRUPTIBLE); 710 set_current_state(TASK_INTERRUPTIBLE);
723 711
724 if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED) 712 if (ctrl_sk->sk_state != BT_CONNECTED ||
713 intr_sk->sk_state != BT_CONNECTED)
725 break; 714 break;
726 715
727 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { 716 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
@@ -965,6 +954,7 @@ fault:
965int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) 954int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
966{ 955{
967 struct hidp_session *session, *s; 956 struct hidp_session *session, *s;
957 int vendor, product;
968 int err; 958 int err;
969 959
970 BT_DBG(""); 960 BT_DBG("");
@@ -1026,9 +1016,24 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
1026 1016
1027 hidp_set_timer(session); 1017 hidp_set_timer(session);
1028 1018
1029 err = kernel_thread(hidp_session, session, CLONE_KERNEL); 1019 if (session->hid) {
1030 if (err < 0) 1020 vendor = session->hid->vendor;
1021 product = session->hid->product;
1022 } else if (session->input) {
1023 vendor = session->input->id.vendor;
1024 product = session->input->id.product;
1025 } else {
1026 vendor = 0x0000;
1027 product = 0x0000;
1028 }
1029
1030 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1031 vendor, product);
1032 if (IS_ERR(session->task)) {
1033 err = PTR_ERR(session->task);
1031 goto unlink; 1034 goto unlink;
1035 }
1036
1032 while (session->waiting_for_startup) { 1037 while (session->waiting_for_startup) {
1033 wait_event_interruptible(session->startup_queue, 1038 wait_event_interruptible(session->startup_queue,
1034 !session->waiting_for_startup); 1039 !session->waiting_for_startup);
@@ -1053,8 +1058,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
1053err_add_device: 1058err_add_device:
1054 hid_destroy_device(session->hid); 1059 hid_destroy_device(session->hid);
1055 session->hid = NULL; 1060 session->hid = NULL;
1056 atomic_inc(&session->terminate); 1061 kthread_stop(session->task);
1057 hidp_schedule(session);
1058 1062
1059unlink: 1063unlink:
1060 hidp_del_timer(session); 1064 hidp_del_timer(session);
@@ -1105,13 +1109,7 @@ int hidp_del_connection(struct hidp_conndel_req *req)
1105 skb_queue_purge(&session->ctrl_transmit); 1109 skb_queue_purge(&session->ctrl_transmit);
1106 skb_queue_purge(&session->intr_transmit); 1110 skb_queue_purge(&session->intr_transmit);
1107 1111
1108 /* Wakeup user-space polling for socket errors */ 1112 kthread_stop(session->task);
1109 session->intr_sock->sk->sk_err = EUNATCH;
1110 session->ctrl_sock->sk->sk_err = EUNATCH;
1111
1112 /* Kill session thread */
1113 atomic_inc(&session->terminate);
1114 hidp_schedule(session);
1115 } 1113 }
1116 } else 1114 } else
1117 err = -ENOENT; 1115 err = -ENOENT;