Hi Kay: Kay Sievers wrote: > > What the action you want to take at removal? You can set > ENV{REMOVE_CMD}= and it will be passed to RUN+= for that exact device > when it goes away. > > You can also just store any other custom property in the udev > database, and it will be there on remove. > Thanks for the recommendation on ENV{REMOVE_CMD}. With some minor modifications to my old patch, I've got it working using ENV{REMOVE_CMD} now reliably post suspend. Although rewalking the child devices to find the right one to prod might seem tedious, it should be more future-proof in case later hardware ends up changing. Would you mind reviewing the attached patch for submission to udev then? Thanks, -- Mario Limonciello *Dell | Linux Engineering* mario_limonciello@xxxxxxxx
=== modified file 'extras/hid2hci/70-hid2hci.rules' --- extras/hid2hci/70-hid2hci.rules 2009-06-26 06:17:23 +0000 +++ extras/hid2hci/70-hid2hci.rules 2009-07-14 17:25:17 +0000 @@ -11,6 +11,17 @@ 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 +# Well, unfortunately the only event we see is the BT device disappearing, so +# we have to run with that and chase down the mouse device on USB bus as a child. +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 === modified file 'extras/hid2hci/hid2hci.c' --- extras/hid2hci/hid2hci.c 2009-06-16 17:30:22 +0000 +++ extras/hid2hci/hid2hci.c 2009-07-14 17:20:01 +0000 @@ -271,6 +271,28 @@ return 0; } +static struct usb_device* find_resuscitated_device(uint16_t base_vendor, uint16_t base_product, uint8_t bInterfaceProtocol) +{ + struct usb_bus *bus; + struct usb_device *dev; + int i,j,k,l; + + usb_find_busses(); + usb_find_devices(); + + for (bus = usb_get_busses(); bus; bus = bus->next) + for (dev = bus->devices; dev; dev = dev->next) + if (dev->descriptor.idVendor == base_vendor && + dev->descriptor.idProduct == base_product) + for (i = 0; i < dev->num_children; i++) + for (j = 0; j < dev->children[i]->descriptor.bNumConfigurations; j++) + for (k = 0; k < dev->children[i]->config[j].bNumInterfaces; k++) + for (l = 0; l < dev->children[i]->config[j].interface[k].num_altsetting; l++) + if (dev->children[i]->config[j].interface[k].altsetting[l].bInterfaceProtocol == bInterfaceProtocol) + return dev->children[i]; + return NULL; +} + static void usage(char* error) { if (error) @@ -289,6 +311,7 @@ "\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 +324,7 @@ { "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 +333,9 @@ 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 +364,9 @@ case 'q': quiet = 1; break; + case 's': + sscanf(optarg, "%2hx", (short unsigned int*) &resuscitate); + break; case 'h': usage(NULL); default: @@ -355,7 +383,16 @@ usb_init(); - if (!find_device(&dev)) { + if (resuscitate) { + dev.dev = find_resuscitated_device(dev.vendor, dev.product, resuscitate); + if (!quiet && !dev.dev) { + fprintf(stderr, "Device %04x:%04x was unable to resucitate any child devices.\n",dev.vendor,dev.product); + exit(1); + } + dev.vendor = dev.dev->descriptor.idVendor; + dev.product = dev.dev->descriptor.idProduct; + } + else if (!find_device(&dev)) { if (!quiet) fprintf(stderr, "Device %04x:%04x not found on USB bus.\n", dev.vendor, dev.product);
Attachment:
signature.asc
Description: OpenPGP digital signature