diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-04-06 14:28:50 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-04-17 02:04:08 -0400 |
commit | 41edc0c034160408feaa78c9a50cc5e91a5928c7 (patch) | |
tree | 5717a0106d1bb5549e9386d79a746a5cea5f44d3 /net/bluetooth/hidp | |
parent | 7350e6cf360d32206cbe4e3d34fb48ab863bdb14 (diff) |
Bluetooth: hidp: merge 'send' functions into hidp_send_message()
We handle skb buffers all over the place, even though we have
hidp_send_*_message() helpers. This creates a more generic
hidp_send_message() helper and uses it instead of dealing with transmit
queues directly everywhere.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth/hidp')
-rw-r--r-- | net/bluetooth/hidp/core.c | 156 |
1 files changed, 60 insertions, 96 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 8f81379e9907..5fcc0389d929 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -68,15 +68,6 @@ static void hidp_session_remove(struct l2cap_conn *conn, | |||
68 | static int hidp_session_thread(void *arg); | 68 | static int hidp_session_thread(void *arg); |
69 | static void hidp_session_terminate(struct hidp_session *s); | 69 | static void hidp_session_terminate(struct hidp_session *s); |
70 | 70 | ||
71 | static inline void hidp_schedule(struct hidp_session *session) | ||
72 | { | ||
73 | struct sock *ctrl_sk = session->ctrl_sock->sk; | ||
74 | struct sock *intr_sk = session->intr_sock->sk; | ||
75 | |||
76 | wake_up_interruptible(sk_sleep(ctrl_sk)); | ||
77 | wake_up_interruptible(sk_sleep(intr_sk)); | ||
78 | } | ||
79 | |||
80 | static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci) | 71 | static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci) |
81 | { | 72 | { |
82 | memset(ci, 0, sizeof(*ci)); | 73 | memset(ci, 0, sizeof(*ci)); |
@@ -107,11 +98,56 @@ static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo | |||
107 | } | 98 | } |
108 | } | 99 | } |
109 | 100 | ||
101 | /* assemble skb, queue message on @transmit and wake up the session thread */ | ||
102 | static int hidp_send_message(struct hidp_session *session, struct socket *sock, | ||
103 | struct sk_buff_head *transmit, unsigned char hdr, | ||
104 | const unsigned char *data, int size) | ||
105 | { | ||
106 | struct sk_buff *skb; | ||
107 | struct sock *sk = sock->sk; | ||
108 | |||
109 | BT_DBG("session %p data %p size %d", session, data, size); | ||
110 | |||
111 | if (atomic_read(&session->terminate)) | ||
112 | return -EIO; | ||
113 | |||
114 | skb = alloc_skb(size + 1, GFP_ATOMIC); | ||
115 | if (!skb) { | ||
116 | BT_ERR("Can't allocate memory for new frame"); | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | |||
120 | *skb_put(skb, 1) = hdr; | ||
121 | if (data && size > 0) | ||
122 | memcpy(skb_put(skb, size), data, size); | ||
123 | |||
124 | skb_queue_tail(transmit, skb); | ||
125 | wake_up_interruptible(sk_sleep(sk)); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int hidp_send_ctrl_message(struct hidp_session *session, | ||
131 | unsigned char hdr, const unsigned char *data, | ||
132 | int size) | ||
133 | { | ||
134 | return hidp_send_message(session, session->ctrl_sock, | ||
135 | &session->ctrl_transmit, hdr, data, size); | ||
136 | } | ||
137 | |||
138 | static int hidp_send_intr_message(struct hidp_session *session, | ||
139 | unsigned char hdr, const unsigned char *data, | ||
140 | int size) | ||
141 | { | ||
142 | return hidp_send_message(session, session->intr_sock, | ||
143 | &session->intr_transmit, hdr, data, size); | ||
144 | } | ||
145 | |||
110 | static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev, | 146 | static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev, |
111 | unsigned int type, unsigned int code, int value) | 147 | unsigned int type, unsigned int code, int value) |
112 | { | 148 | { |
113 | unsigned char newleds; | 149 | unsigned char newleds; |
114 | struct sk_buff *skb; | 150 | unsigned char hdr, data[2]; |
115 | 151 | ||
116 | BT_DBG("session %p type %d code %d value %d", session, type, code, value); | 152 | BT_DBG("session %p type %d code %d value %d", session, type, code, value); |
117 | 153 | ||
@@ -129,21 +165,11 @@ static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev, | |||
129 | 165 | ||
130 | session->leds = newleds; | 166 | session->leds = newleds; |
131 | 167 | ||
132 | skb = alloc_skb(3, GFP_ATOMIC); | 168 | hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; |
133 | if (!skb) { | 169 | data[0] = 0x01; |
134 | BT_ERR("Can't allocate memory for new frame"); | 170 | data[1] = newleds; |
135 | return -ENOMEM; | ||
136 | } | ||
137 | |||
138 | *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; | ||
139 | *skb_put(skb, 1) = 0x01; | ||
140 | *skb_put(skb, 1) = newleds; | ||
141 | |||
142 | skb_queue_tail(&session->intr_transmit, skb); | ||
143 | 171 | ||
144 | hidp_schedule(session); | 172 | return hidp_send_intr_message(session, hdr, data, 2); |
145 | |||
146 | return 0; | ||
147 | } | 173 | } |
148 | 174 | ||
149 | static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 175 | static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
@@ -216,71 +242,9 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) | |||
216 | input_sync(dev); | 242 | input_sync(dev); |
217 | } | 243 | } |
218 | 244 | ||
219 | static int __hidp_send_ctrl_message(struct hidp_session *session, | ||
220 | unsigned char hdr, unsigned char *data, | ||
221 | int size) | ||
222 | { | ||
223 | struct sk_buff *skb; | ||
224 | |||
225 | BT_DBG("session %p data %p size %d", session, data, size); | ||
226 | |||
227 | if (atomic_read(&session->terminate)) | ||
228 | return -EIO; | ||
229 | |||
230 | skb = alloc_skb(size + 1, GFP_ATOMIC); | ||
231 | if (!skb) { | ||
232 | BT_ERR("Can't allocate memory for new frame"); | ||
233 | return -ENOMEM; | ||
234 | } | ||
235 | |||
236 | *skb_put(skb, 1) = hdr; | ||
237 | if (data && size > 0) | ||
238 | memcpy(skb_put(skb, size), data, size); | ||
239 | |||
240 | skb_queue_tail(&session->ctrl_transmit, skb); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int hidp_send_ctrl_message(struct hidp_session *session, | ||
246 | unsigned char hdr, unsigned char *data, int size) | ||
247 | { | ||
248 | int err; | ||
249 | |||
250 | err = __hidp_send_ctrl_message(session, hdr, data, size); | ||
251 | |||
252 | hidp_schedule(session); | ||
253 | |||
254 | return err; | ||
255 | } | ||
256 | |||
257 | static int hidp_queue_report(struct hidp_session *session, | ||
258 | unsigned char *data, int size) | ||
259 | { | ||
260 | struct sk_buff *skb; | ||
261 | |||
262 | BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size); | ||
263 | |||
264 | skb = alloc_skb(size + 1, GFP_ATOMIC); | ||
265 | if (!skb) { | ||
266 | BT_ERR("Can't allocate memory for new frame"); | ||
267 | return -ENOMEM; | ||
268 | } | ||
269 | |||
270 | *skb_put(skb, 1) = 0xa2; | ||
271 | if (size > 0) | ||
272 | memcpy(skb_put(skb, size), data, size); | ||
273 | |||
274 | skb_queue_tail(&session->intr_transmit, skb); | ||
275 | |||
276 | hidp_schedule(session); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int hidp_send_report(struct hidp_session *session, struct hid_report *report) | 245 | static int hidp_send_report(struct hidp_session *session, struct hid_report *report) |
282 | { | 246 | { |
283 | unsigned char buf[32]; | 247 | unsigned char buf[32], hdr; |
284 | int rsize; | 248 | int rsize; |
285 | 249 | ||
286 | rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 250 | rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
@@ -288,8 +252,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep | |||
288 | return -EIO; | 252 | return -EIO; |
289 | 253 | ||
290 | hid_output_report(report, buf); | 254 | hid_output_report(report, buf); |
255 | hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; | ||
291 | 256 | ||
292 | return hidp_queue_report(session, buf, rsize); | 257 | return hidp_send_intr_message(session, hdr, buf, rsize); |
293 | } | 258 | } |
294 | 259 | ||
295 | static int hidp_get_raw_report(struct hid_device *hid, | 260 | static int hidp_get_raw_report(struct hid_device *hid, |
@@ -328,7 +293,7 @@ static int hidp_get_raw_report(struct hid_device *hid, | |||
328 | session->waiting_report_number = numbered_reports ? report_number : -1; | 293 | session->waiting_report_number = numbered_reports ? report_number : -1; |
329 | set_bit(HIDP_WAITING_FOR_RETURN, &session->flags); | 294 | set_bit(HIDP_WAITING_FOR_RETURN, &session->flags); |
330 | data[0] = report_number; | 295 | data[0] = report_number; |
331 | ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1); | 296 | ret = hidp_send_ctrl_message(session, report_type, data, 1); |
332 | if (ret) | 297 | if (ret) |
333 | goto err; | 298 | goto err; |
334 | 299 | ||
@@ -388,7 +353,7 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s | |||
388 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; | 353 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; |
389 | break; | 354 | break; |
390 | case HID_OUTPUT_REPORT: | 355 | case HID_OUTPUT_REPORT: |
391 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT; | 356 | report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; |
392 | break; | 357 | break; |
393 | default: | 358 | default: |
394 | return -EINVAL; | 359 | return -EINVAL; |
@@ -399,8 +364,7 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s | |||
399 | 364 | ||
400 | /* Set up our wait, and send the report request to the device. */ | 365 | /* Set up our wait, and send the report request to the device. */ |
401 | set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); | 366 | set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); |
402 | ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, | 367 | ret = hidp_send_ctrl_message(session, report_type, data, count); |
403 | count); | ||
404 | if (ret) | 368 | if (ret) |
405 | goto err; | 369 | goto err; |
406 | 370 | ||
@@ -485,12 +449,12 @@ static void hidp_process_handshake(struct hidp_session *session, | |||
485 | case HIDP_HSHK_ERR_FATAL: | 449 | case HIDP_HSHK_ERR_FATAL: |
486 | /* Device requests a reboot, as this is the only way this error | 450 | /* Device requests a reboot, as this is the only way this error |
487 | * can be recovered. */ | 451 | * can be recovered. */ |
488 | __hidp_send_ctrl_message(session, | 452 | hidp_send_ctrl_message(session, |
489 | HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0); | 453 | HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0); |
490 | break; | 454 | break; |
491 | 455 | ||
492 | default: | 456 | default: |
493 | __hidp_send_ctrl_message(session, | 457 | hidp_send_ctrl_message(session, |
494 | HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); | 458 | HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); |
495 | break; | 459 | break; |
496 | } | 460 | } |
@@ -538,7 +502,7 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, | |||
538 | break; | 502 | break; |
539 | 503 | ||
540 | default: | 504 | default: |
541 | __hidp_send_ctrl_message(session, | 505 | hidp_send_ctrl_message(session, |
542 | HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); | 506 | HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); |
543 | } | 507 | } |
544 | 508 | ||
@@ -585,7 +549,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session, | |||
585 | break; | 549 | break; |
586 | 550 | ||
587 | default: | 551 | default: |
588 | __hidp_send_ctrl_message(session, | 552 | hidp_send_ctrl_message(session, |
589 | HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0); | 553 | HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0); |
590 | break; | 554 | break; |
591 | } | 555 | } |