summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Kwak <kkwak@nvidia.com>2014-06-24 21:35:12 -0700
committerPeter Kim <pekim@nvidia.com>2014-06-25 19:10:43 -0700
commit45619115cebae2d5f3344a08476a1e09ea031c75 (patch)
tree8e9ecf5887ba88b32a795bb769736ef0c4df3c2c
parent4f1670a121947f137aeabf9fd194494e16957b06 (diff)
Revert "HID: Handle driver-specific device descriptor in core"
DO NOT INTEGRATE Bug 1466757 This reverts commit 37ad3e3e97d734e74e071bf5e8796b22e16814e4. Change-Id: I709cd76ccc70aee7d768ace2463b85049cc420f3 Signed-off-by: Kenneth Kwak <kkwak@nvidia.com> Reviewed-on: http://git-master/r/428074 Reviewed-by: Peter Kim <pekim@nvidia.com> Tested-by: Peter Kim <pekim@nvidia.com>
-rw-r--r--drivers/hid/hid-core.c112
-rw-r--r--include/linux/hid.h14
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;
}
/**