summaryrefslogtreecommitdiff
path: root/extras
diff options
context:
space:
mode:
authorMario Limonciello <mario_limonciello@dell.com>2009-07-22 00:33:27 +0200
committerKay Sievers <kay.sievers@vrfy.org>2009-07-22 00:33:27 +0200
commit5bacd2aadc854a0c01934bab76d4f575543d361e (patch)
tree1004c3f879ef850c835042466698ae879767ce21 /extras
parentbe7fec4815ef3e96f2454b7fbcd08ac408f387d8 (diff)
hid2hci: support to hid2hci for recovering Dell BT devices after S3
Diffstat (limited to 'extras')
-rw-r--r--extras/hid2hci/70-hid2hci.rules5
-rw-r--r--extras/hid2hci/hid2hci.c45
2 files changed, 49 insertions, 1 deletions
diff --git a/extras/hid2hci/70-hid2hci.rules b/extras/hid2hci/70-hid2hci.rules
index caf9120f53..47eec00abe 100644
--- a/extras/hid2hci/70-hid2hci.rules
+++ b/extras/hid2hci/70-hid2hci.rules
@@ -11,6 +11,11 @@ SUBSYSTEM!="usb", GOTO="hid2hci_end"
ATTR{bInterfaceClass}=="03", ATTR{bInterfaceSubClass}=="01", ATTR{bInterfaceProtocol}=="02", ATTRS{bDeviceClass}=="00", ATTRS{idVendor}=="413c", ATTRS{bmAttributes}=="e0", \
RUN+="hid2hci --method dell -v $attr{idVendor} -p $attr{idProduct} --mode hci"
+# When a Dell device recovers from S3, the mouse child needs to be repoked
+# Unfortunately the only event seen is the BT device disappearing, so the mouse
+# device needs to be chased down on the USB bus.
+ATTR{bDeviceClass}=="e0", ATTR{bDeviceSubClass}=="01", ATTR{bDeviceProtocol}=="01", ATTR{idVendor}=="413c", ATTR{bmAttributes}=="e0", IMPORT{parent}="ID_*", ENV{REMOVE_CMD}="hid2hci --method dell -v $env{ID_VENDOR_ID} -p $env{ID_MODEL_ID} --mode hci -s 02"
+
ENV{DEVTYPE}!="usb_device", GOTO="hid2hci_end"
# Logitech devices
diff --git a/extras/hid2hci/hid2hci.c b/extras/hid2hci/hid2hci.c
index aa44790f2b..469f8709ea 100644
--- a/extras/hid2hci/hid2hci.c
+++ b/extras/hid2hci/hid2hci.c
@@ -271,6 +271,36 @@ static int find_device(struct device_info* devinfo)
return 0;
}
+static int find_resuscitated_device(struct device_info* devinfo, uint8_t bInterfaceProtocol)
+{
+ int i,j,k,l;
+ struct usb_device *dev, *child;
+ struct usb_config_descriptor config;
+ struct usb_interface interface;
+ struct usb_interface_descriptor altsetting;
+
+ /* Using the base device, attempt to find the child with the
+ * matching bInterfaceProtocol */
+ dev = devinfo->dev;
+ for (i = 0; i < dev->num_children; i++) {
+ child = dev->children[i];
+ for (j = 0; j < child->descriptor.bNumConfigurations; j++) {
+ config = child->config[j];
+ for (k = 0; k < config.bNumInterfaces; k++) {
+ interface = config.interface[k];
+ for (l = 0; l < interface.num_altsetting; l++) {
+ altsetting = interface.altsetting[l];
+ if (altsetting.bInterfaceProtocol == bInterfaceProtocol) {
+ devinfo->dev = child;
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
static void usage(char* error)
{
if (error)
@@ -289,6 +319,7 @@ static void usage(char* error)
"\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 [csr, logitech, dell]\n"
+ "\t-s, --resuscitate= Find the child device with this bInterfaceProtocol to run on \n"
"\n");
if (error)
exit(1);
@@ -301,6 +332,7 @@ static const struct option main_options[] = {
{ "vendor", required_argument, 0, 'v' },
{ "product", required_argument, 0, 'p' },
{ "method", required_argument, 0, 'm' },
+ { "resuscitate",required_argument, 0, 's' },
{ 0, 0, 0, 0 }
};
@@ -309,8 +341,9 @@ int main(int argc, char *argv[])
struct device_info dev = { NULL, HCI, 0, 0 };
int opt, quiet = 0;
int (*method)(struct device_info *dev) = NULL;
+ uint8_t resuscitate = 0;
- while ((opt = getopt_long(argc, argv, "+r:v:p:m:qh", main_options, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "+s:r:v:p:m:qh", main_options, NULL)) != -1) {
switch (opt) {
case 'r':
if (optarg && !strcmp(optarg, "hid"))
@@ -339,6 +372,9 @@ int main(int argc, char *argv[])
case 'q':
quiet = 1;
break;
+ case 's':
+ sscanf(optarg, "%2hx", (short unsigned int*) &resuscitate);
+ break;
case 'h':
usage(NULL);
default:
@@ -362,6 +398,13 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (resuscitate && !find_resuscitated_device(&dev, resuscitate)) {
+ if (!quiet)
+ fprintf(stderr, "Device %04x:%04x was unable to resucitate any child devices.\n",
+ dev.vendor,dev.product);
+ exit(1);
+ }
+
if (!quiet)
printf("Attempting to switch device %04x:%04x to %s mode ",
dev.vendor, dev.product, dev.mode ? "HID" : "HCI");