blob: 8f8ba036ce7e3fc7d898a8112bb377e9f987d3f0 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * HCI_SMD (HCI Shared Memory Driver) is Qualcomm's Shared memory driver
3 * for the BT HCI protocol.
4 *
5 * Copyright (c) 2000-2001, 2011 Code Aurora Forum. All rights reserved.
6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7 * Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
8 *
9 * This file is based on drivers/bluetooth/hci_vhci.c
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2
13 * as published by the Free Software Foundation
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/module.h>
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/errno.h>
25#include <linux/string.h>
26#include <linux/skbuff.h>
27#include <net/bluetooth/bluetooth.h>
28#include <net/bluetooth/hci_core.h>
29#include <net/bluetooth/hci.h>
30#include <mach/msm_smd.h>
Bhasker Netid08d9012011-09-05 19:37:54 +053031#include <linux/wakelock.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032
Bhasker Netid08d9012011-09-05 19:37:54 +053033#define EVENT_CHANNEL "APPS_RIVA_BT_CMD"
34#define DATA_CHANNEL "APPS_RIVA_BT_ACL"
35#define RX_Q_MONITOR (1) /* 1 milli second */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070036
37struct hci_smd_data {
38 struct hci_dev *hdev;
39
40 struct smd_channel *event_channel;
41 struct smd_channel *data_channel;
Bhasker Netid08d9012011-09-05 19:37:54 +053042 struct wake_lock wake_lock_tx;
43 struct wake_lock wake_lock_rx;
44 struct timer_list rx_q_timer;
Ankur Nandwani034ed892011-10-07 11:15:53 -070045 struct tasklet_struct hci_event_task;
46 struct tasklet_struct hci_data_task;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047};
48struct hci_smd_data hs;
49
Bhasker Netid08d9012011-09-05 19:37:54 +053050/* Rx queue monitor timer function */
51static int is_rx_q_empty(unsigned long arg)
52{
53 struct hci_dev *hdev = (struct hci_dev *) arg;
54 struct sk_buff_head *list_ = &hdev->rx_q;
55 struct sk_buff *list = ((struct sk_buff *)list_)->next;
56 BT_DBG("%s Rx timer triggered", hdev->name);
57
58 if (list == (struct sk_buff *)list_) {
59 BT_DBG("%s RX queue empty", hdev->name);
60 return 1;
61 } else{
62 BT_DBG("%s RX queue not empty", hdev->name);
63 return 0;
64 }
65}
66
67static void release_lock(void)
68{
69 struct hci_smd_data *hsmd = &hs;
70 BT_DBG("Releasing Rx Lock");
71 if (is_rx_q_empty((unsigned long)hsmd->hdev) &&
72 wake_lock_active(&hs.wake_lock_rx))
73 wake_unlock(&hs.wake_lock_rx);
74}
75
76/* Rx timer callback function */
77static void schedule_timer(unsigned long arg)
78{
79 struct hci_dev *hdev = (struct hci_dev *) arg;
80 struct hci_smd_data *hsmd = &hs;
81 BT_DBG("%s Schedule Rx timer", hdev->name);
82
83 if (is_rx_q_empty(arg) && wake_lock_active(&hs.wake_lock_rx)) {
84 BT_DBG("%s RX queue empty", hdev->name);
85 /*
86 * Since the queue is empty, its ideal
87 * to release the wake lock on Rx
88 */
89 wake_unlock(&hs.wake_lock_rx);
90 } else{
91 BT_DBG("%s RX queue not empty", hdev->name);
92 /*
93 * Restart the timer to monitor whether the Rx queue is
94 * empty for releasing the Rx wake lock
95 */
96 mod_timer(&hsmd->rx_q_timer,
97 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
98 }
99}
100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101static int hci_smd_open(struct hci_dev *hdev)
102{
103 set_bit(HCI_RUNNING, &hdev->flags);
104 return 0;
105}
106
107
108static int hci_smd_close(struct hci_dev *hdev)
109{
110 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
111 return 0;
112 else
113 return -EPERM;
114}
115
116
117static void hci_smd_destruct(struct hci_dev *hdev)
118{
119 kfree(hdev->driver_data);
120}
121
122static void hci_smd_recv_data(unsigned long arg)
123{
Bhasker Netid08d9012011-09-05 19:37:54 +0530124 int len = 0;
125 int rc = 0;
126 struct sk_buff *skb = NULL;
127 unsigned char *buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530129 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130
131 len = smd_read_avail(hsmd->data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530132 if (len <= 0) {
133 BT_ERR("Nothing to read from SMD channel\n");
134 goto out_data;
135 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700136 while (len > 0) {
Ankur Nandwanic8150962011-08-24 13:06:23 -0700137 skb = bt_skb_alloc(len, GFP_ATOMIC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138 if (!skb) {
139 BT_ERR("Error in allocating socket buffer\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530140 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 }
142
Ankur Nandwanic8150962011-08-24 13:06:23 -0700143 buf = kmalloc(len, GFP_ATOMIC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144 if (!buf) {
145 BT_ERR("Error in allocating buffer\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530146 rc = -ENOMEM;
147 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148 }
149
150 rc = smd_read_from_cb(hsmd->data_channel, (void *)buf, len);
151 if (rc < len) {
152 BT_ERR("Error in reading from the channel");
Bhasker Netid08d9012011-09-05 19:37:54 +0530153 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154 }
155
156 memcpy(skb_put(skb, len), buf, len);
157 skb->dev = (void *)hsmd->hdev;
158 bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
159
160 skb_orphan(skb);
161
162 rc = hci_recv_frame(skb);
163 if (rc < 0) {
164 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Netid08d9012011-09-05 19:37:54 +0530165 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166 }
167
168 kfree(buf);
Bhasker Netid08d9012011-09-05 19:37:54 +0530169 buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700170 len = smd_read_avail(hsmd->data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530171 /*
172 * Start the timer to monitor whether the Rx queue is
173 * empty for releasing the Rx wake lock
174 */
175 BT_DBG("Rx Timer is starting\n");
176 mod_timer(&hsmd->rx_q_timer,
177 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
178 }
179out_data:
180 release_lock();
181 if (rc) {
182 if (skb)
183 kfree_skb(skb);
184 kfree(buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700185 }
186}
187
188static void hci_smd_recv_event(unsigned long arg)
189{
Bhasker Netid08d9012011-09-05 19:37:54 +0530190 int len = 0;
191 int rc = 0;
192 struct sk_buff *skb = NULL;
193 unsigned char *buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530195 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700196
197 len = smd_read_avail(hsmd->event_channel);
198 if (len > HCI_MAX_FRAME_SIZE) {
199 BT_ERR("Frame larger than the allowed size");
Bhasker Netid08d9012011-09-05 19:37:54 +0530200 goto out_event;
201 } else if (len <= 0) {
202 BT_ERR("Nothing to read from SMD channel\n");
203 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 }
205
206 while (len > 0) {
Ankur Nandwanic8150962011-08-24 13:06:23 -0700207 skb = bt_skb_alloc(len, GFP_ATOMIC);
Bhasker Netid08d9012011-09-05 19:37:54 +0530208 if (!skb) {
209 BT_ERR("Error in allocating socket buffer\n");
210 goto out_event;
211 }
Ankur Nandwanic8150962011-08-24 13:06:23 -0700212 buf = kmalloc(len, GFP_ATOMIC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700213 if (!buf) {
Bhasker Netid08d9012011-09-05 19:37:54 +0530214 BT_ERR("Error in allocating buffer\n");
215 rc = -ENOMEM;
216 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218 rc = smd_read_from_cb(hsmd->event_channel, (void *)buf, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530219 if (rc < len) {
220 BT_ERR("Error in reading from the event channel");
221 goto out_event;
222 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700223
224 memcpy(skb_put(skb, len), buf, len);
225 skb->dev = (void *)hsmd->hdev;
226 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
227
228 skb_orphan(skb);
229
230 rc = hci_recv_frame(skb);
231 if (rc < 0) {
232 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Netid08d9012011-09-05 19:37:54 +0530233 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700234 }
235
236 kfree(buf);
Bhasker Netid08d9012011-09-05 19:37:54 +0530237 buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700238 len = smd_read_avail(hsmd->event_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530239 /*
240 * Start the timer to monitor whether the Rx queue is
241 * empty for releasing the Rx wake lock
242 */
243 BT_DBG("Rx Timer is starting\n");
244 mod_timer(&hsmd->rx_q_timer,
245 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
246 }
247out_event:
248 release_lock();
249 if (rc) {
250 if (skb)
251 kfree_skb(skb);
252 kfree(buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700253 }
254}
255
256static int hci_smd_send_frame(struct sk_buff *skb)
257{
258 int len;
Bhasker Netid08d9012011-09-05 19:37:54 +0530259 int avail;
260 int ret = 0;
261 wake_lock(&hs.wake_lock_tx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262
263 switch (bt_cb(skb)->pkt_type) {
264 case HCI_COMMAND_PKT:
Bhasker Netid08d9012011-09-05 19:37:54 +0530265 avail = smd_write_avail(hs.event_channel);
266 if (!avail) {
267 BT_ERR("No space available for smd frame");
268 ret = -ENOSPC;
269 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270 len = smd_write(hs.event_channel, skb->data, skb->len);
271 if (len < skb->len) {
272 BT_ERR("Failed to write Command %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530273 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274 }
275 break;
276 case HCI_ACLDATA_PKT:
277 case HCI_SCODATA_PKT:
Bhasker Netid08d9012011-09-05 19:37:54 +0530278 avail = smd_write_avail(hs.event_channel);
279 if (!avail) {
280 BT_ERR("No space available for smd frame");
281 ret = -ENOSPC;
282 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283 len = smd_write(hs.data_channel, skb->data, skb->len);
284 if (len < skb->len) {
285 BT_ERR("Failed to write Data %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530286 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700287 }
288 break;
289 default:
290 BT_ERR("Uknown packet type\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530291 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292 break;
293 }
Bhasker Netid08d9012011-09-05 19:37:54 +0530294
295 wake_unlock(&hs.wake_lock_tx);
296 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700297}
298
299
300static void hci_smd_notify_event(void *data, unsigned int event)
301{
302 struct hci_dev *hdev = hs.hdev;
303
304 if (!hdev) {
305 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
306 return;
307 }
308
309 switch (event) {
310 case SMD_EVENT_DATA:
Ankur Nandwani034ed892011-10-07 11:15:53 -0700311 tasklet_hi_schedule(&hs.hci_event_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700312 break;
313 case SMD_EVENT_OPEN:
314 hci_smd_open(hdev);
315 break;
316 case SMD_EVENT_CLOSE:
317 hci_smd_close(hdev);
318 break;
319 default:
320 break;
321 }
322}
323
324static void hci_smd_notify_data(void *data, unsigned int event)
325{
326 struct hci_dev *hdev = hs.hdev;
327 if (!hdev) {
328 BT_ERR("HCI device (hdev=NULL)");
329 return;
330 }
331
332 switch (event) {
333 case SMD_EVENT_DATA:
Ankur Nandwani034ed892011-10-07 11:15:53 -0700334 tasklet_hi_schedule(&hs.hci_data_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700335 break;
336 case SMD_EVENT_OPEN:
337 hci_smd_open(hdev);
338 break;
339 case SMD_EVENT_CLOSE:
340 hci_smd_close(hdev);
341 break;
342 default:
343 break;
344 }
345
346}
347
348static int hci_smd_register_dev(struct hci_smd_data *hsmd)
349{
350 struct hci_dev *hdev;
351 int rc;
352
353 /* Initialize and register HCI device */
354 hdev = hci_alloc_dev();
355 if (!hdev) {
356 BT_ERR("Can't allocate HCI device");
357 return -ENOMEM;
358 }
359
360 hsmd->hdev = hdev;
361 hdev->bus = HCI_SMD;
362 hdev->driver_data = hsmd;
363 hdev->open = hci_smd_open;
364 hdev->close = hci_smd_close;
365 hdev->send = hci_smd_send_frame;
366 hdev->destruct = hci_smd_destruct;
367 hdev->owner = THIS_MODULE;
368
Ankur Nandwani034ed892011-10-07 11:15:53 -0700369 tasklet_init(&hsmd->hci_event_task,
370 hci_smd_recv_event, (unsigned long) hsmd);
371 tasklet_init(&hsmd->hci_data_task,
372 hci_smd_recv_data, (unsigned long) hsmd);
373
Bhasker Netid08d9012011-09-05 19:37:54 +0530374 wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND, "msm_smd_Rx");
375 wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND, "msm_smd_Tx");
376 /*
377 * Setup the timer to monitor whether the Rx queue is empty,
378 * to control the wake lock release
379 */
380 setup_timer(&hsmd->rx_q_timer, schedule_timer,
381 (unsigned long) hsmd->hdev);
382
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383 /* Open the SMD Channel and device and register the callback function */
384 rc = smd_named_open_on_edge(EVENT_CHANNEL, SMD_APPS_WCNSS,
385 &hsmd->event_channel, hdev, hci_smd_notify_event);
386 if (rc < 0) {
387 BT_ERR("Cannot open the command channel");
388 hci_free_dev(hdev);
389 return -ENODEV;
390 }
391
392 rc = smd_named_open_on_edge(DATA_CHANNEL, SMD_APPS_WCNSS,
393 &hsmd->data_channel, hdev, hci_smd_notify_data);
394 if (rc < 0) {
395 BT_ERR("Failed to open the Data channel\n");
396 hci_free_dev(hdev);
397 return -ENODEV;
398 }
399
400 /* Disable the read interrupts on the channel */
401 smd_disable_read_intr(hsmd->event_channel);
402 smd_disable_read_intr(hsmd->data_channel);
403
404 if (hci_register_dev(hdev) < 0) {
405 BT_ERR("Can't register HCI device");
406 hci_free_dev(hdev);
407 return -ENODEV;
408 }
409
410 return 0;
411}
412
413static void hci_smd_deregister(void)
414{
415 smd_close(hs.event_channel);
416 hs.event_channel = 0;
417 smd_close(hs.data_channel);
418 hs.data_channel = 0;
Bhasker Netid08d9012011-09-05 19:37:54 +0530419 wake_lock_destroy(&hs.wake_lock_rx);
420 wake_lock_destroy(&hs.wake_lock_tx);
421
422 /*Destroy the timer used to monitor the Rx queue for emptiness */
423 del_timer_sync(&hs.rx_q_timer);
Ankur Nandwani034ed892011-10-07 11:15:53 -0700424 tasklet_kill(&hs.hci_event_task);
425 tasklet_kill(&hs.hci_data_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700426}
427
428static int hci_smd_init(void)
429{
430 return hci_smd_register_dev(&hs);
431}
432module_init(hci_smd_init);
433
434static void __exit hci_smd_exit(void)
435{
436 hci_smd_deregister();
437}
438module_exit(hci_smd_exit);
439
440MODULE_AUTHOR("Ankur Nandwani <ankurn@codeaurora.org>");
441MODULE_DESCRIPTION("Bluetooth SMD driver");
442MODULE_LICENSE("GPL v2");