diff options
author | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 13:05:09 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 13:05:09 -0400 |
commit | ad295b6d5739ab24880a31be403bbc8fab62e177 (patch) | |
tree | cd760a18bcfa6e59b8b63fc71e333ba394b1cd9c /drivers/hid/hid-core.c | |
parent | ba04a57b4acd05a764471b2accd02000f6641881 (diff) | |
parent | c3d77fab51f40821de91a744e4b514e9e4e76a7c (diff) |
Merge branch 'for-3.15/hid-core-ll-transport-cleanup' into for-linus
Conflicts:
drivers/hid/hid-ids.h
drivers/hid/hid-sony.c
drivers/hid/i2c-hid/i2c-hid.c
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f36b3524caf1..3736f6a121b7 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,41 @@ 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 | buf = hid_alloc_report_buf(report, GFP_KERNEL); | ||
1334 | if (!buf) | ||
1335 | return; | ||
1336 | |||
1337 | len = hid_report_len(report); | ||
1338 | |||
1339 | if (reqtype == HID_REQ_SET_REPORT) | ||
1340 | hid_output_report(report, buf); | ||
1341 | |||
1342 | ret = hid->ll_driver->raw_request(hid, report->id, buf, len, | ||
1343 | report->type, reqtype); | ||
1344 | if (ret < 0) { | ||
1345 | dbg_hid("unable to complete request: %d\n", ret); | ||
1346 | goto out; | ||
1347 | } | ||
1348 | |||
1349 | if (reqtype == HID_REQ_GET_REPORT) | ||
1350 | hid_input_report(hid, report->type, buf, ret, 0); | ||
1351 | |||
1352 | out: | ||
1353 | kfree(buf); | ||
1354 | } | ||
1355 | EXPORT_SYMBOL_GPL(__hid_request); | ||
1356 | |||
1317 | int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, | 1357 | int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, |
1318 | int interrupt) | 1358 | int interrupt) |
1319 | { | 1359 | { |
@@ -1693,6 +1733,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1693 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, | 1733 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, |
1694 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, | 1734 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, |
1695 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, | 1735 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, |
1736 | { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, | ||
1696 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1737 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
1697 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1738 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
1698 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, | 1739 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, |
@@ -2432,6 +2473,14 @@ int hid_add_device(struct hid_device *hdev) | |||
2432 | return -ENODEV; | 2473 | return -ENODEV; |
2433 | 2474 | ||
2434 | /* | 2475 | /* |
2476 | * Check for the mandatory transport channel. | ||
2477 | */ | ||
2478 | if (!hdev->ll_driver->raw_request) { | ||
2479 | hid_err(hdev, "transport driver missing .raw_request()\n"); | ||
2480 | return -EINVAL; | ||
2481 | } | ||
2482 | |||
2483 | /* | ||
2435 | * Read the device report descriptor once and use as template | 2484 | * Read the device report descriptor once and use as template |
2436 | * for the driver-specific modifications. | 2485 | * for the driver-specific modifications. |
2437 | */ | 2486 | */ |