[PATCH 1/3] Add support for command line arguments on hid2hci tool

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This means that hid2hci won't have to run
 on every bootup for every machine with bluetooth installed.  It instead
gets ran on demand if a
 product that is called out from the dbus rules file contains the
correct attributes and/or VID/PID.

 It also makes it easier for users to manually test new VID/PID
combinations that may or may not
 be yet supported by bluez.
---
 scripts/Makefile.am       |   12 ++-
 scripts/bluetooth.default |    3 -
 scripts/bluetooth.init    |    7 --
 scripts/hid2hci.rules     |   38 ++++++++++
 tools/hid2hci.c           |  179
+++++++++++++++++++-------------------------
 5 files changed, 124 insertions(+), 115 deletions(-)
 create mode 100644 scripts/hid2hci.rules

Attaching patch as Exchange would mangle otherwise.

Thanks,
-- 
Mario Limonciello
*Dell | Linux Engineering*
mario_limonciello@xxxxxxxx
From d95fe2f74815243123bff8f34cb427d901e3ba32 Mon Sep 17 00:00:00 2001
From: Mario Limonciello <Mario_Limonciello@xxxxxxxx>
Date: Fri, 15 May 2009 14:29:03 -0500
Subject: [PATCH] Add support for command line arguments on hid2hci tool.  
 This means that hid2hci won't have to run
 on every bootup for every machine with bluetooth installed.  It instead gets ran on demand if a
 product that is called out from the dbus rules file contains the correct attributes and/or VID/PID.

 It also makes it easier for users to manually test new VID/PID combinations that may or may not
 be yet supported by bluez.
---
 scripts/Makefile.am       |   12 ++-
 scripts/bluetooth.default |    3 -
 scripts/bluetooth.init    |    7 --
 scripts/hid2hci.rules     |   38 ++++++++++
 tools/hid2hci.c           |  179 +++++++++++++++++++-------------------------
 5 files changed, 124 insertions(+), 115 deletions(-)
 create mode 100644 scripts/hid2hci.rules

diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 6a8eec7..a9d09c0 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -1,14 +1,20 @@
+rulesdir = $(sysconfdir)/udev
+
+udevdir = $(libexecdir)/udev
 
 if PCMCIARULES
-rulesdir = $(sysconfdir)/udev
 
 rules_DATA = bluetooth.rules
 
-udevdir = $(libexecdir)/udev
-
 udev_SCRIPTS = bluetooth_serial
 endif
 
+if HID2HCI
+
+rules_DATA = $rules_DATA hid2hci.rules
+
+endif
+
 EXTRA_DIST = bluetooth.rules bluetooth_serial bluetooth.init bluetooth.default
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/scripts/bluetooth.default b/scripts/bluetooth.default
index b0c4493..cdf37fa 100644
--- a/scripts/bluetooth.default
+++ b/scripts/bluetooth.default
@@ -1,4 +1 @@
 # Bluetooth configuraton file
-
-# Run hid2hci (allowed values are "true" and "false")
-HID2HCI_ENABLE=true
diff --git a/scripts/bluetooth.init b/scripts/bluetooth.init
index ee12408..3ea8a89 100644
--- a/scripts/bluetooth.init
+++ b/scripts/bluetooth.init
@@ -10,13 +10,10 @@ NAME=bluetooth
 DESC="Bluetooth subsystem"
 
 DAEMON_NAME=bluetoothd
-HID2HCI_NAME=hid2hci
 
 DAEMON_EXEC="`which $DAEMON_NAME || true`"
-HID2HCI_EXEC="`which $HID2HCI_NAME || true`"
 
 DAEMON_ENABLE=true
-HID2HCI_ENABLE=false
 
 [ -e /etc/default/bluetooth ] && . /etc/default/bluetooth
 
@@ -27,10 +24,6 @@ case "$1" in
 		$DAEMON_EXEC
 		echo -n " $DAEMON_NAME"
 	fi
-	if $HID2HCI_ENABLE && [ -x "$HID2HCI_EXEC" ] ; then
-		$HID2HCI_EXEC --tohci > /dev/null 2>&1 || true
-		echo -n " $HID2HCI_NAME"
-	fi
 	echo "."
 	;;
   stop)
diff --git a/scripts/hid2hci.rules b/scripts/hid2hci.rules
new file mode 100644
index 0000000..ee15c72
--- /dev/null
+++ b/scripts/hid2hci.rules
@@ -0,0 +1,38 @@
+#UDEV Rules to match on Bluetooth USB dongles that need to be switched to HCI mode upon
+#being plugged into the PC's USB bus.
+
+##Variety of Dell Bluetooth adapters
+# it looks like a bit of an odd rule, because it is matching
+# on a mouse device that is self powered, but that is where
+# a HID report needs to be sent to switch modes.
+#Known supported devices:
+# 413c:8154
+# 413c:8158
+# 413c:8162
+ACTION=="add", ENV{ID_VENDOR}=="413c", ENV{ID_CLASS}=="mouse", ATTRS{bmAttributes}=="e0", KERNEL=="mouse*", RUN+="/usr/sbin/hid2hci --method dell -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+
+##Logitech adapters
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c703" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c704" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c705" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c70a" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c70b" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c70c" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c70e" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c713" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c714" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c71b" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="046d", ENV{ID_MODEL}=="c71c" RUN+="/usr/sbin/hid2hci --method logitech -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+
+##HID Proxy adapters
+#These rules are for hid proxy adapters to default them to hci mode
+ACTION=="add", ENV{ID_VENDOR}=="0a12", ENV{ID_MODEL}=="1000" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="0458", ENV{ID_MODEL}=="1000" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+ACTION=="add", ENV{ID_VENDOR}=="05ac", ENV{ID_MODEL}=="1000" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hci"
+
+#These rules are for hid proxy adapters to default them to hid mode
+#ACTION=="add", ENV{ID_VENDOR}=="0a12", ENV{ID_MODEL}=="0001" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hid"
+#ACTION=="add", ENV{ID_VENDOR}=="0458", ENV{ID_MODEL}=="003f" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hid"
+#ACTION=="add", ENV{ID_VENDOR}=="05ac", ENV{ID_MODEL}=="8203" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hid"
+#ACTION=="add", ENV{ID_VENDOR}=="05ac", ENV{ID_MODEL}=="8204" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hid"
+#ACTION=="add", ENV{ID_VENDOR}=="05ac", ENV{ID_MODEL}=="8207" RUN+="/usr/sbin/hid2hci --method hidproxy -v $env{ID_VENDOR} -p $env{ID_MODEL} --radiomode hid"
diff --git a/tools/hid2hci.c b/tools/hid2hci.c
index cd38aac..dace0ea 100644
--- a/tools/hid2hci.c
+++ b/tools/hid2hci.c
@@ -83,21 +83,15 @@ struct hiddev_usage_ref {
 
 #define HID_REPORT_TYPE_OUTPUT	2
 
-#define HCI 0
-#define HID 1
-
-struct device_info;
-
-struct device_id {
-	int mode;
-	uint16_t vendor;
-	uint16_t product;
-	int (*func)(struct device_info *dev);
+enum radio_modes {
+	HCI=0, HID=1 
 };
 
 struct device_info {
 	struct usb_device *dev;
-	struct device_id *id;
+	int mode;
+	uint16_t vendor;
+	uint16_t product;
 };
 
 static int switch_hidproxy(struct device_info *devinfo)
@@ -110,7 +104,7 @@ static int switch_hidproxy(struct device_info *devinfo)
 		return -errno;
 
 	err = usb_control_msg(udev, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				0, devinfo->id->mode, 0, NULL, 0, 10000);
+				0, devinfo->mode, 0, NULL, 0, 10000);
 
 	if (err == 0) {
 		err = -1;
@@ -243,77 +237,33 @@ static int switch_dell(struct device_info *devinfo)
 	return err;
 }
 
-static struct device_id device_list[] = {
-	{ HCI, 0x0a12, 0x1000, switch_hidproxy },
-	{ HID, 0x0a12, 0x0001, switch_hidproxy },
-	{ HCI, 0x0458, 0x1000, switch_hidproxy },
-	{ HID, 0x0458, 0x003f, switch_hidproxy },
-	{ HCI, 0x05ac, 0x1000, switch_hidproxy },
-	{ HID, 0x05ac, 0x8203, switch_hidproxy },
-	{ HID, 0x05ac, 0x8204, switch_hidproxy },	/* Apple Mac mini */
-	{ HID, 0x05ac, 0x8207, switch_hidproxy },	/* Apple Power Mac G5 */
-	{ HCI, 0x046d, 0xc703, switch_logitech },
-	{ HCI, 0x046d, 0xc704, switch_logitech },
-	{ HCI, 0x046d, 0xc705, switch_logitech },
-	{ HCI, 0x046d, 0xc70a, switch_logitech },	/* Logitech diNovo mouse */
-	{ HCI, 0x046d, 0xc70b, switch_logitech },	/* Logitech diNovo Laser keyboard */
-	{ HCI, 0x046d, 0xc70c, switch_logitech },	/* Logitech diNovo Laser mouse */
-	{ HCI, 0x046d, 0xc70e, switch_logitech },	/* Logitech diNovo keyboard */
-	{ HCI, 0x046d, 0xc713, switch_logitech },	/* Logitech diNovo Edge */
-	{ HCI, 0x046d, 0xc714, switch_logitech },	/* Logitech diNovo Edge */
-	{ HCI, 0x046d, 0xc71b, switch_logitech },	/* Logitech diNovo Edge */
-	{ HCI, 0x046d, 0xc71c, switch_logitech },	/* Logitech diNovo Edge */
-	{ HCI, 0x413c, 0x8154, switch_dell     },	/* Dell Wireless 410 */
-	{ HCI, 0x413c, 0x8158, switch_dell     },	/* Dell Wireless 370 */
-	{ HCI, 0x413c, 0x8162, switch_dell     },	/* Dell Wireless 365 */
-	{ -1 }
-};
-
-static struct device_id *match_device(int mode, uint16_t vendor, uint16_t product)
-{
-	int i;
-
-	for (i = 0; device_list[i].mode >= 0; i++) {
-		if (mode != device_list[i].mode)
-			continue;
-		if (vendor == device_list[i].vendor &&
-				product == device_list[i].product)
-			return &device_list[i];
-	}
-
-	return NULL;
-}
-
-static int find_devices(int mode, struct device_info *devinfo, size_t size)
+static int find_device(struct device_info* devinfo)
 {
 	struct usb_bus *bus;
 	struct usb_device *dev;
-	struct device_id *id;
-	unsigned int count = 0;
 
 	usb_find_busses();
 	usb_find_devices();
 
 	for (bus = usb_get_busses(); bus; bus = bus->next)
 		for (dev = bus->devices; dev; dev = dev->next) {
-			id = match_device(mode, dev->descriptor.idVendor,
-						dev->descriptor.idProduct);
-			if (!id)
-				continue;
-
-			if (count < size) {
-				devinfo[count].dev = dev;
-				devinfo[count].id = id;
-				count++;
+			if (dev->descriptor.idVendor == devinfo->vendor &&
+			    dev->descriptor.idProduct == devinfo->product) {
+				devinfo->dev=dev;
+				break;
 			}
 		}
-
-	return count;
+	if (!devinfo->dev)
+		return 0;
+	return 1;
 }
 
-static void usage(void)
+static void usage(char* error)
 {
-	printf("hid2hci - Bluetooth HID to HCI mode switching utility\n\n");
+	if (error)
+		printf("\n%s\n", error);
+	else
+		printf("hid2hci - Bluetooth HID to HCI mode switching utility\n\n");
 
 	printf("Usage:\n"
 		"\thid2hci [options]\n"
@@ -322,42 +272,71 @@ static void usage(void)
 	printf("Options:\n"
 		"\t-h, --help           Display help\n"
 		"\t-q, --quiet          Don't display any messages\n"
-		"\t-0, --tohci          Switch to HCI mode (default)\n"
-		"\t-1, --tohid          Switch to HID mode\n"
+		"\t-r, --radiomode=     Radio Mode to switch to [hid, hci]\n"
+		"\t-v, --vendor=        Vendor ID to act upon\n"
+		"\t-p, --product=       Product ID to act upon\n"
+		"\t-m, --method=        Method to use to switch [hidproxy, logitech, dell]\n"
 		"\n");
+	if (error)
+		exit(1);
+	exit(0);
 }
 
 static struct option main_options[] = {
-	{ "help",	0, 0, 'h' },
-	{ "quiet",	0, 0, 'q' },
-	{ "tohci",	0, 0, '0' },
-	{ "tohid",	0, 0, '1' },
+	{ "help",	no_argument, 0, 'h' },
+	{ "quiet",	no_argument, 0, 'q' },
+	{ "radiomode",	required_argument, 0, 'r' },
+	{ "vendor",	required_argument, 0, 'v' },
+	{ "product",	required_argument, 0, 'p' },
+	{ "method",	required_argument, 0, 'm' },
 	{ 0, 0, 0, 0 }
 };
 
 int main(int argc, char *argv[])
 {
-	struct device_info dev[16];
-	int i, opt, num, quiet = 0, mode = HCI;
+	struct device_info dev = { NULL, HCI, 0, 0 };
+	int opt, quiet = 0;
+	int (*method)(struct device_info *dev) = NULL;
 
-	while ((opt = getopt_long(argc, argv, "+01qh", main_options, NULL)) != -1) {
+	while ((opt = getopt_long(argc, argv, "+r:v:p:m:qh", main_options, NULL)) != -1) {
 		switch (opt) {
-		case '0':
-			mode = HCI;
-			break;
-		case '1':
-			mode = HID;
+		case 'r':
+			if (optarg && !strcmp(optarg, "hid"))
+				dev.mode = HID;
+			else if (optarg && !strcmp(optarg, "hci"))
+				dev.mode = HCI;
+			else {
+				usage("ERROR: Undefined radio mode\n");
+			}
 			break;
+		case 'v':
+				sscanf(optarg, "%4hx", &dev.vendor);
+				break;
+		case 'p':
+				sscanf(optarg, "%4hx", &dev.product);
+				break;
+		case 'm':
+				if (optarg && !strcmp(optarg, "hidproxy"))
+					method = switch_hidproxy;
+				else if (optarg && !strcmp(optarg, "logitech"))
+					method = switch_logitech;
+				else if (optarg && !strcmp(optarg, "dell"))
+					method = switch_dell;
+				else
+					usage("ERROR: Undefined switching method\n");
+				break;
 		case 'q':
 			quiet = 1;
 			break;
 		case 'h':
-			usage();
-			exit(0);
+			usage(NULL);
 		default:
 			exit(0);
 		}
 	}
+	
+	if (!quiet && (!dev.vendor || !dev.product || !method))
+		usage("ERROR: Vendor ID, Product ID, and Switching Method must all be defined.\n");
 
 	argc -= optind;
 	argv += optind;
@@ -365,29 +344,25 @@ int main(int argc, char *argv[])
 
 	usb_init();
 
-	num = find_devices(mode, dev, sizeof(dev) / sizeof(dev[0]));
-	if (num <= 0) {
+	if (!find_device(&dev)) {
 		if (!quiet)
-			fprintf(stderr, "No devices in %s mode found\n",
-							mode ? "HCI" : "HID");
+			fprintf(stderr, "Device %04x:%04x not found on USB bus.\n",
+				dev.vendor, dev.product);
 		exit(1);
 	}
 
-	for (i = 0; i < num; i++) {
-		struct device_id *id = dev[i].id;
+	if (!quiet)
+		printf("Attempting to switch device %04x:%04x to %s mode ",
+			dev.vendor, dev.product, dev.mode ? "HID" : "HCI");
+	fflush(stdout);
 
+	if (method(&dev) < 0) {
 		if (!quiet)
-			printf("Switching device %04x:%04x to %s mode ",
-				id->vendor, id->product, mode ? "HID" : "HCI");
-		fflush(stdout);
-
-		if (id->func(&dev[i]) < 0) {
-			if (!quiet)
-				printf("failed (%s)\n", strerror(errno));
-		} else {
-			if (!quiet)
-				printf("was successful\n");
-		}
+			printf("failed (%s)\n", strerror(errno));
+		exit(errno);
+	} else {
+		if (!quiet)
+			printf("was successful\n");
 	}
 
 	return 0;
-- 
1.6.0.4


Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux