Skip to content

Commit 0825411

Browse files
signal11Jiri Kosina
authored andcommitted
HID: bt: Wait for ACK on Sent Reports
Wait for an ACK from the device before returning from hidp_output_raw_report(). This way, failures can be returned to the user application. Also, it prevents ACK/NAK packets from an output packet from being confused with ACK/NAK packets from an input request packet. Signed-off-by: Alan Ott <alan@signal11.us> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent 0f69dca commit 0825411

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

net/bluetooth/hidp/core.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
316316
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
317317
unsigned char report_type)
318318
{
319+
struct hidp_session *session = hid->driver_data;
320+
int ret;
321+
319322
switch (report_type) {
320323
case HID_FEATURE_REPORT:
321324
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
@@ -327,10 +330,47 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
327330
return -EINVAL;
328331
}
329332

333+
if (mutex_lock_interruptible(&session->report_mutex))
334+
return -ERESTARTSYS;
335+
336+
/* Set up our wait, and send the report request to the device. */
337+
set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
330338
if (hidp_send_ctrl_message(hid->driver_data, report_type,
331-
data, count))
332-
return -ENOMEM;
333-
return count;
339+
data, count)) {
340+
ret = -ENOMEM;
341+
goto err;
342+
}
343+
344+
/* Wait for the ACK from the device. */
345+
while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
346+
int res;
347+
348+
res = wait_event_interruptible_timeout(session->report_queue,
349+
!test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
350+
10*HZ);
351+
if (res == 0) {
352+
/* timeout */
353+
ret = -EIO;
354+
goto err;
355+
}
356+
if (res < 0) {
357+
/* signal */
358+
ret = -ERESTARTSYS;
359+
goto err;
360+
}
361+
}
362+
363+
if (!session->output_report_success) {
364+
ret = -EIO;
365+
goto err;
366+
}
367+
368+
ret = count;
369+
370+
err:
371+
clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
372+
mutex_unlock(&session->report_mutex);
373+
return ret;
334374
}
335375

336376
static void hidp_idle_timeout(unsigned long arg)
@@ -357,10 +397,12 @@ static void hidp_process_handshake(struct hidp_session *session,
357397
unsigned char param)
358398
{
359399
BT_DBG("session %p param 0x%02x", session, param);
400+
session->output_report_success = 0; /* default condition */
360401

361402
switch (param) {
362403
case HIDP_HSHK_SUCCESSFUL:
363404
/* FIXME: Call into SET_ GET_ handlers here */
405+
session->output_report_success = 1;
364406
break;
365407

366408
case HIDP_HSHK_NOT_READY:
@@ -385,6 +427,12 @@ static void hidp_process_handshake(struct hidp_session *session,
385427
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
386428
break;
387429
}
430+
431+
/* Wake up the waiting thread. */
432+
if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
433+
clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
434+
wake_up_interruptible(&session->report_queue);
435+
}
388436
}
389437

390438
static void hidp_process_hid_control(struct hidp_session *session,

net/bluetooth/hidp/hidp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
#define HIDP_VIRTUAL_CABLE_UNPLUG 0
8181
#define HIDP_BOOT_PROTOCOL_MODE 1
8282
#define HIDP_BLUETOOTH_VENDOR_ID 9
83+
#define HIDP_WAITING_FOR_SEND_ACK 11
8384

8485
struct hidp_connadd_req {
8586
int ctrl_sock; // Connected control socket
@@ -154,6 +155,9 @@ struct hidp_session {
154155
struct sk_buff_head ctrl_transmit;
155156
struct sk_buff_head intr_transmit;
156157

158+
/* Used in hidp_output_raw_report() */
159+
int output_report_success; /* boolean */
160+
157161
/* Report descriptor */
158162
__u8 *rd_data;
159163
uint rd_size;

0 commit comments

Comments
 (0)