diff options
-rw-r--r-- | drivers/hid/hid-core.c | 112 | ||||
-rw-r--r-- | include/linux/hid.h | 14 |
2 files changed, 32 insertions, 94 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 521df4d07491..ebb649103fcd 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -546,11 +546,12 @@ static void hid_free_report(struct hid_report *report) } /* - * Close report. This function returns the device - * state to the point prior to hid_open_report(). + * Free a device structure, all reports, and all fields. */ -static void hid_close_report(struct hid_device *device) + +static void hid_device_release(struct device *dev) { + struct hid_device *device = container_of(dev, struct hid_device, dev); unsigned i, j; for (i = 0; i < HID_REPORT_TYPES; i++) { @@ -561,34 +562,11 @@ static void hid_close_report(struct hid_device *device) if (report) hid_free_report(report); } - memset(report_enum, 0, sizeof(*report_enum)); - INIT_LIST_HEAD(&report_enum->report_list); } kfree(device->rdesc); - device->rdesc = NULL; - device->rsize = 0; - kfree(device->collection); - device->collection = NULL; - device->collection_size = 0; - device->maxcollection = 0; - device->maxapplication = 0; - - device->status &= ~HID_STAT_PARSED; -} - -/* - * Free a device structure, all reports, and all fields. - */ - -static void hid_device_release(struct device *dev) -{ - struct hid_device *hid = container_of(dev, struct hid_device, dev); - - hid_close_report(hid); - kfree(hid->dev_rdesc); - kfree(hid); + kfree(device); } /* @@ -665,37 +643,15 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) * @start: report start * @size: report size * - * Allocate the device report as read by the bus driver. This function should - * only be called from parse() in ll drivers. - */ -int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) -{ - hid->dev_rdesc = kmemdup(start, size, GFP_KERNEL); - if (!hid->dev_rdesc) - return -ENOMEM; - hid->dev_rsize = size; - return 0; -} -EXPORT_SYMBOL_GPL(hid_parse_report); - -/** - * hid_open_report - open a driver-specific device report - * - * @device: hid device - * * Parse a report description into a hid_device structure. Reports are * enumerated, fields are attached to these reports. * 0 returned on success, otherwise nonzero error value. - * - * This function (or the equivalent hid_parse() macro) should only be - * called from probe() in drivers, before starting the device. */ -int hid_open_report(struct hid_device *device) +int hid_parse_report(struct hid_device *device, __u8 *start, + unsigned size) { struct hid_parser *parser; struct hid_item item; - unsigned int size; - __u8 *start; __u8 *end; int ret; static int (*dispatch_type[])(struct hid_parser *parser, @@ -706,14 +662,6 @@ int hid_open_report(struct hid_device *device) hid_parser_reserved }; - if (WARN_ON(device->status & HID_STAT_PARSED)) - return -EBUSY; - - start = device->dev_rdesc; - if (WARN_ON(!start)) - return -ENODEV; - size = device->dev_rsize; - if (device->driver->report_fixup) start = device->driver->report_fixup(device, start, &size); @@ -731,15 +679,6 @@ int hid_open_report(struct hid_device *device) parser->device = device; end = start + size; - - device->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS, - sizeof(struct hid_collection), GFP_KERNEL); - if (!device->collection) { - ret = -ENOMEM; - goto err; - } - device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; - ret = -EINVAL; while ((start = fetch_item(start, end, &item)) != NULL) { @@ -765,7 +704,6 @@ int hid_open_report(struct hid_device *device) goto err; } vfree(parser); - device->status |= HID_STAT_PARSED; return 0; } } @@ -773,10 +711,9 @@ int hid_open_report(struct hid_device *device) hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); err: vfree(parser); - hid_close_report(device); return ret; } -EXPORT_SYMBOL_GPL(hid_open_report); +EXPORT_SYMBOL_GPL(hid_parse_report); /* * Convert a signed n-bit integer to signed 32-bit integer. Common @@ -1790,14 +1727,12 @@ static int hid_device_probe(struct device *dev) if (hdrv->probe) { ret = hdrv->probe(hdev, id); } else { /* default probe */ - ret = hid_open_report(hdev); + ret = hid_parse(hdev); if (!ret) ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); } - if (ret) { - hid_close_report(hdev); + if (ret) hdev->driver = NULL; - } } unlock: up(&hdev->driver_lock); @@ -1818,7 +1753,6 @@ static int hid_device_remove(struct device *dev) hdrv->remove(hdev); else /* default remove */ hid_hw_stop(hdev); - hid_close_report(hdev); hdev->driver = NULL; } @@ -2155,16 +2089,6 @@ int hid_add_device(struct hid_device *hdev) && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE))) return -ENODEV; - /* - * Read the device report descriptor once and use as template - * for the driver-specific modifications. - */ - ret = hdev->ll_driver->parse(hdev); - if (ret) - return ret; - if (!hdev->dev_rdesc) - return -ENODEV; - /* XXX hack, any other cleaner solution after the driver core * is converted to allow more than 20 bytes as the device name? */ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, @@ -2193,6 +2117,7 @@ EXPORT_SYMBOL_GPL(hid_add_device); struct hid_device *hid_allocate_device(void) { struct hid_device *hdev; + unsigned int i; int ret = -ENOMEM; hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); @@ -2203,13 +2128,23 @@ struct hid_device *hid_allocate_device(void) hdev->dev.release = hid_device_release; hdev->dev.bus = &hid_bus_type; - hid_close_report(hdev); + hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS, + sizeof(struct hid_collection), GFP_KERNEL); + if (hdev->collection == NULL) + goto err; + hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS; + + for (i = 0; i < HID_REPORT_TYPES; i++) + INIT_LIST_HEAD(&hdev->report_enum[i].report_list); init_waitqueue_head(&hdev->debug_wait); INIT_LIST_HEAD(&hdev->debug_list); sema_init(&hdev->driver_lock, 1); return hdev; +err: + put_device(&hdev->dev); + return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(hid_allocate_device); @@ -2220,9 +2155,6 @@ static void hid_remove_device(struct hid_device *hdev) hid_debug_unregister(hdev); hdev->status &= ~HID_STAT_ADDED; } - kfree(hdev->dev_rdesc); - hdev->dev_rdesc = NULL; - hdev->dev_rsize = 0; } /** diff --git a/include/linux/hid.h b/include/linux/hid.h index f1d71d5ce106..944e21cfc4d6 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -467,8 +467,6 @@ struct hid_driver; struct hid_ll_driver; struct hid_device { /* device report descriptor */ - __u8 *dev_rdesc; - unsigned dev_rsize; __u8 *rdesc; unsigned rsize; struct hid_collection *collection; /* List of HID collections */ @@ -747,7 +745,6 @@ void hid_output_report(struct hid_report *report, __u8 *data); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); -int hid_open_report(struct hid_device *device); int hid_check_keys_pressed(struct hid_device *hid); int hid_connect(struct hid_device *hid, unsigned int connect_mask); void hid_disconnect(struct hid_device *hid); @@ -818,7 +815,16 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput, */ static inline int __must_check hid_parse(struct hid_device *hdev) { - return hid_open_report(hdev); + int ret; + + if (hdev->status & HID_STAT_PARSED) + return 0; + + ret = hdev->ll_driver->parse(hdev); + if (!ret) + hdev->status |= HID_STAT_PARSED; + + return ret; } /** |