diff options
author | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 12:56:24 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 12:56:24 -0400 |
commit | ee5f68e6c2f183e6aade0e9c57af13d5eff44f2f (patch) | |
tree | de4132918ec7b033c4981e2ba4aea9027816bdb9 | |
parent | f74346a04b79c9a5e50a2ee5e923b94195975d17 (diff) | |
parent | 0a7f364e812285246cd617a51194a3f8bd0e8daa (diff) |
Merge branch 'for-3.15/ll-driver-new-callbacks' into for-linus
-rw-r--r-- | drivers/hid/uhid.c | 27 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 78 | ||||
-rw-r--r-- | include/linux/hid.h | 8 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 90 |
4 files changed, 202 insertions, 1 deletions
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index cedc6da93c19..f5a2b1931143 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c | |||
@@ -244,12 +244,39 @@ static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count, | |||
244 | return count; | 244 | return count; |
245 | } | 245 | } |
246 | 246 | ||
247 | static int uhid_hid_output_report(struct hid_device *hid, __u8 *buf, | ||
248 | size_t count) | ||
249 | { | ||
250 | struct uhid_device *uhid = hid->driver_data; | ||
251 | unsigned long flags; | ||
252 | struct uhid_event *ev; | ||
253 | |||
254 | if (count < 1 || count > UHID_DATA_MAX) | ||
255 | return -EINVAL; | ||
256 | |||
257 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); | ||
258 | if (!ev) | ||
259 | return -ENOMEM; | ||
260 | |||
261 | ev->type = UHID_OUTPUT; | ||
262 | ev->u.output.size = count; | ||
263 | ev->u.output.rtype = UHID_OUTPUT_REPORT; | ||
264 | memcpy(ev->u.output.data, buf, count); | ||
265 | |||
266 | spin_lock_irqsave(&uhid->qlock, flags); | ||
267 | uhid_queue(uhid, ev); | ||
268 | spin_unlock_irqrestore(&uhid->qlock, flags); | ||
269 | |||
270 | return count; | ||
271 | } | ||
272 | |||
247 | static struct hid_ll_driver uhid_hid_driver = { | 273 | static struct hid_ll_driver uhid_hid_driver = { |
248 | .start = uhid_hid_start, | 274 | .start = uhid_hid_start, |
249 | .stop = uhid_hid_stop, | 275 | .stop = uhid_hid_stop, |
250 | .open = uhid_hid_open, | 276 | .open = uhid_hid_open, |
251 | .close = uhid_hid_close, | 277 | .close = uhid_hid_close, |
252 | .parse = uhid_hid_parse, | 278 | .parse = uhid_hid_parse, |
279 | .output_report = uhid_hid_output_report, | ||
253 | }; | 280 | }; |
254 | 281 | ||
255 | #ifdef CONFIG_COMPAT | 282 | #ifdef CONFIG_COMPAT |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 44df131d390a..f8ca312bae1b 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -884,6 +884,38 @@ static int usbhid_get_raw_report(struct hid_device *hid, | |||
884 | return ret; | 884 | return ret; |
885 | } | 885 | } |
886 | 886 | ||
887 | static int usbhid_set_raw_report(struct hid_device *hid, unsigned int reportnum, | ||
888 | __u8 *buf, size_t count, unsigned char rtype) | ||
889 | { | ||
890 | struct usbhid_device *usbhid = hid->driver_data; | ||
891 | struct usb_device *dev = hid_to_usb_dev(hid); | ||
892 | struct usb_interface *intf = usbhid->intf; | ||
893 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
894 | int ret, skipped_report_id = 0; | ||
895 | |||
896 | /* Byte 0 is the report number. Report data starts at byte 1.*/ | ||
897 | buf[0] = reportnum; | ||
898 | if (buf[0] == 0x0) { | ||
899 | /* Don't send the Report ID */ | ||
900 | buf++; | ||
901 | count--; | ||
902 | skipped_report_id = 1; | ||
903 | } | ||
904 | |||
905 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
906 | HID_REQ_SET_REPORT, | ||
907 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
908 | ((rtype + 1) << 8) | reportnum, | ||
909 | interface->desc.bInterfaceNumber, buf, count, | ||
910 | USB_CTRL_SET_TIMEOUT); | ||
911 | /* count also the report id, if this was a numbered report. */ | ||
912 | if (ret > 0 && skipped_report_id) | ||
913 | ret++; | ||
914 | |||
915 | return ret; | ||
916 | } | ||
917 | |||
918 | |||
887 | static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, | 919 | static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, |
888 | unsigned char report_type) | 920 | unsigned char report_type) |
889 | { | 921 | { |
@@ -936,6 +968,36 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
936 | return ret; | 968 | return ret; |
937 | } | 969 | } |
938 | 970 | ||
971 | static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count) | ||
972 | { | ||
973 | struct usbhid_device *usbhid = hid->driver_data; | ||
974 | struct usb_device *dev = hid_to_usb_dev(hid); | ||
975 | int actual_length, skipped_report_id = 0, ret; | ||
976 | |||
977 | if (!usbhid->urbout) | ||
978 | return -EIO; | ||
979 | |||
980 | if (buf[0] == 0x0) { | ||
981 | /* Don't send the Report ID */ | ||
982 | buf++; | ||
983 | count--; | ||
984 | skipped_report_id = 1; | ||
985 | } | ||
986 | |||
987 | ret = usb_interrupt_msg(dev, usbhid->urbout->pipe, | ||
988 | buf, count, &actual_length, | ||
989 | USB_CTRL_SET_TIMEOUT); | ||
990 | /* return the number of bytes transferred */ | ||
991 | if (ret == 0) { | ||
992 | ret = actual_length; | ||
993 | /* count also the report id */ | ||
994 | if (skipped_report_id) | ||
995 | ret++; | ||
996 | } | ||
997 | |||
998 | return ret; | ||
999 | } | ||
1000 | |||
939 | static void usbhid_restart_queues(struct usbhid_device *usbhid) | 1001 | static void usbhid_restart_queues(struct usbhid_device *usbhid) |
940 | { | 1002 | { |
941 | if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)) | 1003 | if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)) |
@@ -1200,6 +1262,20 @@ static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int r | |||
1200 | } | 1262 | } |
1201 | } | 1263 | } |
1202 | 1264 | ||
1265 | static int usbhid_raw_request(struct hid_device *hid, unsigned char reportnum, | ||
1266 | __u8 *buf, size_t len, unsigned char rtype, | ||
1267 | int reqtype) | ||
1268 | { | ||
1269 | switch (reqtype) { | ||
1270 | case HID_REQ_GET_REPORT: | ||
1271 | return usbhid_get_raw_report(hid, reportnum, buf, len, rtype); | ||
1272 | case HID_REQ_SET_REPORT: | ||
1273 | return usbhid_set_raw_report(hid, reportnum, buf, len, rtype); | ||
1274 | default: | ||
1275 | return -EIO; | ||
1276 | } | ||
1277 | } | ||
1278 | |||
1203 | static int usbhid_idle(struct hid_device *hid, int report, int idle, | 1279 | static int usbhid_idle(struct hid_device *hid, int report, int idle, |
1204 | int reqtype) | 1280 | int reqtype) |
1205 | { | 1281 | { |
@@ -1223,6 +1299,8 @@ static struct hid_ll_driver usb_hid_driver = { | |||
1223 | .power = usbhid_power, | 1299 | .power = usbhid_power, |
1224 | .request = usbhid_request, | 1300 | .request = usbhid_request, |
1225 | .wait = usbhid_wait_io, | 1301 | .wait = usbhid_wait_io, |
1302 | .raw_request = usbhid_raw_request, | ||
1303 | .output_report = usbhid_output_report, | ||
1226 | .idle = usbhid_idle, | 1304 | .idle = usbhid_idle, |
1227 | }; | 1305 | }; |
1228 | 1306 | ||
diff --git a/include/linux/hid.h b/include/linux/hid.h index 31b9d299ef6c..003cc8e89831 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -700,8 +700,14 @@ struct hid_ll_driver { | |||
700 | struct hid_report *report, int reqtype); | 700 | struct hid_report *report, int reqtype); |
701 | 701 | ||
702 | int (*wait)(struct hid_device *hdev); | 702 | int (*wait)(struct hid_device *hdev); |
703 | int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype); | ||
704 | 703 | ||
704 | int (*raw_request) (struct hid_device *hdev, unsigned char reportnum, | ||
705 | __u8 *buf, size_t len, unsigned char rtype, | ||
706 | int reqtype); | ||
707 | |||
708 | int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len); | ||
709 | |||
710 | int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype); | ||
705 | }; | 711 | }; |
706 | 712 | ||
707 | #define PM_HINT_FULLON 1<<5 | 713 | #define PM_HINT_FULLON 1<<5 |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index d9fb93451442..450a0b999614 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -353,6 +353,71 @@ err: | |||
353 | return ret; | 353 | return ret; |
354 | } | 354 | } |
355 | 355 | ||
356 | static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum, | ||
357 | unsigned char *data, size_t count, | ||
358 | unsigned char report_type) | ||
359 | { | ||
360 | struct hidp_session *session = hid->driver_data; | ||
361 | int ret; | ||
362 | |||
363 | switch (report_type) { | ||
364 | case HID_FEATURE_REPORT: | ||
365 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; | ||
366 | break; | ||
367 | case HID_INPUT_REPORT: | ||
368 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_INPUT; | ||
369 | break; | ||
370 | case HID_OUTPUT_REPORT: | ||
371 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT; | ||
372 | break; | ||
373 | default: | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | |||
377 | if (mutex_lock_interruptible(&session->report_mutex)) | ||
378 | return -ERESTARTSYS; | ||
379 | |||
380 | /* Set up our wait, and send the report request to the device. */ | ||
381 | data[0] = reportnum; | ||
382 | set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); | ||
383 | ret = hidp_send_ctrl_message(session, report_type, data, count); | ||
384 | if (ret) | ||
385 | goto err; | ||
386 | |||
387 | /* Wait for the ACK from the device. */ | ||
388 | while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) && | ||
389 | !atomic_read(&session->terminate)) { | ||
390 | int res; | ||
391 | |||
392 | res = wait_event_interruptible_timeout(session->report_queue, | ||
393 | !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) | ||
394 | || atomic_read(&session->terminate), | ||
395 | 10*HZ); | ||
396 | if (res == 0) { | ||
397 | /* timeout */ | ||
398 | ret = -EIO; | ||
399 | goto err; | ||
400 | } | ||
401 | if (res < 0) { | ||
402 | /* signal */ | ||
403 | ret = -ERESTARTSYS; | ||
404 | goto err; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | if (!session->output_report_success) { | ||
409 | ret = -EIO; | ||
410 | goto err; | ||
411 | } | ||
412 | |||
413 | ret = count; | ||
414 | |||
415 | err: | ||
416 | clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); | ||
417 | mutex_unlock(&session->report_mutex); | ||
418 | return ret; | ||
419 | } | ||
420 | |||
356 | static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, | 421 | static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, |
357 | unsigned char report_type) | 422 | unsigned char report_type) |
358 | { | 423 | { |
@@ -411,6 +476,29 @@ err: | |||
411 | return ret; | 476 | return ret; |
412 | } | 477 | } |
413 | 478 | ||
479 | static int hidp_raw_request(struct hid_device *hid, unsigned char reportnum, | ||
480 | __u8 *buf, size_t len, unsigned char rtype, | ||
481 | int reqtype) | ||
482 | { | ||
483 | switch (reqtype) { | ||
484 | case HID_REQ_GET_REPORT: | ||
485 | return hidp_get_raw_report(hid, reportnum, buf, len, rtype); | ||
486 | case HID_REQ_SET_REPORT: | ||
487 | return hidp_set_raw_report(hid, reportnum, buf, len, rtype); | ||
488 | default: | ||
489 | return -EIO; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | static int hidp_output_report(struct hid_device *hid, __u8 *data, size_t count) | ||
494 | { | ||
495 | struct hidp_session *session = hid->driver_data; | ||
496 | |||
497 | return hidp_send_intr_message(session, | ||
498 | HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT, | ||
499 | data, count); | ||
500 | } | ||
501 | |||
414 | static void hidp_idle_timeout(unsigned long arg) | 502 | static void hidp_idle_timeout(unsigned long arg) |
415 | { | 503 | { |
416 | struct hidp_session *session = (struct hidp_session *) arg; | 504 | struct hidp_session *session = (struct hidp_session *) arg; |
@@ -739,6 +827,8 @@ static struct hid_ll_driver hidp_hid_driver = { | |||
739 | .stop = hidp_stop, | 827 | .stop = hidp_stop, |
740 | .open = hidp_open, | 828 | .open = hidp_open, |
741 | .close = hidp_close, | 829 | .close = hidp_close, |
830 | .raw_request = hidp_raw_request, | ||
831 | .output_report = hidp_output_report, | ||
742 | .hidinput_input_event = hidp_hidinput_event, | 832 | .hidinput_input_event = hidp_hidinput_event, |
743 | }; | 833 | }; |
744 | 834 | ||