diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-04 14:39:00 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-04 14:39:00 -0400 |
| commit | 3366dd9fa887ebbda4872e9554f853eaeda764be (patch) | |
| tree | d1bb553325b276e9d2a1bce99f3e64834b46866b /net | |
| parent | 697a067f1ec67f2f8dfafd0a1b95a46997a11f32 (diff) | |
| parent | 21796b39c9e876a46a353a4a9ff9881766a7c176 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina:
- HID battery handling cleanup by David Herrmann
- ELO 4000/4500 driver, which has been finally ported to be proper HID
driver by Jiri Slaby
- ps3remote driver functionality is now provided by generic sony
driver, by Jiri Kosina
- PS2/3 Buzz controllers support, by Colin Leitner
- rework of wiimote driver including full extensions hotpluggin
support, sub-device modularization and speaker support by David
Herrmann
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (55 commits)
HID: wacom: Intuos4 battery charging changes
HID: i2c-hid: support sending HID output reports using the output register
HID: kye: Add report fixup for Genius Gila Gaming mouse
HID: wiimote: support Nintendo Wii U Pro Controller
Input: make gamepad API keycodes more clear
input: document gamepad API and add extra keycodes
HID: explain out-of-range check better
HID: fix false positive out of range values
HID: wiimote: fix coccinelle warnings
HID: roccat: check cdev_add return value
HID: fold ps3remote driver into generic Sony driver
HID: hyperv: convert alloc+memcpy to memdup
HID: core: fix reporting of raw events
HID: wiimote: discard invalid EXT data reports
HID: wiimote: fix classic controller parsing
HID: wiimote: init EXT/MP during device detection
HID: wiimote: fix DRM debug-attr to correctly parse input
HID: wiimote: add MP quirks
HID: wiimote: remove old static extension support
HID: wiimote: add "bboard_calib" attribute
...
Diffstat (limited to 'net')
| -rw-r--r-- | net/bluetooth/hidp/core.c | 56 | ||||
| -rw-r--r-- | net/bluetooth/hidp/hidp.h | 2 |
2 files changed, 49 insertions, 9 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 940f5acb6694..46c6a148f0b3 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -851,6 +851,29 @@ static void hidp_session_dev_del(struct hidp_session *session) | |||
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | /* | 853 | /* |
| 854 | * Asynchronous device registration | ||
| 855 | * HID device drivers might want to perform I/O during initialization to | ||
| 856 | * detect device types. Therefore, call device registration in a separate | ||
| 857 | * worker so the HIDP thread can schedule I/O operations. | ||
| 858 | * Note that this must be called after the worker thread was initialized | ||
| 859 | * successfully. This will then add the devices and increase session state | ||
| 860 | * on success, otherwise it will terminate the session thread. | ||
| 861 | */ | ||
| 862 | static void hidp_session_dev_work(struct work_struct *work) | ||
| 863 | { | ||
| 864 | struct hidp_session *session = container_of(work, | ||
| 865 | struct hidp_session, | ||
| 866 | dev_init); | ||
| 867 | int ret; | ||
| 868 | |||
| 869 | ret = hidp_session_dev_add(session); | ||
| 870 | if (!ret) | ||
| 871 | atomic_inc(&session->state); | ||
| 872 | else | ||
| 873 | hidp_session_terminate(session); | ||
| 874 | } | ||
| 875 | |||
| 876 | /* | ||
| 854 | * Create new session object | 877 | * Create new session object |
| 855 | * Allocate session object, initialize static fields, copy input data into the | 878 | * Allocate session object, initialize static fields, copy input data into the |
| 856 | * object and take a reference to all sub-objects. | 879 | * object and take a reference to all sub-objects. |
| @@ -897,6 +920,7 @@ static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr, | |||
| 897 | session->idle_to = req->idle_to; | 920 | session->idle_to = req->idle_to; |
| 898 | 921 | ||
| 899 | /* device management */ | 922 | /* device management */ |
| 923 | INIT_WORK(&session->dev_init, hidp_session_dev_work); | ||
| 900 | setup_timer(&session->timer, hidp_idle_timeout, | 924 | setup_timer(&session->timer, hidp_idle_timeout, |
| 901 | (unsigned long)session); | 925 | (unsigned long)session); |
| 902 | 926 | ||
| @@ -1035,8 +1059,8 @@ static void hidp_session_terminate(struct hidp_session *session) | |||
| 1035 | * Probe HIDP session | 1059 | * Probe HIDP session |
| 1036 | * This is called from the l2cap_conn core when our l2cap_user object is bound | 1060 | * This is called from the l2cap_conn core when our l2cap_user object is bound |
| 1037 | * to the hci-connection. We get the session via the \user object and can now | 1061 | * to the hci-connection. We get the session via the \user object and can now |
| 1038 | * start the session thread, register the HID/input devices and link it into | 1062 | * start the session thread, link it into the global session list and |
| 1039 | * the global session list. | 1063 | * schedule HID/input device registration. |
| 1040 | * The global session-list owns its own reference to the session object so you | 1064 | * The global session-list owns its own reference to the session object so you |
| 1041 | * can drop your own reference after registering the l2cap_user object. | 1065 | * can drop your own reference after registering the l2cap_user object. |
| 1042 | */ | 1066 | */ |
| @@ -1058,21 +1082,30 @@ static int hidp_session_probe(struct l2cap_conn *conn, | |||
| 1058 | goto out_unlock; | 1082 | goto out_unlock; |
| 1059 | } | 1083 | } |
| 1060 | 1084 | ||
| 1085 | if (session->input) { | ||
| 1086 | ret = hidp_session_dev_add(session); | ||
| 1087 | if (ret) | ||
| 1088 | goto out_unlock; | ||
| 1089 | } | ||
| 1090 | |||
| 1061 | ret = hidp_session_start_sync(session); | 1091 | ret = hidp_session_start_sync(session); |
| 1062 | if (ret) | 1092 | if (ret) |
| 1063 | goto out_unlock; | 1093 | goto out_del; |
| 1064 | 1094 | ||
| 1065 | ret = hidp_session_dev_add(session); | 1095 | /* HID device registration is async to allow I/O during probe */ |
| 1066 | if (ret) | 1096 | if (session->input) |
| 1067 | goto out_stop; | 1097 | atomic_inc(&session->state); |
| 1098 | else | ||
| 1099 | schedule_work(&session->dev_init); | ||
| 1068 | 1100 | ||
| 1069 | hidp_session_get(session); | 1101 | hidp_session_get(session); |
| 1070 | list_add(&session->list, &hidp_session_list); | 1102 | list_add(&session->list, &hidp_session_list); |
| 1071 | ret = 0; | 1103 | ret = 0; |
| 1072 | goto out_unlock; | 1104 | goto out_unlock; |
| 1073 | 1105 | ||
| 1074 | out_stop: | 1106 | out_del: |
| 1075 | hidp_session_terminate(session); | 1107 | if (session->input) |
| 1108 | hidp_session_dev_del(session); | ||
| 1076 | out_unlock: | 1109 | out_unlock: |
| 1077 | up_write(&hidp_session_sem); | 1110 | up_write(&hidp_session_sem); |
| 1078 | return ret; | 1111 | return ret; |
| @@ -1102,7 +1135,12 @@ static void hidp_session_remove(struct l2cap_conn *conn, | |||
| 1102 | down_write(&hidp_session_sem); | 1135 | down_write(&hidp_session_sem); |
| 1103 | 1136 | ||
| 1104 | hidp_session_terminate(session); | 1137 | hidp_session_terminate(session); |
| 1105 | hidp_session_dev_del(session); | 1138 | |
| 1139 | cancel_work_sync(&session->dev_init); | ||
| 1140 | if (session->input || | ||
| 1141 | atomic_read(&session->state) > HIDP_SESSION_PREPARING) | ||
| 1142 | hidp_session_dev_del(session); | ||
| 1143 | |||
| 1106 | list_del(&session->list); | 1144 | list_del(&session->list); |
| 1107 | 1145 | ||
| 1108 | up_write(&hidp_session_sem); | 1146 | up_write(&hidp_session_sem); |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 6162ce8606ac..9e6cc3553105 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
| @@ -128,6 +128,7 @@ int hidp_get_conninfo(struct hidp_conninfo *ci); | |||
| 128 | 128 | ||
| 129 | enum hidp_session_state { | 129 | enum hidp_session_state { |
| 130 | HIDP_SESSION_IDLING, | 130 | HIDP_SESSION_IDLING, |
| 131 | HIDP_SESSION_PREPARING, | ||
| 131 | HIDP_SESSION_RUNNING, | 132 | HIDP_SESSION_RUNNING, |
| 132 | }; | 133 | }; |
| 133 | 134 | ||
| @@ -156,6 +157,7 @@ struct hidp_session { | |||
| 156 | unsigned long idle_to; | 157 | unsigned long idle_to; |
| 157 | 158 | ||
| 158 | /* device management */ | 159 | /* device management */ |
| 160 | struct work_struct dev_init; | ||
| 159 | struct input_dev *input; | 161 | struct input_dev *input; |
| 160 | struct hid_device *hid; | 162 | struct hid_device *hid; |
| 161 | struct timer_list timer; | 163 | struct timer_list timer; |
