[PATCH 5/5]:hidbus prototype 070409:bluetooth hid

"Li Yu" <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
diff -Naurp linux-2.6.21-rc6-mm1.orig/net/bluetooth/hidp/core.c linux-2.6.21-rc6-mm1.new/net/bluetooth/hidp/core.c
--- linux-2.6.21-rc6-mm1.orig/net/bluetooth/hidp/core.c	2007-04-10 09:16:51.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/net/bluetooth/hidp/core.c	2007-04-17 09:19:27.000000000 +0800
@@ -54,6 +54,7 @@
 
 #define VERSION "1.2"
 
+static DECLARE_WAIT_QUEUE_HEAD(hidp_session_clean_barrier);
 static DECLARE_RWSEM(hidp_session_sem);
 static LIST_HEAD(hidp_session_list);
 
@@ -78,6 +79,15 @@ static unsigned char hidp_keycode[256] =
 
 static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
 
+static void hidp_update_busid(struct hid_device *dev)
+{
+	static atomic_t hidp_hiddev_idx = ATOMIC_INIT(-1);
+
+	snprintf(dev->device.bus_id, BUS_ID_SIZE, "B:%04x:%04x:%d",
+					dev->vendor, dev->product,
+				atomic_add_return(1, &hidp_hiddev_idx));
+}
+
 static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
 {
 	struct hidp_session *session;
@@ -176,7 +186,7 @@ static inline int hidp_queue_event(struc
 static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	struct hid_device *hid = dev->private;
-	struct hidp_session *session = hid->driver_data;
+	struct hidp_session *session = hid->tl_data;
 
 	return hidp_queue_event(session, dev, type, code, value);
 }
@@ -544,6 +554,11 @@ static int hidp_session(void *arg)
 	if (session->hid) {
 		vendor  = session->hid->vendor;
 		product = session->hid->product;
+		session->hid->module = THIS_MODULE;
+		if (hid_register_device(session->hid)) {
+			hid_free_device(session->hid);
+			session->hid = NULL;
+		}
 	}
 
 	daemonize("khidpd_%04x%04x", vendor, product);
@@ -598,14 +613,17 @@ static int hidp_session(void *arg)
 	}
 
 	if (session->hid) {
-		if (session->hid->claimed & HID_CLAIMED_INPUT)
-			hidinput_disconnect(session->hid);
+		hid_unregister_device(session->hid);
 		hid_free_device(session->hid);
 	}
 
 	up_write(&hidp_session_sem);
 
 	kfree(session);
+
+	if (list_empty(&hidp_session_list))
+		wake_up(&hidp_session_clean_barrier);
+
 	return 0;
 }
 
@@ -711,7 +729,7 @@ static inline void hidp_setup_hid(struct
 	baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
 	baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
 
-	hid->driver_data = session;
+	hid->tl_data = session;
 
 	hid->country = req->country;
 
@@ -726,11 +744,6 @@ static inline void hidp_setup_hid(struct
 
 	hid->dev = hidp_get_device(session);
 
-	hid->hid_open  = hidp_open;
-	hid->hid_close = hidp_close;
-
-	hid->hidinput_input_event = hidp_hidinput_event;
-
 	hidp_setup_quirks(hid);
 
 	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
@@ -738,11 +751,6 @@ static inline void hidp_setup_hid(struct
 
 	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
 		hidp_send_report(session, report);
-
-	if (hidinput_connect(hid) == 0) {
-		hid->claimed |= HID_CLAIMED_INPUT;
-		hid_ff_init(hid);
-	}
 }
 
 int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
@@ -868,6 +876,10 @@ failed:
 
 	kfree(session->input);
 	kfree(session);
+
+	if (list_empty(&hidp_session_list))
+		wake_up(&hidp_session_clean_barrier);
+
 	return err;
 }
 
@@ -951,8 +963,57 @@ int hidp_get_conninfo(struct hidp_connin
 	return err;
 }
 
+static struct hid_driver hid_bt_driver = {
+	.name = "hidbt",
+	.version = "0.9.0",
+	.bus = BUS_BLUETOOTH,
+	.module = THIS_MODULE,
+	.match = NULL, /* default match any bluetooth hidp device. */
+	.probe = NULL, /* default is hidinput_connect() */
+	.remove = NULL, /* default is hidinput_disconnect() */
+};
+
+static struct hid_transport hid_bt_transport = {
+	.bus = BUS_BLUETOOTH,
+	.event = hidp_hidinput_event,
+	.open = hidp_open,
+	.close = hidp_close,
+	.update_busid = hidp_update_busid,
+	.module = THIS_MODULE,
+};
+
+static int is_hidp_session_list_empty(void)
+{
+	int ret;
+
+	down_read(&hidp_session_sem);
+	ret = list_empty(&hidp_session_list);
+	up_read(&hidp_session_sem);
+	return ret;
+}
+
+static void hidp_session_clean(void)
+{
+	struct hidp_session *session;
+	
+	down_read(&hidp_session_sem);
+	list_for_each_entry(session, &hidp_session_list, list) {
+		atomic_inc(&session->terminate);
+		hidp_schedule(session);
+	}
+	up_read(&hidp_session_sem);
+}
+
+
 static int __init hidp_init(void)
 {
+	if (hid_register_transport(&hid_bt_transport))
+		return -ENODEV;
+	if (hid_register_driver(&hid_bt_driver)) {
+		hid_unregister_transport(&hid_bt_transport);
+		return -ENODEV;
+	}
+
 	l2cap_load();
 
 	BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
@@ -962,6 +1023,11 @@ static int __init hidp_init(void)
 
 static void __exit hidp_exit(void)
 {
+	hidp_session_clean();
+	wait_event(hidp_session_clean_barrier, is_hidp_session_list_empty());
+
+	hid_unregister_transport(&hid_bt_transport);
+	hid_unregister_driver(&hid_bt_driver);
 	hidp_cleanup_sockets();
 }

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.