Add changes from the Linux-2.6 tree.
[linux-2.6.git] / net / bluetooth / hidp / core.c
index 2cf98ce..6678201 100644 (file)
    SOFTWARE IS DISCLAIMED.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
@@ -42,6 +40,7 @@
 #include <linux/input.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "hidp.h"
@@ -429,7 +428,7 @@ static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
        return kernel_sendmsg(sock, &msg, &iv, 1, len);
 }
 
-static int hidp_process_transmit(struct hidp_session *session)
+static void hidp_process_transmit(struct hidp_session *session)
 {
        struct sk_buff *skb;
 
@@ -454,9 +453,6 @@ static int hidp_process_transmit(struct hidp_session *session)
                hidp_set_timer(session);
                kfree_skb(skb);
        }
-
-       return skb_queue_len(&session->ctrl_transmit) +
-                               skb_queue_len(&session->intr_transmit);
 }
 
 static int hidp_session(void *arg)
@@ -511,20 +507,18 @@ static int hidp_session(void *arg)
 
        hidp_del_timer(session);
 
-       if (intr_sk->sk_state != BT_CONNECTED)
-               wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
-
-       fput(session->ctrl_sock->file);
+       fput(session->intr_sock->file);
 
-       wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
+       wait_event_timeout(*(ctrl_sk->sk_sleep),
+               (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
 
-       fput(session->intr_sock->file);
+       fput(session->ctrl_sock->file);
 
        __hidp_unlink_session(session);
 
        if (session->input) {
                input_unregister_device(session->input);
-               kfree(session->input);
+               session->input = NULL;
        }
 
        up_write(&hidp_session_sem);
@@ -533,6 +527,24 @@ static int hidp_session(void *arg)
        return 0;
 }
 
+static struct device *hidp_get_device(struct hidp_session *session)
+{
+       bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
+       bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(dst, src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+
+       hci_dev_put(hdev);
+
+       return conn ? &conn->dev : NULL;
+}
+
 static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
 {
        struct input_dev *input = session->input;
@@ -540,6 +552,8 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
 
        input->private = session;
 
+       input->name = "Bluetooth HID Boot Protocol Device";
+
        input->id.bustype = BUS_BLUETOOTH;
        input->id.vendor  = req->vendor;
        input->id.product = req->product;
@@ -569,6 +583,8 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
                input->relbit[0] |= BIT(REL_WHEEL);
        }
 
+       input->cdev.dev = hidp_get_device(session);
+
        input->event = hidp_input_event;
 
        input_register_device(input);
@@ -585,17 +601,15 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
                        bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
                return -ENOTUNIQ;
 
-       session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
-       if (!session) 
+       session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
+       if (!session)
                return -ENOMEM;
-       memset(session, 0, sizeof(struct hidp_session));
 
-       session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
+       session->input = input_allocate_device();
        if (!session->input) {
                kfree(session);
                return -ENOMEM;
        }
-       memset(session->input, 0, sizeof(struct input_dev));
 
        down_write(&hidp_session_sem);
 
@@ -655,15 +669,15 @@ unlink:
 
        __hidp_unlink_session(session);
 
-       if (session->input)
+       if (session->input) {
                input_unregister_device(session->input);
+               session->input = NULL; /* don't try to free it here */
+       }
 
 failed:
        up_write(&hidp_session_sem);
 
-       if (session->input)
-               kfree(session->input);
-
+       kfree(session->input);
        kfree(session);
        return err;
 }