From: Mario Limonciello Date: Tue, 21 Jul 2009 22:33:27 +0000 (+0200) Subject: hid2hci: support to hid2hci for recovering Dell BT devices after S3 X-Git-Tag: 174~880 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bacd2aadc854a0c01934bab76d4f575543d361e;p=systemd hid2hci: support to hid2hci for recovering Dell BT devices after S3 --- diff --git a/extras/hid2hci/70-hid2hci.rules b/extras/hid2hci/70-hid2hci.rules index caf9120f..47eec00a 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 aa44790f..469f8709 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");