| Index: chromeos/drivers/ath6kl/os/linux/hci_bridge.c | 
| diff --git a/chromeos/drivers/ath6kl/os/linux/hci_bridge.c b/chromeos/drivers/ath6kl/os/linux/hci_bridge.c | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..32489336975d4e1794ded18ba7fa0fc6e650d34e | 
| --- /dev/null | 
| +++ b/chromeos/drivers/ath6kl/os/linux/hci_bridge.c | 
| @@ -0,0 +1,1117 @@ | 
| +//------------------------------------------------------------------------------ | 
| +// <copyright file="hci_bridge.c" company="Atheros"> | 
| +//    Copyright (c) 2009 Atheros Corporation.  All rights reserved. | 
| +// | 
| +// This program is free software; you can redistribute it and/or modify | 
| +// it under the terms of the GNU General Public License version 2 as | 
| +// published by the Free Software Foundation; | 
| +// | 
| +// Software distributed under the License is distributed on an "AS | 
| +// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | 
| +// implied. See the License for the specific language governing | 
| +// rights and limitations under the License. | 
| +// | 
| +// | 
| +//------------------------------------------------------------------------------ | 
| +//============================================================================== | 
| +// HCI bridge implementation | 
| +// | 
| +// Author(s): ="Atheros" | 
| +//============================================================================== | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +#include <linux/etherdevice.h> | 
| +#include <a_config.h> | 
| +#include <athdefs.h> | 
| +#include "a_types.h" | 
| +#include "a_osapi.h" | 
| +#include "htc_api.h" | 
| +#include "wmi.h" | 
| +#include "a_drv.h" | 
| +#include "hif.h" | 
| +#include "common_drv.h" | 
| +#include "a_debug.h" | 
| +#define  ATH_DEBUG_HCI_BRIDGE    ATH_DEBUG_MAKE_MODULE_MASK(6) | 
| +#define  ATH_DEBUG_HCI_RECV      ATH_DEBUG_MAKE_MODULE_MASK(7) | 
| +#define  ATH_DEBUG_HCI_SEND      ATH_DEBUG_MAKE_MODULE_MASK(8) | 
| +#define  ATH_DEBUG_HCI_DUMP      ATH_DEBUG_MAKE_MODULE_MASK(9) | 
| +#else | 
| +#include "ar6000_drv.h" | 
| +#endif  /* EXPORT_HCI_BRIDGE_INTERFACE */ | 
| + | 
| +#ifdef ATH_AR6K_ENABLE_GMBOX | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +#include "export_hci_transport.h" | 
| +#else | 
| +#include "hci_transport_api.h" | 
| +#endif | 
| +#include "epping_test.h" | 
| +#include "gmboxif.h" | 
| +#include "ar3kconfig.h" | 
| +#include <net/bluetooth/bluetooth.h> | 
| +#include <net/bluetooth/hci_core.h> | 
| + | 
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) | 
| +    /* only build on newer kernels which have BT configured */ | 
| +#if defined(CONFIG_BT_MODULE) || defined(CONFIG_BT) | 
| +#define CONFIG_BLUEZ_HCI_BRIDGE | 
| +#endif | 
| +#endif | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +unsigned int ar3khcibaud = 0; | 
| +unsigned int hciuartscale = 0; | 
| +unsigned int hciuartstep = 0; | 
| + | 
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | 
| +module_param(ar3khcibaud, int, 0644); | 
| +module_param(hciuartscale, int, 0644); | 
| +module_param(hciuartstep, int, 0644); | 
| +#else | 
| + | 
| +#define __user | 
| +/* for linux 2.4 and lower */ | 
| +MODULE_PARM(ar3khcibaud, "i"); | 
| +MODULE_PARM(hciuartscale, "i"); | 
| +MODULE_PARM(hciuartstep, "i"); | 
| +#endif | 
| +#else | 
| +extern unsigned int ar3khcibaud; | 
| +extern unsigned int hciuartscale; | 
| +extern unsigned int hciuartstep; | 
| +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ | 
| + | 
| +typedef struct { | 
| +    void                    *pHCIDev;          /* HCI bridge device */ | 
| +    HCI_TRANSPORT_PROPERTIES HCIProps;         /* HCI bridge props */ | 
| +    struct hci_dev          *pBtStackHCIDev;   /* BT Stack HCI dev */ | 
| +    A_BOOL                  HciNormalMode;     /* Actual HCI mode enabled (non-TEST)*/ | 
| +    A_BOOL                  HciRegistered;     /* HCI device registered with stack */ | 
| +    HTC_PACKET_QUEUE        HTCPacketStructHead; | 
| +    A_UINT8                 *pHTCStructAlloc; | 
| +    spinlock_t              BridgeLock; | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +    HCI_TRANSPORT_MISC_HANDLES    HCITransHdl; | 
| +#else | 
| +    AR_SOFTC_T              *ar; | 
| +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ | 
| +} AR6K_HCI_BRIDGE_INFO; | 
| + | 
| +#define MAX_ACL_RECV_BUFS           16 | 
| +#define MAX_EVT_RECV_BUFS           8 | 
| +#define MAX_HCI_WRITE_QUEUE_DEPTH   32 | 
| +#define MAX_ACL_RECV_LENGTH         1200 | 
| +#define MAX_EVT_RECV_LENGTH         257 | 
| +#define TX_PACKET_RSV_OFFSET        32 | 
| +#define NUM_HTC_PACKET_STRUCTS     ((MAX_ACL_RECV_BUFS + MAX_EVT_RECV_BUFS + MAX_HCI_WRITE_QUEUE_DEPTH) * 2) | 
| + | 
| +#define HCI_GET_OP_CODE(p)          (((A_UINT16)((p)[1])) << 8) | ((A_UINT16)((p)[0])) | 
| + | 
| +extern unsigned int setupbtdev; | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +AR6K_HCI_BRIDGE_INFO *g_pHcidevInfo; | 
| +#endif | 
| + | 
| +static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo); | 
| +static void     bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo); | 
| +static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo); | 
| +static A_BOOL   bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, | 
| +                                 HCI_TRANSPORT_PACKET_TYPE Type, | 
| +                                 struct sk_buff            *skb); | 
| +static struct sk_buff *bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length); | 
| +static void     bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb); | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +A_STATUS ar6000_setup_hci(void *ar); | 
| +void     ar6000_cleanup_hci(void *ar); | 
| +A_STATUS hci_test_send(void *ar, struct sk_buff *skb); | 
| +#else | 
| +A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar); | 
| +void     ar6000_cleanup_hci(AR_SOFTC_T *ar); | 
| +/* HCI bridge testing */ | 
| +A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb); | 
| +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ | 
| + | 
| +#define LOCK_BRIDGE(dev)   spin_lock_bh(&(dev)->BridgeLock) | 
| +#define UNLOCK_BRIDGE(dev) spin_unlock_bh(&(dev)->BridgeLock) | 
| + | 
| +static inline void FreeBtOsBuf(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, void *osbuf) | 
| +{ | 
| +    if (pHcidevInfo->HciNormalMode) { | 
| +        bt_free_buffer(pHcidevInfo, (struct sk_buff *)osbuf); | 
| +    } else { | 
| +            /* in test mode, these are just ordinary netbuf allocations */ | 
| +        A_NETBUF_FREE(osbuf); | 
| +    } | 
| +} | 
| + | 
| +static void FreeHTCStruct(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, HTC_PACKET *pPacket) | 
| +{ | 
| +    LOCK_BRIDGE(pHcidevInfo); | 
| +    HTC_PACKET_ENQUEUE(&pHcidevInfo->HTCPacketStructHead,pPacket); | 
| +    UNLOCK_BRIDGE(pHcidevInfo); | 
| +} | 
| + | 
| +static HTC_PACKET * AllocHTCStruct(AR6K_HCI_BRIDGE_INFO *pHcidevInfo) | 
| +{ | 
| +    HTC_PACKET  *pPacket = NULL; | 
| +    LOCK_BRIDGE(pHcidevInfo); | 
| +    pPacket = HTC_PACKET_DEQUEUE(&pHcidevInfo->HTCPacketStructHead); | 
| +    UNLOCK_BRIDGE(pHcidevInfo); | 
| +    return pPacket; | 
| +} | 
| + | 
| +#define BLOCK_ROUND_UP_PWR2(x, align)    (((int) (x) + ((align)-1)) & ~((align)-1)) | 
| + | 
| +static void RefillRecvBuffers(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, | 
| +                              HCI_TRANSPORT_PACKET_TYPE Type, | 
| +                              int                       NumBuffers) | 
| +{ | 
| +    int                 length, i; | 
| +    void                *osBuf = NULL; | 
| +    HTC_PACKET_QUEUE    queue; | 
| +    HTC_PACKET          *pPacket; | 
| + | 
| +    INIT_HTC_PACKET_QUEUE(&queue); | 
| + | 
| +    if (Type == HCI_ACL_TYPE) { | 
| +        if (pHcidevInfo->HciNormalMode) { | 
| +            length = HCI_MAX_FRAME_SIZE; | 
| +        } else { | 
| +            length = MAX_ACL_RECV_LENGTH; | 
| +        } | 
| +    } else { | 
| +        length = MAX_EVT_RECV_LENGTH; | 
| +    } | 
| + | 
| +        /* add on transport head and tail room */ | 
| +    length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom; | 
| +        /* round up to the required I/O padding */ | 
| +    length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad); | 
| + | 
| +    for (i = 0; i < NumBuffers; i++) { | 
| + | 
| +        if (pHcidevInfo->HciNormalMode) { | 
| +            osBuf = bt_alloc_buffer(pHcidevInfo,length); | 
| +        } else { | 
| +            osBuf = A_NETBUF_ALLOC(length); | 
| +        } | 
| + | 
| +        if (NULL == osBuf) { | 
| +            break; | 
| +        } | 
| + | 
| +        pPacket = AllocHTCStruct(pHcidevInfo); | 
| +        if (NULL == pPacket) { | 
| +            FreeBtOsBuf(pHcidevInfo,osBuf); | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); | 
| +            break; | 
| +        } | 
| + | 
| +        SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type); | 
| +            /* add to queue */ | 
| +        HTC_PACKET_ENQUEUE(&queue,pPacket); | 
| +    } | 
| + | 
| +    if (i > 0) { | 
| +        HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue); | 
| +    } | 
| +} | 
| + | 
| +static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle, | 
| +                                           HCI_TRANSPORT_PROPERTIES *pProps, | 
| +                                           void                     *pContext) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; | 
| +    A_STATUS              status; | 
| +    AR3K_CONFIG_INFO      ar3kconfig; | 
| + | 
| +    pHcidevInfo->pHCIDev = HCIHandle; | 
| + | 
| +    A_MEMCPY(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps)); | 
| + | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%X, headroom:%d, tailroom:%d blockpad:%d) \n", | 
| +            (A_UINT32)HCIHandle, | 
| +            pHcidevInfo->HCIProps.HeadRoom, | 
| +            pHcidevInfo->HCIProps.TailRoom, | 
| +            pHcidevInfo->HCIProps.IOBlockPad)); | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len); | 
| +#else | 
| +    A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= pHcidevInfo->ar->arNetDev->hard_header_len); | 
| +#endif | 
| + | 
| +        /* provide buffers */ | 
| +    RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS); | 
| +    RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS); | 
| + | 
| +    do { | 
| +            /* start transport */ | 
| +        status = HCI_TransportStart(pHcidevInfo->pHCIDev); | 
| + | 
| +        if (A_FAILED(status)) { | 
| +            break; | 
| +        } | 
| + | 
| +        if (!pHcidevInfo->HciNormalMode) { | 
| +                /* in test mode, no need to go any further */ | 
| +            break; | 
| +        } | 
| + | 
| +        A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); | 
| +        ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev; | 
| +        ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps; | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +        ar3kconfig.pHIFDevice = (HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice); | 
| +#else | 
| +        ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice; | 
| +#endif | 
| +        ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; | 
| + | 
| +        if (ar3khcibaud != 0) { | 
| +                /* user wants ar3k baud rate change */ | 
| +            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; | 
| +            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY; | 
| +            ar3kconfig.AR3KBaudRate = ar3khcibaud; | 
| +        } | 
| + | 
| +        if ((hciuartscale != 0) || (hciuartstep != 0)) { | 
| +                /* user wants to tune HCI bridge UART scale/step values */ | 
| +            ar3kconfig.AR6KScale = (A_UINT16)hciuartscale; | 
| +            ar3kconfig.AR6KStep = (A_UINT16)hciuartstep; | 
| +            ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP; | 
| +        } | 
| + | 
| +            /* configure the AR3K device */ | 
| +        status = AR3KConfigure(&ar3kconfig); | 
| +        if (A_FAILED(status)) { | 
| +            break; | 
| +        } | 
| + | 
| +        status = bt_register_hci(pHcidevInfo); | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    return status; | 
| +} | 
| + | 
| +static void ar6000_hci_transport_failure(void *pContext, A_STATUS Status) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; | 
| + | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: transport failure! \n")); | 
| + | 
| +    if (pHcidevInfo->HciNormalMode) { | 
| +        /* TODO .. */ | 
| +    } | 
| +} | 
| + | 
| +static void ar6000_hci_transport_removed(void *pContext) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; | 
| + | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: transport removed. \n")); | 
| + | 
| +    A_ASSERT(pHcidevInfo->pHCIDev != NULL); | 
| + | 
| +    HCI_TransportDetach(pHcidevInfo->pHCIDev); | 
| +    bt_cleanup_hci(pHcidevInfo); | 
| +    pHcidevInfo->pHCIDev = NULL; | 
| +} | 
| + | 
| +static void ar6000_hci_send_complete(void *pContext, HTC_PACKET *pPacket) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; | 
| +    void                 *osbuf = pPacket->pPktContext; | 
| +    A_ASSERT(osbuf != NULL); | 
| +    A_ASSERT(pHcidevInfo != NULL); | 
| + | 
| +    if (A_FAILED(pPacket->Status)) { | 
| +        if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); | 
| +        } | 
| +    } | 
| + | 
| +    FreeHTCStruct(pHcidevInfo,pPacket); | 
| +    FreeBtOsBuf(pHcidevInfo,osbuf); | 
| + | 
| +} | 
| + | 
| +static void ar6000_hci_pkt_recv(void *pContext, HTC_PACKET *pPacket) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; | 
| +    struct sk_buff       *skb; | 
| + | 
| +    A_ASSERT(pHcidevInfo != NULL); | 
| +    skb = (struct sk_buff *)pPacket->pPktContext; | 
| +    A_ASSERT(skb != NULL); | 
| + | 
| +    do { | 
| + | 
| +        if (A_FAILED(pPacket->Status)) { | 
| +            break; | 
| +        } | 
| + | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, | 
| +                        ("HCI Bridge, packet received type : %d len:%d \n", | 
| +                        HCI_GET_PACKET_TYPE(pPacket),pPacket->ActualLength)); | 
| + | 
| +            /* set the actual buffer position in the os buffer, HTC recv buffers posted to HCI are set | 
| +             * to fill the front of the buffer */ | 
| +        A_NETBUF_PUT(skb,pPacket->ActualLength + pHcidevInfo->HCIProps.HeadRoom); | 
| +        A_NETBUF_PULL(skb,pHcidevInfo->HCIProps.HeadRoom); | 
| + | 
| +        if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("<<< Recv HCI %s packet len:%d \n", | 
| +                        (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) ? "EVENT" : "ACL", | 
| +                        skb->len)); | 
| +            AR_DEBUG_PRINTBUF(skb->data, skb->len,"BT HCI RECV Packet Dump"); | 
| +        } | 
| + | 
| +        if (pHcidevInfo->HciNormalMode) { | 
| +                /* indicate the packet */ | 
| +            if (bt_indicate_recv(pHcidevInfo,HCI_GET_PACKET_TYPE(pPacket),skb)) { | 
| +                    /* bt stack accepted the packet */ | 
| +                skb = NULL; | 
| +            } | 
| +            break; | 
| +        } | 
| + | 
| +            /* for testing, indicate packet to the network stack */ | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +        skb->dev = (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice); | 
| +        if ((((struct net_device *)pHcidevInfo->HCITransHdl.netDevice)->flags & IFF_UP) == IFF_UP) { | 
| +            skb->protocol = eth_type_trans(skb, (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)); | 
| +#else | 
| +        skb->dev = pHcidevInfo->ar->arNetDev; | 
| +        if ((pHcidevInfo->ar->arNetDev->flags & IFF_UP) == IFF_UP) { | 
| +            skb->protocol = eth_type_trans(skb, pHcidevInfo->ar->arNetDev); | 
| +#endif | 
| +            netif_rx(skb); | 
| +            skb = NULL; | 
| +        } | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    FreeHTCStruct(pHcidevInfo,pPacket); | 
| + | 
| +    if (skb != NULL) { | 
| +            /* packet was not accepted, free it */ | 
| +        FreeBtOsBuf(pHcidevInfo,skb); | 
| +    } | 
| + | 
| +} | 
| + | 
| +static void  ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; | 
| +    int                  refillCount; | 
| + | 
| +    if (Type == HCI_ACL_TYPE) { | 
| +        refillCount =  MAX_ACL_RECV_BUFS - BuffersAvailable; | 
| +    } else { | 
| +        refillCount =  MAX_EVT_RECV_BUFS - BuffersAvailable; | 
| +    } | 
| + | 
| +    if (refillCount > 0) { | 
| +        RefillRecvBuffers(pHcidevInfo,Type,refillCount); | 
| +    } | 
| + | 
| +} | 
| + | 
| +static HCI_SEND_FULL_ACTION  ar6000_hci_pkt_send_full(void *pContext, HTC_PACKET *pPacket) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO    *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; | 
| +    HCI_SEND_FULL_ACTION    action = HCI_SEND_FULL_KEEP; | 
| + | 
| +    if (!pHcidevInfo->HciNormalMode) { | 
| +            /* for epping testing, check packet tag, some epping packets are | 
| +             * special and cannot be dropped */ | 
| +        if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_DATA_PKT_TAG) { | 
| +            action = HCI_SEND_FULL_DROP; | 
| +        } | 
| +    } | 
| + | 
| +    return action; | 
| +} | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +A_STATUS ar6000_setup_hci(void *ar) | 
| +#else | 
| +A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar) | 
| +#endif | 
| +{ | 
| +    HCI_TRANSPORT_CONFIG_INFO config; | 
| +    A_STATUS                  status = A_OK; | 
| +    int                       i; | 
| +    HTC_PACKET                *pPacket; | 
| +    AR6K_HCI_BRIDGE_INFO      *pHcidevInfo; | 
| + | 
| + | 
| +    do { | 
| + | 
| +        pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)A_MALLOC(sizeof(AR6K_HCI_BRIDGE_INFO)); | 
| + | 
| +        if (NULL == pHcidevInfo) { | 
| +            status = A_NO_MEMORY; | 
| +            break; | 
| +        } | 
| + | 
| +        A_MEMZERO(pHcidevInfo, sizeof(AR6K_HCI_BRIDGE_INFO)); | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +        g_pHcidevInfo = pHcidevInfo; | 
| +        pHcidevInfo->HCITransHdl = *(HCI_TRANSPORT_MISC_HANDLES *)ar; | 
| +#else | 
| +        ar->hcidev_info = pHcidevInfo; | 
| +        pHcidevInfo->ar = ar; | 
| +#endif | 
| +        spin_lock_init(&pHcidevInfo->BridgeLock); | 
| +        INIT_HTC_PACKET_QUEUE(&pHcidevInfo->HTCPacketStructHead); | 
| + | 
| +        ar->exitCallback = AR3KConfigureExit; | 
| + | 
| +        status = bt_setup_hci(pHcidevInfo); | 
| +        if (A_FAILED(status)) { | 
| +            break; | 
| +        } | 
| + | 
| +        if (pHcidevInfo->HciNormalMode) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in normal mode... \n")); | 
| +        } else { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in test mode... \n")); | 
| +        } | 
| + | 
| +        pHcidevInfo->pHTCStructAlloc = (A_UINT8 *)A_MALLOC((sizeof(HTC_PACKET)) * NUM_HTC_PACKET_STRUCTS); | 
| + | 
| +        if (NULL == pHcidevInfo->pHTCStructAlloc) { | 
| +            status = A_NO_MEMORY; | 
| +            break; | 
| +        } | 
| + | 
| +        pPacket = (HTC_PACKET *)pHcidevInfo->pHTCStructAlloc; | 
| +        for (i = 0; i < NUM_HTC_PACKET_STRUCTS; i++,pPacket++) { | 
| +            FreeHTCStruct(pHcidevInfo,pPacket); | 
| +        } | 
| + | 
| +        A_MEMZERO(&config,sizeof(HCI_TRANSPORT_CONFIG_INFO)); | 
| +        config.ACLRecvBufferWaterMark = MAX_ACL_RECV_BUFS / 2; | 
| +        config.EventRecvBufferWaterMark = MAX_EVT_RECV_BUFS / 2; | 
| +        config.MaxSendQueueDepth = MAX_HCI_WRITE_QUEUE_DEPTH; | 
| +        config.pContext = pHcidevInfo; | 
| +        config.TransportFailure = ar6000_hci_transport_failure; | 
| +        config.TransportReady = ar6000_hci_transport_ready; | 
| +        config.TransportRemoved = ar6000_hci_transport_removed; | 
| +        config.pHCISendComplete = ar6000_hci_send_complete; | 
| +        config.pHCIPktRecv = ar6000_hci_pkt_recv; | 
| +        config.pHCIPktRecvRefill = ar6000_hci_pkt_refill; | 
| +        config.pHCISendFull = ar6000_hci_pkt_send_full; | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +        pHcidevInfo->pHCIDev = HCI_TransportAttach(pHcidevInfo->HCITransHdl.htcHandle, &config); | 
| +#else | 
| +        pHcidevInfo->pHCIDev = HCI_TransportAttach(ar->arHtcTarget, &config); | 
| +#endif | 
| + | 
| +        if (NULL == pHcidevInfo->pHCIDev) { | 
| +            status = A_ERROR; | 
| +        } | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    if (A_FAILED(status)) { | 
| +        if (pHcidevInfo != NULL) { | 
| +            if (NULL == pHcidevInfo->pHCIDev) { | 
| +                /* GMBOX may not be present in older chips */ | 
| +                /* just return success */ | 
| +                status = A_OK; | 
| +            } | 
| +        } | 
| +        ar6000_cleanup_hci(ar); | 
| +    } | 
| + | 
| +    return status; | 
| +} | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +void  ar6000_cleanup_hci(void *ar) | 
| +#else | 
| +void  ar6000_cleanup_hci(AR_SOFTC_T *ar) | 
| +#endif | 
| +{ | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo; | 
| +#else | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info; | 
| +#endif | 
| + | 
| +    if (pHcidevInfo != NULL) { | 
| +        bt_cleanup_hci(pHcidevInfo); | 
| + | 
| +        if (pHcidevInfo->pHCIDev != NULL) { | 
| +            HCI_TransportStop(pHcidevInfo->pHCIDev); | 
| +            HCI_TransportDetach(pHcidevInfo->pHCIDev); | 
| +            pHcidevInfo->pHCIDev = NULL; | 
| +        } | 
| + | 
| +        if (pHcidevInfo->pHTCStructAlloc != NULL) { | 
| +            A_FREE(pHcidevInfo->pHTCStructAlloc); | 
| +            pHcidevInfo->pHTCStructAlloc = NULL; | 
| +        } | 
| + | 
| +        A_FREE(pHcidevInfo); | 
| +#ifndef EXPORT_HCI_BRIDGE_INTERFACE | 
| +        ar->hcidev_info = NULL; | 
| +#endif | 
| +    } | 
| + | 
| + | 
| +} | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +A_STATUS hci_test_send(void *ar, struct sk_buff *skb) | 
| +#else | 
| +A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb) | 
| +#endif | 
| +{ | 
| +    int              status = A_OK; | 
| +    int              length; | 
| +    EPPING_HEADER    *pHeader; | 
| +    HTC_PACKET       *pPacket; | 
| +    HTC_TX_TAG       htc_tag = AR6K_DATA_PKT_TAG; | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo; | 
| +#else | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info; | 
| +#endif | 
| + | 
| +    do { | 
| + | 
| +        if (NULL == pHcidevInfo) { | 
| +            status = A_ERROR; | 
| +            break; | 
| +        } | 
| + | 
| +        if (NULL == pHcidevInfo->pHCIDev) { | 
| +            status = A_ERROR; | 
| +            break; | 
| +        } | 
| + | 
| +        if (pHcidevInfo->HciNormalMode) { | 
| +                /* this interface cannot run when normal WMI is running */ | 
| +            status = A_ERROR; | 
| +            break; | 
| +        } | 
| + | 
| +        pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb); | 
| + | 
| +        if (!IS_EPPING_PACKET(pHeader)) { | 
| +            status = A_EINVAL; | 
| +            break; | 
| +        } | 
| + | 
| +        if (IS_EPING_PACKET_NO_DROP(pHeader)) { | 
| +            htc_tag = AR6K_CONTROL_PKT_TAG; | 
| +        } | 
| + | 
| +        length = sizeof(EPPING_HEADER) + pHeader->DataLength; | 
| + | 
| +        pPacket = AllocHTCStruct(pHcidevInfo); | 
| +        if (NULL == pPacket) { | 
| +            status = A_NO_MEMORY; | 
| +            break; | 
| +        } | 
| + | 
| +        SET_HTC_PACKET_INFO_TX(pPacket, | 
| +                               skb, | 
| +                               A_NETBUF_DATA(skb), | 
| +                               length, | 
| +                               HCI_ACL_TYPE,  /* send every thing out as ACL */ | 
| +                               htc_tag); | 
| + | 
| +        HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE); | 
| +        pPacket = NULL; | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    return status; | 
| +} | 
| + | 
| +void ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info; | 
| +    AR3K_CONFIG_INFO *config = (AR3K_CONFIG_INFO *)ar3kconfig; | 
| + | 
| +    config->pHCIDev = pHcidevInfo->pHCIDev; | 
| +    config->pHCIProps = &pHcidevInfo->HCIProps; | 
| +    config->pHIFDevice = ar->arHifDevice; | 
| +    config->pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; | 
| +    config->Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; | 
| +    config->AR3KBaudRate = 115200; | 
| +} | 
| + | 
| +#ifdef CONFIG_BLUEZ_HCI_BRIDGE | 
| +/*** BT Stack Entrypoints *******/ | 
| + | 
| +/* | 
| + * bt_open - open a handle to the device | 
| +*/ | 
| +static int bt_open(struct hci_dev *hdev) | 
| +{ | 
| + | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_open - enter - x\n")); | 
| +    set_bit(HCI_RUNNING, &hdev->flags); | 
| +    set_bit(HCI_UP, &hdev->flags); | 
| +    set_bit(HCI_INIT, &hdev->flags); | 
| +    return 0; | 
| +} | 
| + | 
| +/* | 
| + * bt_close - close handle to the device | 
| +*/ | 
| +static int bt_close(struct hci_dev *hdev) | 
| +{ | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_close - enter\n")); | 
| +    clear_bit(HCI_RUNNING, &hdev->flags); | 
| +    return 0; | 
| +} | 
| + | 
| +/* | 
| + * bt_send_frame - send data frames | 
| +*/ | 
| +static int bt_send_frame(struct sk_buff *skb) | 
| +{ | 
| +    struct hci_dev             *hdev = (struct hci_dev *)skb->dev; | 
| +    HCI_TRANSPORT_PACKET_TYPE  type; | 
| +    AR6K_HCI_BRIDGE_INFO       *pHcidevInfo; | 
| +    A_UINT8                    *pTemp; | 
| +    HTC_PACKET                 *pPacket; | 
| +    A_STATUS                   status = A_OK; | 
| +    struct sk_buff             *txSkb = NULL; | 
| + | 
| +    if (!hdev) { | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_send_frame - no device\n")); | 
| +        return -ENODEV; | 
| +    } | 
| + | 
| +    if (!test_bit(HCI_RUNNING, &hdev->flags)) { | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_send_frame - not open\n")); | 
| +        return -EBUSY; | 
| +    } | 
| + | 
| +    pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)hdev->driver_data; | 
| +    A_ASSERT(pHcidevInfo != NULL); | 
| + | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("+bt_send_frame type: %d \n",bt_cb(skb)->pkt_type)); | 
| +    type = HCI_COMMAND_TYPE; | 
| + | 
| +    switch (bt_cb(skb)->pkt_type) { | 
| +        case HCI_COMMAND_PKT: | 
| +            type = HCI_COMMAND_TYPE; | 
| +            hdev->stat.cmd_tx++; | 
| +            break; | 
| + | 
| +        case HCI_ACLDATA_PKT: | 
| +            type = HCI_ACL_TYPE; | 
| +            hdev->stat.acl_tx++; | 
| +            break; | 
| + | 
| +        case HCI_SCODATA_PKT: | 
| +            /* we don't support SCO over the bridge */ | 
| +            kfree_skb(skb); | 
| +            return 0; | 
| +        default: | 
| +            A_ASSERT(FALSE); | 
| +            kfree_skb(skb); | 
| +            return 0; | 
| +    } | 
| + | 
| +    if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(">>> Send HCI %s packet len: %d\n", | 
| +                        (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL", | 
| +                        skb->len)); | 
| +        if (type == HCI_COMMAND_TYPE) { | 
| +            A_UINT16 opcode = HCI_GET_OP_CODE(skb->data); | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("    HCI Command: OGF:0x%X OCF:0x%X \r\n", | 
| +                  opcode >> 10, opcode & 0x3FF)); | 
| +        } | 
| +        AR_DEBUG_PRINTBUF(skb->data,skb->len,"BT HCI SEND Packet Dump"); | 
| +    } | 
| + | 
| +    do { | 
| + | 
| +        txSkb = bt_skb_alloc(TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom + | 
| +                             pHcidevInfo->HCIProps.TailRoom + skb->len, | 
| +                             GFP_ATOMIC); | 
| + | 
| +        if (txSkb == NULL) { | 
| +            status = A_NO_MEMORY; | 
| +            break; | 
| +        } | 
| + | 
| +        bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type; | 
| +        txSkb->dev = (void *)pHcidevInfo->pBtStackHCIDev; | 
| +        skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom); | 
| +        A_MEMCPY(txSkb->data, skb->data, skb->len); | 
| +        skb_put(txSkb,skb->len); | 
| + | 
| +            /* push on header transport space */ | 
| +        pTemp = (A_UINT8 *)skb_push(txSkb, pHcidevInfo->HCIProps.HeadRoom); | 
| +        pPacket = AllocHTCStruct(pHcidevInfo); | 
| +        if (NULL == pPacket) { | 
| +            status = A_NO_MEMORY; | 
| +            break; | 
| +        } | 
| + | 
| +        SET_HTC_PACKET_INFO_TX(pPacket, | 
| +                               txSkb, | 
| +                               pTemp + pHcidevInfo->HCIProps.HeadRoom, | 
| +                               txSkb->len, | 
| +                               type, | 
| +                               AR6K_CONTROL_PKT_TAG); /* HCI packets cannot be dropped */ | 
| + | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: bt_send_frame skb:0x%X \n",(A_UINT32)txSkb)); | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: type:%d, Total Length:%d Bytes \n", | 
| +                                      type, txSkb->len)); | 
| + | 
| +        status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE); | 
| +        pPacket = NULL; | 
| +        txSkb = NULL; | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    if (txSkb != NULL) { | 
| +        kfree_skb(txSkb); | 
| +    } | 
| + | 
| +    kfree_skb(skb); | 
| + | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("-bt_send_frame  \n")); | 
| +    return 0; | 
| +} | 
| + | 
| +/* | 
| + * bt_ioctl - ioctl processing | 
| +*/ | 
| +static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | 
| +{ | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_ioctl - enter\n")); | 
| +    return -ENOIOCTLCMD; | 
| +} | 
| + | 
| +/* | 
| + * bt_flush - flush outstandingbpackets | 
| +*/ | 
| +static int bt_flush(struct hci_dev *hdev) | 
| +{ | 
| +    AR6K_HCI_BRIDGE_INFO    *pHcidevInfo; | 
| + | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_flush - enter\n")); | 
| + | 
| +    pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)hdev->driver_data; | 
| + | 
| +    /* TODO??? */ | 
| + | 
| +    return 0; | 
| +} | 
| + | 
| + | 
| +/* | 
| + * bt_destruct - | 
| +*/ | 
| +static void bt_destruct(struct hci_dev *hdev) | 
| +{ | 
| +    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_destruct - enter\n")); | 
| +    /* nothing to do here */ | 
| +} | 
| + | 
| +static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo) | 
| +{ | 
| +    A_STATUS                    status = A_OK; | 
| +    struct hci_dev              *pHciDev = NULL; | 
| +    HIF_DEVICE_OS_DEVICE_INFO   osDevInfo; | 
| + | 
| +    if (!setupbtdev) { | 
| +        return A_OK; | 
| +    } | 
| + | 
| +    do { | 
| + | 
| +        A_MEMZERO(&osDevInfo,sizeof(osDevInfo)); | 
| +            /* get the underlying OS device */ | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +        status = ar6000_get_hif_dev((HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice), | 
| +                                    &osDevInfo); | 
| +#else | 
| +        status = HIFConfigureDevice(pHcidevInfo->ar->arHifDevice, | 
| +                                    HIF_DEVICE_GET_OS_DEVICE, | 
| +                                    &osDevInfo, | 
| +                                    sizeof(osDevInfo)); | 
| +#endif | 
| + | 
| +        if (A_FAILED(status)) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to OS device info from HIF\n")); | 
| +            break; | 
| +        } | 
| + | 
| +            /* allocate a BT HCI struct for this device */ | 
| +        pHciDev = hci_alloc_dev(); | 
| +        if (NULL == pHciDev) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge - failed to allocate bt struct \n")); | 
| +            status = A_NO_MEMORY; | 
| +            break; | 
| +        } | 
| +            /* save the device, we'll register this later */ | 
| +        pHcidevInfo->pBtStackHCIDev = pHciDev; | 
| +        SET_HCIDEV_DEV(pHciDev,osDevInfo.pOSDevice); | 
| +        pHciDev->type = HCI_VIRTUAL; | 
| +        pHciDev->driver_data = pHcidevInfo; | 
| +        pHciDev->open     = bt_open; | 
| +        pHciDev->close    = bt_close; | 
| +        pHciDev->send     = bt_send_frame; | 
| +        pHciDev->ioctl    = bt_ioctl; | 
| +        pHciDev->flush    = bt_flush; | 
| +        pHciDev->destruct = bt_destruct; | 
| +        pHciDev->owner = THIS_MODULE; | 
| +            /* driver is running in normal BT mode */ | 
| +        pHcidevInfo->HciNormalMode = TRUE; | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    if (A_FAILED(status)) { | 
| +        bt_cleanup_hci(pHcidevInfo); | 
| +    } | 
| + | 
| +    return status; | 
| +} | 
| + | 
| +static void bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo) | 
| +{ | 
| +    int   err; | 
| + | 
| +    if (pHcidevInfo->HciRegistered) { | 
| +        pHcidevInfo->HciRegistered = FALSE; | 
| +        clear_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags); | 
| +        clear_bit(HCI_UP, &pHcidevInfo->pBtStackHCIDev->flags); | 
| +        clear_bit(HCI_INIT, &pHcidevInfo->pBtStackHCIDev->flags); | 
| +        A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); | 
| +            /* unregister */ | 
| +        if ((err = hci_unregister_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to unregister with bluetooth %d\n",err)); | 
| +        } | 
| +    } | 
| + | 
| +    if (pHcidevInfo->pBtStackHCIDev != NULL) { | 
| +        kfree(pHcidevInfo->pBtStackHCIDev); | 
| +        pHcidevInfo->pBtStackHCIDev = NULL; | 
| +    } | 
| +} | 
| + | 
| +static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo) | 
| +{ | 
| +    int       err; | 
| +    A_STATUS  status = A_OK; | 
| + | 
| +    do { | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: registering HCI... \n")); | 
| +        A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); | 
| +             /* mark that we are registered */ | 
| +        pHcidevInfo->HciRegistered = TRUE; | 
| +        if ((err = hci_register_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to register with bluetooth %d\n",err)); | 
| +            pHcidevInfo->HciRegistered = FALSE; | 
| +            status = A_ERROR; | 
| +            break; | 
| +        } | 
| + | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: HCI registered \n")); | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    return status; | 
| +} | 
| + | 
| +static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, | 
| +                               HCI_TRANSPORT_PACKET_TYPE Type, | 
| +                               struct                    sk_buff *skb) | 
| +{ | 
| +    A_UINT8               btType; | 
| +    int                   len; | 
| +    A_BOOL                success = FALSE; | 
| +    BT_HCI_EVENT_HEADER   *pEvent; | 
| + | 
| +    do { | 
| + | 
| +        if (!test_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags)) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_indicate_recv - not running\n")); | 
| +            break; | 
| +        } | 
| + | 
| +        switch (Type) { | 
| +            case HCI_ACL_TYPE: | 
| +                btType = HCI_ACLDATA_PKT; | 
| +                break; | 
| +            case HCI_EVENT_TYPE: | 
| +                btType = HCI_EVENT_PKT; | 
| +                break; | 
| +            default: | 
| +                btType = 0; | 
| +                A_ASSERT(FALSE); | 
| +                break; | 
| +        } | 
| + | 
| +        if (0 == btType) { | 
| +            break; | 
| +        } | 
| + | 
| +            /* set the final type */ | 
| +        bt_cb(skb)->pkt_type = btType; | 
| +            /* set dev */ | 
| +        skb->dev = (void *)pHcidevInfo->pBtStackHCIDev; | 
| +        len = skb->len; | 
| + | 
| +        if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_RECV)) { | 
| +            if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) { | 
| +                pEvent = (BT_HCI_EVENT_HEADER *)skb->data; | 
| +                AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, ("BT HCI EventCode: %d, len:%d \n", | 
| +                        pEvent->EventCode, pEvent->ParamLength)); | 
| +            } | 
| +        } | 
| + | 
| +            /* pass receive packet up the stack */ | 
| +        if (hci_recv_frame(skb) != 0) { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: hci_recv_frame failed \n")); | 
| +            break; | 
| +        } else { | 
| +            AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, | 
| +                    ("HCI Bridge: Indicated RCV of type:%d, Length:%d \n",btType,len)); | 
| +        } | 
| + | 
| +        success = TRUE; | 
| + | 
| +    } while (FALSE); | 
| + | 
| +    return success; | 
| +} | 
| + | 
| +static struct sk_buff* bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length) | 
| +{ | 
| +    struct sk_buff *skb; | 
| +        /* in normal HCI mode we need to alloc from the bt core APIs */ | 
| +    skb = bt_skb_alloc(Length, GFP_ATOMIC); | 
| +    if (NULL == skb) { | 
| +        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc bt sk_buff \n")); | 
| +    } | 
| +    return skb; | 
| +} | 
| + | 
| +static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb) | 
| +{ | 
| +    kfree_skb(skb); | 
| +} | 
| + | 
| +#else // { CONFIG_BLUEZ_HCI_BRIDGE | 
| + | 
| +    /* stubs when we only want to test the HCI bridging Interface without the HT stack */ | 
| +static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo) | 
| +{ | 
| +    return A_OK; | 
| +} | 
| +static void bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo) | 
| +{ | 
| + | 
| +} | 
| +static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo) | 
| +{ | 
| +    A_ASSERT(FALSE); | 
| +    return A_ERROR; | 
| +} | 
| + | 
| +static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, | 
| +                               HCI_TRANSPORT_PACKET_TYPE Type, | 
| +                               struct                    sk_buff *skb) | 
| +{ | 
| +    A_ASSERT(FALSE); | 
| +    return FALSE; | 
| +} | 
| + | 
| +static struct sk_buff* bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length) | 
| +{ | 
| +    A_ASSERT(FALSE); | 
| +    return NULL; | 
| +} | 
| +static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb) | 
| +{ | 
| +    A_ASSERT(FALSE); | 
| +} | 
| + | 
| +#endif // } CONFIG_BLUEZ_HCI_BRIDGE | 
| + | 
| +#else  // { ATH_AR6K_ENABLE_GMBOX | 
| + | 
| +    /* stubs when GMBOX support is not needed */ | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +A_STATUS ar6000_setup_hci(void *ar) | 
| +#else | 
| +A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar) | 
| +#endif | 
| +{ | 
| +    return A_OK; | 
| +} | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +void ar6000_cleanup_hci(void *ar) | 
| +#else | 
| +void ar6000_cleanup_hci(AR_SOFTC_T *ar) | 
| +#endif | 
| +{ | 
| +    return; | 
| +} | 
| + | 
| +#ifndef EXPORT_HCI_BRIDGE_INTERFACE | 
| +void ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig) | 
| +{ | 
| +    return; | 
| +} | 
| +#endif | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +int hci_test_send(void *ar, struct sk_buff *skb) | 
| +#else | 
| +int hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb) | 
| +#endif | 
| +{ | 
| +    return -EOPNOTSUPP; | 
| +} | 
| + | 
| +#endif // } ATH_AR6K_ENABLE_GMBOX | 
| + | 
| + | 
| +#ifdef EXPORT_HCI_BRIDGE_INTERFACE | 
| +static int __init | 
| +hcibridge_init_module(void) | 
| +{ | 
| +    A_STATUS status; | 
| +    HCI_TRANSPORT_CALLBACKS hciTransCallbacks; | 
| + | 
| +    hciTransCallbacks.setupTransport = ar6000_setup_hci; | 
| +    hciTransCallbacks.cleanupTransport = ar6000_cleanup_hci; | 
| + | 
| +    status = ar6000_register_hci_transport(&hciTransCallbacks); | 
| +    if(status != A_OK) | 
| +        return -ENODEV; | 
| + | 
| +    return 0; | 
| +} | 
| + | 
| +static void __exit | 
| +hcibridge_cleanup_module(void) | 
| +{ | 
| +} | 
| + | 
| +module_init(hcibridge_init_module); | 
| +module_exit(hcibridge_cleanup_module); | 
| +MODULE_LICENSE("GPL and additional rights"); | 
| +#endif | 
|  |