From patchwork Mon Jan 10 20:49:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Ott X-Patchwork-Id: 469611 X-Patchwork-Delegate: jikos@jikos.cz Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0AKnWNM012192 for ; Mon, 10 Jan 2011 20:49:32 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754682Ab1AJUtb (ORCPT ); Mon, 10 Jan 2011 15:49:31 -0500 Received: from core.signal11.us ([64.251.29.136]:46993 "EHLO core.signal11.us" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754651Ab1AJUtb (ORCPT ); Mon, 10 Jan 2011 15:49:31 -0500 Received: from localhost (localhost.localdomain [127.0.0.1]) by core.signal11.us (Postfix) with SMTP id 69ED11CCAB82 for ; Mon, 10 Jan 2011 15:49:30 -0500 (EST) Received: from [192.168.1.100] (c-76-29-154-30.hsd1.fl.comcast.net [76.29.154.30]) by core.signal11.us (Postfix) with ESMTP id 55FC21CCAB7F; Mon, 10 Jan 2011 15:49:28 -0500 (EST) Message-ID: <4D2B70D8.3030203@signal11.us> Date: Mon, 10 Jan 2011 15:49:28 -0500 From: Alan Ott User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100528 Lightning/1.0b1 Thunderbird/3.0.5 MIME-Version: 1.0 To: Antonio Ospite , Ville Tervo , Jiri Kosina , Bill Good , Marcel Holtmann , "Gustavo F. Padovan" Cc: "linux-input@vger.kernel.org" , "linux-bluetooth@vger.kernel.org" Subject: Re: hidraw: Wait for Ack when Sending to Device References: <4D2B6883.7090900@signal11.us> In-Reply-To: <4D2B6883.7090900@signal11.us> X-DSPAM-Result: Whitelisted X-DSPAM-Processed: Mon Jan 10 15:49:30 2011 X-DSPAM-Confidence: 0.9899 X-DSPAM-Probability: 0.0000 X-DSPAM-Signature: 4d2b70da15021295386491 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 10 Jan 2011 20:49:33 +0000 (UTC) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 0e4880e..b55562a 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -397,6 +397,9 @@ err_eio: static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, unsigned char report_type) { + struct hidp_session *session = hid->driver_data; + int ret; + switch (report_type) { case HID_FEATURE_REPORT: report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; @@ -408,10 +411,59 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s return -EINVAL; } + if (mutex_lock_interruptible(&session->report_mutex)) + return -ERESTARTSYS; + + /* Set up our wait, and send the report request to the device. */ + set_bit(HIDP_WAITING_FOR_SEND_ACK,&session->flags); if (hidp_send_ctrl_message(hid->driver_data, report_type, - data, count)) - return -ENOMEM; - return count; + data, count)) { + ret = -ENOMEM; + goto err; + } + + { + int i; + printk(KERN_WARNING "Sent %d message: %02hhx len: %d\n", report_type, data[0], (int)count); + for (i = 0; i< count; i++) { + printk(KERN_WARNING " %02hhx", data[i]); + } + printk(KERN_WARNING "\n"); + } + + /* Wait for the ACK from the device. */ + while (test_bit(HIDP_WAITING_FOR_SEND_ACK,&session->flags)) { + int res; + + res = wait_event_interruptible_timeout(session->report_queue, + !test_bit(HIDP_WAITING_FOR_SEND_ACK,&session->flags), + 10*HZ); + if (res == 0) { + /* timeout */ + printk(KERN_WARNING "TIMEOUT\n"); + ret = -EIO; + goto err; + } + if (res< 0) { + /* signal */ + printk(KERN_WARNING "SIGNAL\n"); + ret = -ERESTARTSYS; + goto err; + } + } + + if (!session->output_report_success) { + printk(KERN_WARNING "NOT SUCCESS: Returning -EIO\n"); + ret = -EIO; + goto err; + } + + ret = count; + +err: + clear_bit(HIDP_WAITING_FOR_SEND_ACK,&session->flags); + mutex_unlock(&session->report_mutex); + return ret; } static void hidp_idle_timeout(unsigned long arg) @@ -438,10 +490,14 @@ static void hidp_process_handshake(struct hidp_session *session, unsigned char param) { BT_DBG("session %p param 0x%02x", session, param); + printk(KERN_WARNING "Handshake Packet %d\n", param); + session->output_report_success = 0; /* default condition */ switch (param) { case HIDP_HSHK_SUCCESSFUL: /* FIXME: Call into SET_ GET_ handlers here */ + printk(KERN_WARNING " (Successful)\n"); + session->output_report_success = 1; break; case HIDP_HSHK_NOT_READY: @@ -452,6 +508,7 @@ static void hidp_process_handshake(struct hidp_session *session, clear_bit(HIDP_WAITING_FOR_RETURN,&session->flags); wake_up_interruptible(&session->report_queue); } + printk(KERN_WARNING " (not-successful %d)\n", param); /* FIXME: Call into SET_ GET_ handlers here */ break; @@ -470,6 +527,12 @@ static void hidp_process_handshake(struct hidp_session *session, HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); break; } + + /* Wake up the waiting thread. */ + if (test_bit(HIDP_WAITING_FOR_SEND_ACK,&session->flags)) { + clear_bit(HIDP_WAITING_FOR_SEND_ACK,&session->flags); + wake_up_interruptible(&session->report_queue); + } } static void hidp_process_hid_control(struct hidp_session *session, @@ -494,6 +557,7 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, { int done_with_skb = 1; BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param); + printk(KERN_WARNING "Got Data packet. param: %d\n", param); switch (param) { case HIDP_DATA_RTYPE_INPUT: @@ -647,6 +711,7 @@ static int hidp_session(void *arg) wait_queue_t ctrl_wait, intr_wait; BT_DBG("session %p", session); + printk(KERN_WARNING "SESSION STARTING\n"); if (session->input) { vendor = session->input->id.vendor; @@ -665,6 +730,7 @@ static int hidp_session(void *arg) init_waitqueue_entry(&intr_wait, current); add_wait_queue(sk_sleep(ctrl_sk),&ctrl_wait); add_wait_queue(sk_sleep(intr_sk),&intr_wait); + printk(KERN_WARNING "session entering main loop\n"); while (!atomic_read(&session->terminate)) { set_current_state(TASK_INTERRUPTIBLE); @@ -673,6 +739,7 @@ static int hidp_session(void *arg) while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { skb_orphan(skb); + printk(KERN_WARNING "Got CTRL Frame\n"); hidp_recv_ctrl_frame(session, skb); } @@ -925,6 +992,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, int err; BT_DBG(""); + printk(KERN_WARNING "HIDP ADD CONNECTION"); if (bacmp(&bt_sk(ctrl_sock->sk)->src,&bt_sk(intr_sock->sk)->src) || bacmp(&bt_sk(ctrl_sock->sk)->dst,&bt_sk(intr_sock->sk)->dst)) diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 00e71dd..2f16eea 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h @@ -81,6 +81,7 @@ #define HIDP_BOOT_PROTOCOL_MODE 1 #define HIDP_BLUETOOTH_VENDOR_ID 9 #define HIDP_WAITING_FOR_RETURN 10 +#define HIDP_WAITING_FOR_SEND_ACK 11 struct hidp_connadd_req { int ctrl_sock; // Connected control socket @@ -161,6 +162,9 @@ struct hidp_session { struct mutex report_mutex; struct sk_buff *report_return; wait_queue_head_t report_queue; + + /* Used in hidp_output_raw_report() */ + int output_report_success; /* boolean */ /* Report descriptor */ __u8 *rd_data;