blob: 6555e217f62ecd51719d95a4dcdd55bbdbf38fa8 [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;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070045};
46struct hci_smd_data hs;
47
Bhasker Netid08d9012011-09-05 19:37:54 +053048/* Rx queue monitor timer function */
49static int is_rx_q_empty(unsigned long arg)
50{
51 struct hci_dev *hdev = (struct hci_dev *) arg;
52 struct sk_buff_head *list_ = &hdev->rx_q;
53 struct sk_buff *list = ((struct sk_buff *)list_)->next;
54 BT_DBG("%s Rx timer triggered", hdev->name);
55
56 if (list == (struct sk_buff *)list_) {
57 BT_DBG("%s RX queue empty", hdev->name);
58 return 1;
59 } else{
60 BT_DBG("%s RX queue not empty", hdev->name);
61 return 0;
62 }
63}
64
65static void release_lock(void)
66{
67 struct hci_smd_data *hsmd = &hs;
68 BT_DBG("Releasing Rx Lock");
69 if (is_rx_q_empty((unsigned long)hsmd->hdev) &&
70 wake_lock_active(&hs.wake_lock_rx))
71 wake_unlock(&hs.wake_lock_rx);
72}
73
74/* Rx timer callback function */
75static void schedule_timer(unsigned long arg)
76{
77 struct hci_dev *hdev = (struct hci_dev *) arg;
78 struct hci_smd_data *hsmd = &hs;
79 BT_DBG("%s Schedule Rx timer", hdev->name);
80
81 if (is_rx_q_empty(arg) && wake_lock_active(&hs.wake_lock_rx)) {
82 BT_DBG("%s RX queue empty", hdev->name);
83 /*
84 * Since the queue is empty, its ideal
85 * to release the wake lock on Rx
86 */
87 wake_unlock(&hs.wake_lock_rx);
88 } else{
89 BT_DBG("%s RX queue not empty", hdev->name);
90 /*
91 * Restart the timer to monitor whether the Rx queue is
92 * empty for releasing the Rx wake lock
93 */
94 mod_timer(&hsmd->rx_q_timer,
95 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
96 }
97}
98
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070099static int hci_smd_open(struct hci_dev *hdev)
100{
101 set_bit(HCI_RUNNING, &hdev->flags);
102 return 0;
103}
104
105
106static int hci_smd_close(struct hci_dev *hdev)
107{
108 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
109 return 0;
110 else
111 return -EPERM;
112}
113
114
115static void hci_smd_destruct(struct hci_dev *hdev)
116{
117 kfree(hdev->driver_data);
118}
119
120static void hci_smd_recv_data(unsigned long arg)
121{
Bhasker Netid08d9012011-09-05 19:37:54 +0530122 int len = 0;
123 int rc = 0;
124 struct sk_buff *skb = NULL;
125 unsigned char *buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530127 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128
129 len = smd_read_avail(hsmd->data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530130 if (len <= 0) {
131 BT_ERR("Nothing to read from SMD channel\n");
132 goto out_data;
133 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700134 while (len > 0) {
135 skb = bt_skb_alloc(len, GFP_KERNEL);
136 if (!skb) {
137 BT_ERR("Error in allocating socket buffer\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530138 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700139 }
140
141 buf = kmalloc(len, GFP_KERNEL);
142 if (!buf) {
143 BT_ERR("Error in allocating buffer\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530144 rc = -ENOMEM;
145 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700146 }
147
148 rc = smd_read_from_cb(hsmd->data_channel, (void *)buf, len);
149 if (rc < len) {
150 BT_ERR("Error in reading from the channel");
Bhasker Netid08d9012011-09-05 19:37:54 +0530151 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700152 }
153
154 memcpy(skb_put(skb, len), buf, len);
155 skb->dev = (void *)hsmd->hdev;
156 bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
157
158 skb_orphan(skb);
159
160 rc = hci_recv_frame(skb);
161 if (rc < 0) {
162 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Netid08d9012011-09-05 19:37:54 +0530163 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164 }
165
166 kfree(buf);
Bhasker Netid08d9012011-09-05 19:37:54 +0530167 buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700168 len = smd_read_avail(hsmd->data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530169 /*
170 * Start the timer to monitor whether the Rx queue is
171 * empty for releasing the Rx wake lock
172 */
173 BT_DBG("Rx Timer is starting\n");
174 mod_timer(&hsmd->rx_q_timer,
175 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
176 }
177out_data:
178 release_lock();
179 if (rc) {
180 if (skb)
181 kfree_skb(skb);
182 kfree(buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700183 }
184}
185
186static void hci_smd_recv_event(unsigned long arg)
187{
Bhasker Netid08d9012011-09-05 19:37:54 +0530188 int len = 0;
189 int rc = 0;
190 struct sk_buff *skb = NULL;
191 unsigned char *buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700192 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530193 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194
195 len = smd_read_avail(hsmd->event_channel);
196 if (len > HCI_MAX_FRAME_SIZE) {
197 BT_ERR("Frame larger than the allowed size");
Bhasker Netid08d9012011-09-05 19:37:54 +0530198 goto out_event;
199 } else if (len <= 0) {
200 BT_ERR("Nothing to read from SMD channel\n");
201 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202 }
203
204 while (len > 0) {
205 skb = bt_skb_alloc(len, GFP_KERNEL);
Bhasker Netid08d9012011-09-05 19:37:54 +0530206 if (!skb) {
207 BT_ERR("Error in allocating socket buffer\n");
208 goto out_event;
209 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700210 buf = kmalloc(len, GFP_KERNEL);
211 if (!buf) {
Bhasker Netid08d9012011-09-05 19:37:54 +0530212 BT_ERR("Error in allocating buffer\n");
213 rc = -ENOMEM;
214 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700216 rc = smd_read_from_cb(hsmd->event_channel, (void *)buf, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530217 if (rc < len) {
218 BT_ERR("Error in reading from the event channel");
219 goto out_event;
220 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221
222 memcpy(skb_put(skb, len), buf, len);
223 skb->dev = (void *)hsmd->hdev;
224 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
225
226 skb_orphan(skb);
227
228 rc = hci_recv_frame(skb);
229 if (rc < 0) {
230 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Netid08d9012011-09-05 19:37:54 +0530231 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232 }
233
234 kfree(buf);
Bhasker Netid08d9012011-09-05 19:37:54 +0530235 buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700236 len = smd_read_avail(hsmd->event_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530237 /*
238 * Start the timer to monitor whether the Rx queue is
239 * empty for releasing the Rx wake lock
240 */
241 BT_DBG("Rx Timer is starting\n");
242 mod_timer(&hsmd->rx_q_timer,
243 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
244 }
245out_event:
246 release_lock();
247 if (rc) {
248 if (skb)
249 kfree_skb(skb);
250 kfree(buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700251 }
252}
253
254static int hci_smd_send_frame(struct sk_buff *skb)
255{
256 int len;
Bhasker Netid08d9012011-09-05 19:37:54 +0530257 int avail;
258 int ret = 0;
259 wake_lock(&hs.wake_lock_tx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700260
261 switch (bt_cb(skb)->pkt_type) {
262 case HCI_COMMAND_PKT:
Bhasker Netid08d9012011-09-05 19:37:54 +0530263 avail = smd_write_avail(hs.event_channel);
264 if (!avail) {
265 BT_ERR("No space available for smd frame");
266 ret = -ENOSPC;
267 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268 len = smd_write(hs.event_channel, skb->data, skb->len);
269 if (len < skb->len) {
270 BT_ERR("Failed to write Command %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530271 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272 }
273 break;
274 case HCI_ACLDATA_PKT:
275 case HCI_SCODATA_PKT:
Bhasker Netid08d9012011-09-05 19:37:54 +0530276 avail = smd_write_avail(hs.event_channel);
277 if (!avail) {
278 BT_ERR("No space available for smd frame");
279 ret = -ENOSPC;
280 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281 len = smd_write(hs.data_channel, skb->data, skb->len);
282 if (len < skb->len) {
283 BT_ERR("Failed to write Data %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530284 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285 }
286 break;
287 default:
288 BT_ERR("Uknown packet type\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530289 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290 break;
291 }
Bhasker Netid08d9012011-09-05 19:37:54 +0530292
293 wake_unlock(&hs.wake_lock_tx);
294 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295}
296
297
298static void hci_smd_notify_event(void *data, unsigned int event)
299{
300 struct hci_dev *hdev = hs.hdev;
301
302 if (!hdev) {
303 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
304 return;
305 }
306
307 switch (event) {
308 case SMD_EVENT_DATA:
309 hci_smd_recv_event(event);
310 break;
311 case SMD_EVENT_OPEN:
312 hci_smd_open(hdev);
313 break;
314 case SMD_EVENT_CLOSE:
315 hci_smd_close(hdev);
316 break;
317 default:
318 break;
319 }
320}
321
322static void hci_smd_notify_data(void *data, unsigned int event)
323{
324 struct hci_dev *hdev = hs.hdev;
325 if (!hdev) {
326 BT_ERR("HCI device (hdev=NULL)");
327 return;
328 }
329
330 switch (event) {
331 case SMD_EVENT_DATA:
332 hci_smd_recv_data(event);
333 break;
334 case SMD_EVENT_OPEN:
335 hci_smd_open(hdev);
336 break;
337 case SMD_EVENT_CLOSE:
338 hci_smd_close(hdev);
339 break;
340 default:
341 break;
342 }
343
344}
345
346static int hci_smd_register_dev(struct hci_smd_data *hsmd)
347{
348 struct hci_dev *hdev;
349 int rc;
350
351 /* Initialize and register HCI device */
352 hdev = hci_alloc_dev();
353 if (!hdev) {
354 BT_ERR("Can't allocate HCI device");
355 return -ENOMEM;
356 }
357
358 hsmd->hdev = hdev;
359 hdev->bus = HCI_SMD;
360 hdev->driver_data = hsmd;
361 hdev->open = hci_smd_open;
362 hdev->close = hci_smd_close;
363 hdev->send = hci_smd_send_frame;
364 hdev->destruct = hci_smd_destruct;
365 hdev->owner = THIS_MODULE;
366
Bhasker Netid08d9012011-09-05 19:37:54 +0530367 wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND, "msm_smd_Rx");
368 wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND, "msm_smd_Tx");
369 /*
370 * Setup the timer to monitor whether the Rx queue is empty,
371 * to control the wake lock release
372 */
373 setup_timer(&hsmd->rx_q_timer, schedule_timer,
374 (unsigned long) hsmd->hdev);
375
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700376 /* Open the SMD Channel and device and register the callback function */
377 rc = smd_named_open_on_edge(EVENT_CHANNEL, SMD_APPS_WCNSS,
378 &hsmd->event_channel, hdev, hci_smd_notify_event);
379 if (rc < 0) {
380 BT_ERR("Cannot open the command channel");
381 hci_free_dev(hdev);
382 return -ENODEV;
383 }
384
385 rc = smd_named_open_on_edge(DATA_CHANNEL, SMD_APPS_WCNSS,
386 &hsmd->data_channel, hdev, hci_smd_notify_data);
387 if (rc < 0) {
388 BT_ERR("Failed to open the Data channel\n");
389 hci_free_dev(hdev);
390 return -ENODEV;
391 }
392
393 /* Disable the read interrupts on the channel */
394 smd_disable_read_intr(hsmd->event_channel);
395 smd_disable_read_intr(hsmd->data_channel);
396
397 if (hci_register_dev(hdev) < 0) {
398 BT_ERR("Can't register HCI device");
399 hci_free_dev(hdev);
400 return -ENODEV;
401 }
402
403 return 0;
404}
405
406static void hci_smd_deregister(void)
407{
408 smd_close(hs.event_channel);
409 hs.event_channel = 0;
410 smd_close(hs.data_channel);
411 hs.data_channel = 0;
Bhasker Netid08d9012011-09-05 19:37:54 +0530412 wake_lock_destroy(&hs.wake_lock_rx);
413 wake_lock_destroy(&hs.wake_lock_tx);
414
415 /*Destroy the timer used to monitor the Rx queue for emptiness */
416 del_timer_sync(&hs.rx_q_timer);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700417}
418
419static int hci_smd_init(void)
420{
421 return hci_smd_register_dev(&hs);
422}
423module_init(hci_smd_init);
424
425static void __exit hci_smd_exit(void)
426{
427 hci_smd_deregister();
428}
429module_exit(hci_smd_exit);
430
431MODULE_AUTHOR("Ankur Nandwani <ankurn@codeaurora.org>");
432MODULE_DESCRIPTION("Bluetooth SMD driver");
433MODULE_LICENSE("GPL v2");