diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2014-02-10 12:58:48 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-02-17 08:52:51 -0500 |
commit | 4fa5a7f76cc7b6ac87f57741edd2b124851d119f (patch) | |
tree | 02f12545996a893bf29d788375b8001e27a360e0 /drivers/hid/hid-core.c | |
parent | 706daeffaf36590efc77142f6a209bfe51804f36 (diff) |
HID: core: implement generic .request()
.request() can be emulated through .raw_request()
we can implement this emulation in hid-core, and make .request
not mandatory for transport layer drivers.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 026ab0fc06f7..b6ae69711d2a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1248,6 +1248,11 @@ void hid_output_report(struct hid_report *report, __u8 *data) | |||
1248 | } | 1248 | } |
1249 | EXPORT_SYMBOL_GPL(hid_output_report); | 1249 | EXPORT_SYMBOL_GPL(hid_output_report); |
1250 | 1250 | ||
1251 | static int hid_report_len(struct hid_report *report) | ||
1252 | { | ||
1253 | return ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7; | ||
1254 | } | ||
1255 | |||
1251 | /* | 1256 | /* |
1252 | * Allocator for buffer that is going to be passed to hid_output_report() | 1257 | * Allocator for buffer that is going to be passed to hid_output_report() |
1253 | */ | 1258 | */ |
@@ -1258,7 +1263,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) | |||
1258 | * of implement() working on 8 byte chunks | 1263 | * of implement() working on 8 byte chunks |
1259 | */ | 1264 | */ |
1260 | 1265 | ||
1261 | int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7; | 1266 | int len = hid_report_len(report); |
1262 | 1267 | ||
1263 | return kmalloc(len, flags); | 1268 | return kmalloc(len, flags); |
1264 | } | 1269 | } |
@@ -1314,6 +1319,44 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, | |||
1314 | return report; | 1319 | return report; |
1315 | } | 1320 | } |
1316 | 1321 | ||
1322 | /* | ||
1323 | * Implement a generic .request() callback, using .raw_request() | ||
1324 | * DO NOT USE in hid drivers directly, but through hid_hw_request instead. | ||
1325 | */ | ||
1326 | void __hid_request(struct hid_device *hid, struct hid_report *report, | ||
1327 | int reqtype) | ||
1328 | { | ||
1329 | char *buf; | ||
1330 | int ret; | ||
1331 | int len; | ||
1332 | |||
1333 | if (!hid->ll_driver->raw_request) | ||
1334 | return; | ||
1335 | |||
1336 | buf = hid_alloc_report_buf(report, GFP_KERNEL); | ||
1337 | if (!buf) | ||
1338 | return; | ||
1339 | |||
1340 | len = hid_report_len(report); | ||
1341 | |||
1342 | if (reqtype == HID_REQ_SET_REPORT) | ||
1343 | hid_output_report(report, buf); | ||
1344 | |||
1345 | ret = hid->ll_driver->raw_request(hid, report->id, buf, len, | ||
1346 | report->type, reqtype); | ||
1347 | if (ret < 0) { | ||
1348 | dbg_hid("unable to complete request: %d\n", ret); | ||
1349 | goto out; | ||
1350 | } | ||
1351 | |||
1352 | if (reqtype == HID_REQ_GET_REPORT) | ||
1353 | hid_input_report(hid, report->type, buf, ret, 0); | ||
1354 | |||
1355 | out: | ||
1356 | kfree(buf); | ||
1357 | } | ||
1358 | EXPORT_SYMBOL_GPL(__hid_request); | ||
1359 | |||
1317 | int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, | 1360 | int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, |
1318 | int interrupt) | 1361 | int interrupt) |
1319 | { | 1362 | { |