1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
24 #include "ar6000_drv.h"
25 #ifdef AR6K_ENABLE_HCI_PAL
26 #include <net/bluetooth/bluetooth.h>
27 #include <net/bluetooth/hci_core.h>
30 extern unsigned int setupbtdev;
31 #define bt_check_bit(val, bit) (val & bit)
32 #define bt_set_bit(val, bit) (val |= bit)
33 #define bt_clear_bit(val, bit) (val &= ~bit)
35 /* export ATH_AR6K_DEBUG_HCI_PAL=yes in host/localmake.linux.inc
36 * to enable debug information */
38 #define PRIN_LOG(format, args...) printk(KERN_ALERT "%s:%d - %s Msg:" format "\n",__FUNCTION__, __LINE__, __FILE__, ## args)
40 #define PRIN_LOG(format, args...)
43 /**********************************
44 * HCI PAL private info structure
45 *********************************/
46 typedef struct ar6k_hci_pal_info_s{
48 unsigned long ulFlags;
49 #define HCI_NORMAL_MODE (1)
50 #define HCI_REGISTERED (1<<1)
51 struct hci_dev *hdev; /* BT Stack HCI dev */
56 /*** BT Stack Entrypoints *******/
57 /***************************************
58 * bt_open - open a handle to the device
59 ***************************************/
60 static int bt_open(struct hci_dev *hdev)
62 PRIN_LOG("HCI PAL: bt_open - enter - x\n");
63 set_bit(HCI_RUNNING, &hdev->flags);
64 set_bit(HCI_UP, &hdev->flags);
65 set_bit(HCI_INIT, &hdev->flags);
69 /***************************************
70 * bt_close - close handle to the device
71 ***************************************/
72 static int bt_close(struct hci_dev *hdev)
74 PRIN_LOG("HCI PAL: bt_close - enter\n");
75 clear_bit(HCI_RUNNING, &hdev->flags);
79 /*****************************
80 * bt_ioctl - ioctl processing
81 *****************************/
82 static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
84 PRIN_LOG("HCI PAL: bt_ioctl - enter\n");
88 /**************************************
89 * bt_flush - flush outstanding packets
90 **************************************/
91 static int bt_flush(struct hci_dev *hdev)
93 PRIN_LOG("HCI PAL: bt_flush - enter\n");
100 static void bt_destruct(struct hci_dev *hdev)
102 PRIN_LOG("HCI PAL: bt_destruct - enter\n");
103 /* nothing to do here */
106 /****************************************************
107 * Invoked from bluetooth stack via hdev->send()
108 * to send the packet out via ar6k to PAL firmware.
110 * For HCI command packet wmi_send_hci_cmd() is invoked.
111 * wmi_send_hci_cmd adds WMI_CMD_HDR and sends the packet
114 * For HCI ACL data packet wmi_data_hdr_add is invoked
115 * to add WMI_DATA_HDR to the packet. ar6000_acl_data_tx
116 * is then invoked to send the packet to PAL firmware.
117 ******************************************************/
118 static int btpal_send_frame(struct sk_buff *skb)
120 struct hci_dev *hdev = (struct hci_dev *)skb->dev;
121 HCI_TRANSPORT_PACKET_TYPE type;
122 ar6k_hci_pal_info_t *pHciPalInfo;
123 A_STATUS status = A_OK;
124 struct sk_buff *txSkb = NULL;
128 PRIN_LOG("HCI PAL: btpal_send_frame - no device\n");
132 if (!test_bit(HCI_RUNNING, &hdev->flags)) {
133 PRIN_LOG("HCI PAL: btpal_send_frame - not open\n");
137 pHciPalInfo = (ar6k_hci_pal_info_t *)hdev->driver_data;
138 A_ASSERT(pHciPalInfo != NULL);
139 ar = pHciPalInfo->ar;
141 PRIN_LOG("+btpal_send_frame type: %d \n",bt_cb(skb)->pkt_type);
142 type = HCI_COMMAND_TYPE;
144 switch (bt_cb(skb)->pkt_type) {
145 case HCI_COMMAND_PKT:
146 type = HCI_COMMAND_TYPE;
150 case HCI_ACLDATA_PKT:
155 case HCI_SCODATA_PKT:
156 /* we don't support SCO over the pal */
165 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) {
166 A_PRINTF(">>> Send HCI %s packet len: %d\n",
167 (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL",
169 if (type == HCI_COMMAND_TYPE) {
170 PRIN_LOG(" HCI Command: OGF:0x%X OCF:0x%X \r\n",
171 HCI_GET_OP_CODE(skb-data) >> 10, HCI_GET_OP_CODE(skb-data) & 0x3FF);
173 AR_DEBUG_PRINTBUF(skb->data,skb->len,"BT HCI SEND Packet Dump");
177 if(type == HCI_COMMAND_TYPE)
179 PRIN_LOG("HCI command");
181 if (ar->arWmiReady == FALSE)
183 PRIN_LOG("WMI not ready ");
187 if (wmi_send_hci_cmd(ar->arWmi, skb->data, skb->len) != A_OK)
189 PRIN_LOG("send hci cmd error");
193 else if(type == HCI_ACL_TYPE)
197 PRIN_LOG("ACL data");
198 if (ar->arWmiReady == FALSE)
200 PRIN_LOG("WMI not ready");
204 /* need to add WMI header so allocate a skb with more space */
205 txSkb = bt_skb_alloc(TX_PACKET_RSV_OFFSET + WMI_MAX_TX_META_SZ +
206 sizeof(WMI_DATA_HDR) + skb->len,
210 status = A_NO_MEMORY;
211 PRIN_LOG("No memory");
215 bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type;
216 txSkb->dev = (void *)pHciPalInfo->hdev;
217 skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + WMI_MAX_TX_META_SZ + sizeof(WMI_DATA_HDR));
218 A_MEMCPY(txSkb->data, skb->data, skb->len);
219 skb_put(txSkb,skb->len);
220 /* Add WMI packet type */
221 osbuf = (void *)txSkb;
223 if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != A_OK) {
224 PRIN_LOG("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n");
226 /* Send data buffer over HTC */
227 PRIN_LOG("acl data tx");
228 ar6000_acl_data_tx(osbuf, ar->arNetDev);
235 PRIN_LOG("Free skb");
243 /***********************************************
244 * Unregister HCI device and free HCI device info
245 ***********************************************/
246 static void bt_cleanup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
250 if (bt_check_bit(pHciPalInfo->ulFlags, HCI_REGISTERED)) {
251 bt_clear_bit(pHciPalInfo->ulFlags, HCI_REGISTERED);
252 clear_bit(HCI_RUNNING, &pHciPalInfo->hdev->flags);
253 clear_bit(HCI_UP, &pHciPalInfo->hdev->flags);
254 clear_bit(HCI_INIT, &pHciPalInfo->hdev->flags);
255 A_ASSERT(pHciPalInfo->hdev != NULL);
257 PRIN_LOG("Unregister PAL device");
258 if ((err = hci_unregister_dev(pHciPalInfo->hdev)) < 0) {
259 PRIN_LOG("HCI PAL: failed to unregister with bluetooth %d\n",err);
263 if (pHciPalInfo->hdev != NULL) {
264 kfree(pHciPalInfo->hdev);
265 pHciPalInfo->hdev = NULL;
269 /*********************************************************
270 * Allocate HCI device and store in PAL private info structure.
271 *********************************************************/
272 static A_STATUS bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
274 A_STATUS status = A_OK;
275 struct hci_dev *pHciDev = NULL;
282 /* allocate a BT HCI struct for this device */
283 pHciDev = hci_alloc_dev();
284 if (NULL == pHciDev) {
285 PRIN_LOG("HCI PAL driver - failed to allocate BT HCI struct \n");
286 status = A_NO_MEMORY;
290 /* save the device, we'll register this later */
291 pHciPalInfo->hdev = pHciDev;
292 SET_HCI_BUS_TYPE(pHciDev, HCI_VIRTUAL, HCI_80211);
293 pHciDev->driver_data = pHciPalInfo;
294 pHciDev->open = bt_open;
295 pHciDev->close = bt_close;
296 pHciDev->send = btpal_send_frame;
297 pHciDev->ioctl = bt_ioctl;
298 pHciDev->flush = bt_flush;
299 pHciDev->destruct = bt_destruct;
300 pHciDev->owner = THIS_MODULE;
301 /* driver is running in normal BT mode */
302 PRIN_LOG("Normal mode enabled");
303 bt_set_bit(pHciPalInfo->ulFlags, HCI_NORMAL_MODE);
307 if (A_FAILED(status)) {
308 bt_cleanup_hci_pal(pHciPalInfo);
313 /**********************************************
314 * Cleanup HCI device and free HCI PAL private info
315 *********************************************/
316 void ar6k_cleanup_hci_pal(void *ar_p)
318 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar_p;
319 ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)ar->hcipal_info;
321 if (pHciPalInfo != NULL) {
322 bt_cleanup_hci_pal(pHciPalInfo);
324 ar->hcipal_info = NULL;
328 /****************************
329 * Register HCI device
330 ****************************/
331 static A_BOOL ar6k_pal_transport_ready(void *pHciPal)
333 ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
335 PRIN_LOG("HCI device transport ready");
336 if(pHciPalInfo == NULL)
339 if (hci_register_dev(pHciPalInfo->hdev) < 0) {
340 PRIN_LOG("Can't register HCI device");
341 hci_free_dev(pHciPalInfo->hdev);
344 PRIN_LOG("HCI device registered");
345 pHciPalInfo->ulFlags |= HCI_REGISTERED;
349 /**************************************************
350 * Called from ar6k driver when command or ACL data
351 * packet is received. Pass the packet to bluetooth
352 * stack via hci_recv_frame.
353 **************************************************/
354 A_BOOL ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
356 struct sk_buff *skb = (struct sk_buff *)osbuf;
357 ar6k_hci_pal_info_t *pHciPalInfo;
358 A_BOOL success = FALSE;
360 pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
364 /* if normal mode is not enabled pass on to the stack
365 * by returning failure */
366 if(!(pHciPalInfo->ulFlags & HCI_NORMAL_MODE))
368 PRIN_LOG("Normal mode not enabled");
372 if (!test_bit(HCI_RUNNING, &pHciPalInfo->hdev->flags)) {
373 PRIN_LOG("HCI PAL: HCI - not running\n");
377 if(*((short *)A_NETBUF_DATA(skb)) == WMI_ACL_DATA_EVENTID)
378 btType = HCI_ACLDATA_PKT;
380 btType = HCI_EVENT_PKT;
381 /* pull 4 bytes which contains WMI packet type */
382 A_NETBUF_PULL(skb, sizeof(int));
383 bt_cb(skb)->pkt_type = btType;
384 skb->dev = (void *)pHciPalInfo->hdev;
386 /* pass the received event packet up the stack */
387 if (hci_recv_frame(skb) != 0) {
388 PRIN_LOG("HCI PAL: hci_recv_frame failed \n");
391 PRIN_LOG("HCI PAL: Indicated RCV of type:%d, Length:%d \n",HCI_EVENT_PKT, skb->len);
393 PRIN_LOG("hci recv success");
399 /**********************************************************
400 * HCI PAL init function called from ar6k when it is loaded..
401 * Allocates PAL private info, stores the same in ar6k private info.
402 * Registers a HCI device.
403 * Registers packet receive callback function with ar6k
404 **********************************************************/
405 A_STATUS ar6k_setup_hci_pal(void *ar_p)
407 A_STATUS status = A_OK;
408 ar6k_hci_pal_info_t *pHciPalInfo;
409 ar6k_pal_config_t ar6k_pal_config;
410 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar_p;
414 pHciPalInfo = (ar6k_hci_pal_info_t *)A_MALLOC(sizeof(ar6k_hci_pal_info_t));
416 if (NULL == pHciPalInfo) {
417 status = A_NO_MEMORY;
421 A_MEMZERO(pHciPalInfo, sizeof(ar6k_hci_pal_info_t));
422 ar->hcipal_info = pHciPalInfo;
423 pHciPalInfo->ar = ar;
425 status = bt_setup_hci_pal(pHciPalInfo);
426 if (A_FAILED(status)) {
430 if(bt_check_bit(pHciPalInfo->ulFlags, HCI_NORMAL_MODE))
431 PRIN_LOG("HCI PAL: running in normal mode... \n");
433 PRIN_LOG("HCI PAL: running in test mode... \n");
435 ar6k_pal_config.fpar6k_pal_recv_pkt = ar6k_pal_recv_pkt;
436 register_pal_cb(&ar6k_pal_config);
437 ar6k_pal_transport_ready(ar->hcipal_info);
440 if (A_FAILED(status)) {
441 ar6k_cleanup_hci_pal(ar);
445 #else /* AR6K_ENABLE_HCI_PAL */
446 A_STATUS ar6k_setup_hci_pal(void *ar_p)
450 void ar6k_cleanup_hci_pal(void *ar_p)
453 #endif /* AR6K_ENABLE_HCI_PAL */
455 #ifdef EXPORT_HCI_PAL_INTERFACE
456 /*****************************************************
457 * Register init and callback function with ar6k
458 * when PAL driver is a separate kernel module.
459 ****************************************************/
460 A_STATUS ar6k_register_hci_pal(HCI_TRANSPORT_CALLBACKS *hciTransCallbacks);
461 static int __init pal_init_module(void)
463 HCI_TRANSPORT_CALLBACKS hciTransCallbacks;
465 hciTransCallbacks.setupTransport = ar6k_setup_hci_pal;
466 hciTransCallbacks.cleanupTransport = ar6k_cleanup_hci_pal;
468 if(ar6k_register_hci_pal(&hciTransCallbacks) != A_OK)
474 static void __exit pal_cleanup_module(void)
478 module_init(pal_init_module);
479 module_exit(pal_cleanup_module);
480 MODULE_LICENSE("Dual BSD/GPL");