From d5af7099c1e90231743ede48a83d2b82a440c2e4 Mon Sep 17 00:00:00 2001 From: Kai Wang Date: Sat, 20 Oct 2012 18:29:38 +0000 Subject: [PATCH] Reworked r213: check kernel driver after "driver match" but before "driver attach". In this way uhidd will not allocate resources for the device interface it won't attach later due to active kernel driver. --- uhidd/uhidd.c | 38 ++++++++++++++++++++++++-------------- uhidd/uhidd.h | 1 + uhidd/uhidd_hidcore.c | 10 +++++++--- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/uhidd/uhidd.c b/uhidd/uhidd.c index 3339fa6..2516a4b 100644 --- a/uhidd/uhidd.c +++ b/uhidd/uhidd.c @@ -502,24 +502,19 @@ alloc_hid_interface_be(struct hid_interface *hi) return (0); } -static void * -start_hid_interface(void *arg) +int +hid_handle_kernel_driver(struct hid_parser *hp) { struct hid_interface *hi; struct libusb20_device *pdev; - struct libusb20_transfer *xfer; - char buf[4096]; - uint32_t actlen; - uint8_t x; - int e, i, ndx; - - hi = arg; - assert(hi != NULL); + int ndx; /* * Check if any kernel driver is attached to this interface. */ + hi = hid_parser_get_private(hp); + assert(hi != NULL); pdev = hi->pdev; ndx = hi->ndx; if (libusb20_dev_kernel_driver_active(pdev, ndx) == 0) { @@ -529,17 +524,32 @@ start_hid_interface(void *arg) PRINT1("Unable to detach kernel driver: " "libusb20_dev_detach_kernel_driver " "failed\n"); - return (NULL); + return (-1); } else PRINT1("kernel driver detached!\n"); } else { PRINT1("Abort attach since kernel driver is active\n"); PRINT1("Please try running uhidd with option '-u' to " "detach the kernel drivers\n"); - return (NULL); + return (-1); } - } else - PRINT1("Kernel driver is not active\n"); + } + + return (0); +} + +static void * +start_hid_interface(void *arg) +{ + struct hid_interface *hi; + struct libusb20_transfer *xfer; + char buf[4096]; + uint32_t actlen; + uint8_t x; + int e, i; + + hi = arg; + assert(hi != NULL); /* * Start receiving data from the endpoint. diff --git a/uhidd/uhidd.h b/uhidd/uhidd.h index b745f0a..87d2d3d 100644 --- a/uhidd/uhidd.h +++ b/uhidd/uhidd.h @@ -299,6 +299,7 @@ void hid_field_get_usage_value(struct hid_field *, int, int hid_field_get_usage_min(struct hid_field *); int hid_field_get_usage_max(struct hid_field *); void hid_field_set_value(struct hid_field *, int, int); +int hid_handle_kernel_driver(struct hid_parser *); int kbd_match(struct hid_appcol *); int kbd_attach(struct hid_appcol *); void kbd_input(struct hid_appcol *, uint8_t, uint16_t *, int); diff --git a/uhidd/uhidd_hidcore.c b/uhidd/uhidd_hidcore.c index b20eb17..f314b56 100644 --- a/uhidd/uhidd_hidcore.c +++ b/uhidd/uhidd_hidcore.c @@ -144,9 +144,13 @@ hid_parser_attach_drivers(struct hid_parser *hp) } } } - if (mhd != NULL && mhd->ha_drv_attach(ha) == 0) { - ha->ha_drv = mhd; - hp->hp_attached++; + if (mhd != NULL) { + if (hid_handle_kernel_driver(hp) < 0) + break; + if (mhd->ha_drv_attach(ha) == 0) { + ha->ha_drv = mhd; + hp->hp_attached++; + } } } }