--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
-@@ -383,6 +383,7 @@ err:
+@@ -329,6 +329,7 @@ err:
return ret;
}
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
unsigned char report_type)
{
-@@ -441,6 +442,16 @@ err:
+@@ -386,6 +387,16 @@ err:
mutex_unlock(&session->report_mutex);
return ret;
}
static void hidp_idle_timeout(unsigned long arg)
{
-@@ -743,8 +754,14 @@ static int hidp_session(void *arg)
- }
-
- if (session->hid) {
-+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
- hid_destroy_device(session->hid);
- session->hid = NULL;
-+#else
-+ if (session->hid->claimed & HID_CLAIMED_INPUT)
-+ hidinput_disconnect(session->hid);
-+ hid_free_device(session->hid);
-+#endif
- }
-
- /* Wakeup user-space polling for socket errors */
-@@ -855,6 +872,70 @@ static void hidp_close(struct hid_device
+@@ -674,6 +685,87 @@ static void hidp_close(struct hid_device
{
}
+ hid->quirks = hidp_blacklist[n].quirks;
+}
+
-+static void hidp_setup_hid(struct hidp_session *session,
-+ struct hidp_connadd_req *req)
++static int hidp_setup_hid(struct hidp_session *session,
++ struct hidp_connadd_req *req)
+{
-+ struct hid_device *hid = session->hid;
++ struct hid_device *hid;
+ struct hid_report *report;
+ bdaddr_t src, dst;
++ unsigned char *buf;
++
++ buf = kmalloc(req->rd_size, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ if (copy_from_user(buf, req->rd_data, req->rd_size)) {
++ kfree(buf);
++ return -EFAULT;
++ }
++
++ hid = hid_parse_report(buf, req->rd_size);
++ kfree(buf);
++ if (!session->hid)
++ return -EINVAL;
+
+ session->hid = hid;
+
+ hid->version = req->version;
+ hid->country = req->country;
+
-+ strncpy(hid->name, req->name, 128);
-+ strncpy(hid->phys, batostr(&src), 64);
-+ strncpy(hid->uniq, batostr(&dst), 64);
++ strlcpy(hid->name, req->name, 128);
++ strlcpy(hid->phys, batostr(&src), 64);
++ strlcpy(hid->uniq, batostr(&dst), 64);
+
+ hid->dev = hidp_get_device(session);
+ hid->hid_open = hidp_open;
+
+ if (hidinput_connect(hid) == 0)
+ hid->claimed |= HID_CLAIMED_INPUT;
++
++ return 0;
+}
+#else
+
static int hidp_parse(struct hid_device *hid)
{
struct hidp_session *session = hid->driver_data;
-@@ -946,7 +1027,9 @@ static int hidp_setup_hid(struct hidp_se
- hid->dev.parent = &session->conn->dev;
+@@ -764,7 +856,9 @@ static int hidp_setup_hid(struct hidp_se
+ hid->dev.parent = &session->conn->hcon->dev;
hid->ll_driver = &hidp_hid_driver;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
hid->hid_output_raw_report = hidp_output_raw_report;
/* True if device is blacklisted in drivers/hid/hid-core.c */
-@@ -964,6 +1047,7 @@ fault:
+@@ -782,6 +876,7 @@ fault:
return err;
}
+#endif
- int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
+ /* initialize session devices */
+ static int hidp_session_dev_init(struct hidp_session *session,
+@@ -844,10 +939,17 @@ static int hidp_session_dev_add(struct h
+ /* remove HID/input devices from their bus systems */
+ static void hidp_session_dev_del(struct hidp_session *session)
{
-@@ -981,6 +1065,39 @@ int hidp_add_connection(struct hidp_conn
-
- BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
-
-+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27))
-+ if (req->rd_size > 0) {
-+ unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
-+
-+ if (!buf) {
-+ kfree(session);
-+ return -ENOMEM;
-+ }
-+
-+ if (copy_from_user(buf, req->rd_data, req->rd_size)) {
-+ kfree(buf);
-+ kfree(session);
-+ return -EFAULT;
-+ }
-+
-+ session->hid = hid_parse_report(buf, req->rd_size);
-+
-+ kfree(buf);
-+
-+ if (!session->hid) {
-+ kfree(session);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ if (!session->hid) {
-+ session->input = input_allocate_device();
-+ if (!session->input) {
-+ kfree(session);
-+ return -ENOMEM;
-+ }
-+ }
-+#endif
- down_write(&hidp_session_sem);
-
- s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
-@@ -1028,6 +1145,7 @@ int hidp_add_connection(struct hidp_conn
-
- __hidp_link_session(session);
-
+- if (session->hid)
++ if (session->hid) {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
- if (req->rd_size > 0) {
- err = hidp_setup_hid(session, req);
- if (err && err != -ENODEV)
-@@ -1039,6 +1157,16 @@ int hidp_add_connection(struct hidp_conn
- if (err < 0)
- goto purge;
- }
-+#else
-+ if (session->input) {
-+ err = hidp_setup_input(session, req);
-+ if (err < 0)
-+ goto failed;
-+ }
-+
-+ if (session->hid)
-+ hidp_setup_hid(session, req);
-+#endif
-
- hidp_set_timer(session);
-
-@@ -1097,6 +1225,7 @@ unlink:
- session->input = NULL;
- }
-
-+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
- if (session->hid) {
hid_destroy_device(session->hid);
- session->hid = NULL;
-@@ -1110,10 +1239,15 @@ purge:
-
- skb_queue_purge(&session->ctrl_transmit);
- skb_queue_purge(&session->intr_transmit);
-+#endif
-
- failed:
- up_write(&hidp_session_sem);
-
-+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27))
-+ if (session->hid)
+- else if (session->input)
++#else
++ if (session->hid->claimed & HID_CLAIMED_INPUT)
++ hidinput_disconnect(session->hid);
+ hid_free_device(session->hid);
+#endif
- kfree(session);
- return err;
++ } else if (session->input) {
+ input_unregister_device(session->input);
++ }
}
+
+ /*