aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-02-10 12:58:48 -0500
committerJiri Kosina <jkosina@suse.cz>2014-02-17 08:52:51 -0500
commit4fa5a7f76cc7b6ac87f57741edd2b124851d119f (patch)
tree02f12545996a893bf29d788375b8001e27a360e0
parent706daeffaf36590efc77142f6a209bfe51804f36 (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>
-rw-r--r--drivers/hid/hid-core.c45
-rw-r--r--include/linux/hid.h5
2 files changed, 48 insertions, 2 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}
1249EXPORT_SYMBOL_GPL(hid_output_report); 1249EXPORT_SYMBOL_GPL(hid_output_report);
1250 1250
1251static 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 */
1326void __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
1355out:
1356 kfree(buf);
1357}
1358EXPORT_SYMBOL_GPL(__hid_request);
1359
1317int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, 1360int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
1318 int interrupt) 1361 int interrupt)
1319{ 1362{
diff --git a/include/linux/hid.h b/include/linux/hid.h
index a837ede65ec6..09fbbd7fb784 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -753,6 +753,7 @@ struct hid_field *hidinput_get_led_field(struct hid_device *hid);
753unsigned int hidinput_count_leds(struct hid_device *hid); 753unsigned int hidinput_count_leds(struct hid_device *hid);
754__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); 754__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
755void hid_output_report(struct hid_report *report, __u8 *data); 755void hid_output_report(struct hid_report *report, __u8 *data);
756void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype);
756u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); 757u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
757struct hid_device *hid_allocate_device(void); 758struct hid_device *hid_allocate_device(void);
758struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); 759struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
@@ -965,7 +966,9 @@ static inline void hid_hw_request(struct hid_device *hdev,
965 struct hid_report *report, int reqtype) 966 struct hid_report *report, int reqtype)
966{ 967{
967 if (hdev->ll_driver->request) 968 if (hdev->ll_driver->request)
968 hdev->ll_driver->request(hdev, report, reqtype); 969 return hdev->ll_driver->request(hdev, report, reqtype);
970
971 __hid_request(hdev, report, reqtype);
969} 972}
970 973
971/** 974/**