A_STATUS Abf_WlanIssueFrontEndConfig(ATHBT_FILTER_INFO * pInfo) { WMI_SET_BTCOEX_FE_ANT_CMD btcoexFeAntCmd; WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD btcoexCoLocatedBtCmd; A_UINT32 buf_fe_ant_cmd[sizeof(A_UINT32) + sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)]; A_UINT32 buf_co_located_bt_cmd[sizeof(A_UINT32) + sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)]; A_STATUS status; /* Set co-located bt type to 1, generic for any PTA based bluetooth */ buf_co_located_bt_cmd[0] = AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV; if (pInfo->Flags & ABF_BT_CHIP_IS_QCOM) { btcoexCoLocatedBtCmd.btcoexCoLocatedBTdev = 2; } else { btcoexCoLocatedBtCmd.btcoexCoLocatedBTdev = 1; } A_MEMCPY(&buf_co_located_bt_cmd[1], (void *)&btcoexCoLocatedBtCmd, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); status = Abf_WlanDispatchIO(pInfo, AR6000_IOCTL_EXTENDED, (void *)buf_co_located_bt_cmd, (sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD) + sizeof(A_UINT32))); if (A_FAILED(status)) { A_ERR("[%s] Failed to issue Co-located BT configuration\n", __FUNCTION__); return A_ERROR; } if(pInfo->Flags & ABF_FE_ANT_IS_SA) { /* Indicate front end antenna configuration as single antenna */ A_INFO("FLAGS = %x, Issue FE antenna configuration as single \n", pInfo->Flags); btcoexFeAntCmd.btcoexFeAntType = WMI_BTCOEX_FE_ANT_SINGLE; }else { A_INFO("FLAGS = %x, Issue FE antenna configuration as dual \n", pInfo->Flags); btcoexFeAntCmd.btcoexFeAntType = WMI_BTCOEX_FE_ANT_DUAL; } buf_fe_ant_cmd[0] = AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT; A_MEMCPY(&buf_fe_ant_cmd[1], (void *)&btcoexFeAntCmd, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); status = Abf_WlanDispatchIO(pInfo, AR6000_IOCTL_EXTENDED, (void *)buf_fe_ant_cmd, (sizeof(WMI_SET_BTCOEX_FE_ANT_CMD) + sizeof(A_UINT32))); if (A_FAILED(status)) { A_ERR("[%s] Failed to issue FE ant configuration\n", __FUNCTION__); return A_ERROR; } return A_OK; }
void Abf_ShutDown(void) { A_INFO("Shutting Down\n"); /* Clean up all the resources */ Abf_BtStackNotificationDeInit(&g_AthBtFilterInstance); Abf_WlanStackNotificationDeInit(&g_AthBtFilterInstance); AthBtFilter_Detach(&g_AthBtFilterInstance); A_INFO("Shutting Down Complete\n"); }
void Abf_WlanStackNotificationDeInit(ATH_BT_FILTER_INSTANCE *pInstance) { ATHBT_FILTER_INFO *pInfo = (ATHBT_FILTER_INFO *)pInstance->pContext; ABF_WLAN_INFO *pAbfWlanInfo = pInfo->pWlanInfo; if (!pAbfWlanInfo) return; /* Terminate and wait for the WLAN Event Handler task to finish */ A_MUTEX_LOCK(&pAbfWlanInfo->hWaitEventLock); if (pAbfWlanInfo->Loop) { pAbfWlanInfo->Loop = FALSE; A_COND_WAIT(&pAbfWlanInfo->hWaitEvent, &pAbfWlanInfo->hWaitEventLock, WAITFOREVER); } A_MUTEX_UNLOCK(&pAbfWlanInfo->hWaitEventLock); /* Flush all the BT actions from the filter core */ HandleAdapterEvent(pInfo, ATH_ADAPTER_REMOVED); pInfo->pWlanInfo = NULL; A_MUTEX_DEINIT(&pAbfWlanInfo->hWaitEventLock); A_COND_DEINIT(&pAbfWlanInfo->hWaitEvent); A_MEMZERO(pAbfWlanInfo, sizeof(ABF_WLAN_INFO)); A_FREE(pAbfWlanInfo); A_INFO("WLAN Stack Notification de-init complete\n"); }
/* APIs exported to other modules */ A_STATUS Abf_WlanStackNotificationInit(ATH_BT_FILTER_INSTANCE *pInstance, A_UINT32 flags) { A_STATUS status; ATHBT_FILTER_INFO *pInfo; ABF_WLAN_INFO *pAbfWlanInfo; pInfo = (ATHBT_FILTER_INFO *)pInstance->pContext; if (pInfo->pWlanInfo) { return A_OK; } pAbfWlanInfo = (ABF_WLAN_INFO *)A_MALLOC(sizeof(ABF_WLAN_INFO)); A_MEMZERO(pAbfWlanInfo,sizeof(ABF_WLAN_INFO)); A_MUTEX_INIT(&pAbfWlanInfo->hWaitEventLock); A_COND_INIT(&pAbfWlanInfo->hWaitEvent); A_MEMZERO(pAbfWlanInfo, sizeof(ABF_WLAN_INFO)); pAbfWlanInfo->pInfo = pInfo; pAbfWlanInfo->Loop = TRUE; pInfo->pWlanInfo = pAbfWlanInfo; /* Spawn a thread which will be used to process events from WLAN */ status = A_TASK_CREATE(&pInfo->hWlanThread, WlanEventThread, pAbfWlanInfo); if (A_FAILED(status)) { A_ERR("[%s] Failed to spawn a WLAN thread\n", __FUNCTION__); return A_ERROR; } A_INFO("WLAN Stack Notification init complete\n"); return A_OK; }
A_STATUS Abf_IssueAFHViaHciLib (ABF_BT_INFO * pAbfBtInfo, int CurrentWLANChannel) { A_UINT32 center; tHCIUTILS_HCICMD_SET_AFH_CHANNELS setChannels; A_INFO("WLAN Operating Channel: %d \n", CurrentWLANChannel); if(!CurrentWLANChannel) { setChannels.first = 79; setChannels.last = 79; center = 0; }else { if( (CurrentWLANChannel < 2412) || (CurrentWLANChannel > 2470)) { return A_ERROR; } center = CurrentWLANChannel; center = center - 2400; setChannels.first = center - 10; setChannels.last = center + 10; } if (pfn_HCIUTILS_SendCmd) { (*pfn_HCIUTILS_SendCmd) (HCIUTILS_SET_AFH_CHANNELS, &setChannels); A_DEBUG("Issue AFH first =%x, last = %x, center =%x\n", setChannels.first, setChannels.last, center); } else { A_ERR( "%s : Fail to issue AFH due to NULL pointer of pfn_HCIUTILS_SendCmd\n", __FUNCTION__); return A_ERROR; } return A_OK; }
void Abf_RegisterToHciLib( ABF_BT_INFO * pAbfBtInfo) { void * handle = 0; tHCIUTILS_STATUS ret; char * pparam = NULL; int n_opcode = 0, n_type = 0; int i; A_INFO("Register To HCI LIB \n"); if (pfn_HCIUTILS_RegisterHCINotification) { for (i=0; i <= 2;i++) { ret = (*pfn_HCIUTILS_RegisterHCINotification) ( HCIUTILS_COMMAND, hciCmdList[i], eventNotificationCallback, (void *) pAbfBtInfo ); A_DEBUG("Registered for HCI cmd %x, ret= %d\n", hciCmdList[i],ret); } for (i=0; i <= 8; i++) { ret = (*pfn_HCIUTILS_RegisterHCINotification) ( HCIUTILS_EVENT, hciEventList[i], eventNotificationCallback, (void *)pAbfBtInfo ); A_DEBUG("Hcievent List[%d] =%x, ret =%x\n",i, hciEventList[i], ret); } } }
static void DelLinkEvent(ATH_BT_FILTER_INSTANCE *pInstance, struct nlmsghdr *h, int len) { A_BOOL found; struct ifinfomsg *ifi; struct rtattr * attr; int attrlen, nlmsg_len, rta_len; ATHBT_FILTER_INFO *pInfo = (ATHBT_FILTER_INFO *)pInstance->pContext; ABF_WLAN_INFO *pAbfWlanInfo = (ABF_WLAN_INFO *)pInfo->pWlanInfo; if (!pAbfWlanInfo->Handle) return; if (len < sizeof(*ifi)) { A_DEBUG("packet too short\n"); return; } ifi = NLMSG_DATA(h); nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) { A_DEBUG("bad attrlen\n"); return; } attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); found = FALSE; while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_IFNAME) { /* * Shall be used to get the socket descriptor. Also we should do * it only until we get the adapter we are interested in */ if (!(strcmp(pAbfWlanInfo->IfName, ((char *)attr + rta_len)))) { found = TRUE; } } attr = RTA_NEXT(attr, attrlen); } if (!found) return; /* Flush all the BT actions from the filter core */ HandleAdapterEvent(pInfo, ATH_ADAPTER_REMOVED); ReleaseWlanAdapter(pAbfWlanInfo); /* Reset the WLAN adapter specific info */ A_MEMZERO(pAbfWlanInfo->AdapterName, WLAN_ADAPTER_NAME_SIZE_MAX); pAbfWlanInfo->PhyCapability = 0; A_INFO("WLAN Adapter Removed\n"); }
static A_STATUS AcquireWlanAdapter(ABF_WLAN_INFO *pAbfWlanInfo) { int sd; A_STATUS status; if (pAbfWlanInfo->Handle != 0) { return A_OK; } if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { A_ERR("[%s] Error creating socket: %d\n", __FUNCTION__, sd); return A_ERROR; } pAbfWlanInfo->Handle = sd; status = GetAdapterInfo(pAbfWlanInfo); if (A_FAILED(status)) { A_ERR("[%s] Failed to get Adapter Info\n", __FUNCTION__); close(sd); pAbfWlanInfo->Handle = 0; return A_ERROR; } else { /* Try to get RTS to determinate that wlan is enabled */ A_UCHAR buf[sizeof(int)+sizeof(WMI_SET_RTS_CMD)]; ((int *)buf)[0] = AR6000_XIOCTL_AP_GET_RTS; status = Abf_WlanDispatchIO(pAbfWlanInfo->pInfo, AR6000_IOCTL_EXTENDED, (void *)buf, sizeof(buf)); if (A_FAILED(status)) { A_INFO("WMI is ready but wlan is disabled.\n"); return A_ERROR; } } return A_OK; }
static A_STATUS WirelessCustomEvent(ATH_BT_FILTER_INSTANCE *pInstance, char *buf, int len) { char *ptr; int length, i; A_UINT16 eventid; WMI_READY_EVENT *ev1; WMI_CONNECT_EVENT *ev2; WMI_REPORT_SLEEP_STATE_EVENT * ev3; A_STATUS status = A_OK; ATHBT_FILTER_INFO *pInfo = (ATHBT_FILTER_INFO *)pInstance->pContext; ABF_WLAN_INFO *pAbfWlanInfo = pInfo->pWlanInfo; do { eventid = *((A_UINT16 *)buf); ptr = buf + 2; //Skip the event id length = len - 2; switch (eventid) { case (WMI_READY_EVENTID): if (length < sizeof(WMI_READY_EVENT)) { A_ERR("[%s:%d] Check Failed\n", __FUNCTION__, __LINE__); status = A_ERROR; break; } ev1 = (WMI_READY_EVENT *)ptr; A_MEMCPY(pAbfWlanInfo->AdapterName, ev1->macaddr, ATH_MAC_LEN); pAbfWlanInfo->PhyCapability = ev1->phyCapability; A_DEBUG("WMI READY: Capability: %d, Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", pAbfWlanInfo->PhyCapability, (pAbfWlanInfo->AdapterName[0]), (pAbfWlanInfo->AdapterName[1]), (pAbfWlanInfo->AdapterName[2]), (pAbfWlanInfo->AdapterName[3]), (pAbfWlanInfo->AdapterName[4]), (pAbfWlanInfo->AdapterName[5])); /* * Open a handle for the ioctls that will be issued later * Try 10 times because the driver may not yet be ready to receive * IOCTLs, so we give the driver time to get ready by looping here */ for (i = 0; i <= 10; i++) { status = AcquireWlanAdapter(pAbfWlanInfo); if (A_SUCCESS(status)) { break; /* Break out of FOR loop, but not out of switch case statement */ } sleep(1); } if (A_FAILED(status)) { A_ERR("[%s] Failed to acquire WLAN adapter\n", __FUNCTION__); break; } /* Communicate this to the Filter task */ HandleAdapterEvent(pInfo, ATH_ADAPTER_ARRIVED); A_INFO("WLAN Adapter Added\n"); break; case (WMI_CONNECT_EVENTID): if (length < sizeof(WMI_CONNECT_EVENT)) { A_ERR("[%s:%d] Check Failed\n", __FUNCTION__, __LINE__); status = A_ERROR; break; } ev2 = (WMI_CONNECT_EVENT *)ptr; pAbfWlanInfo->Channel = ev2->u.infra_ibss_bss.channel; A_DEBUG("WMI CONNECT: Channel: %d\n", ev2->u.infra_ibss_bss.channel); IndicateCurrentWLANOperatingChannel(pInfo, pAbfWlanInfo->Channel); break; case (WMI_DISCONNECT_EVENTID): A_DEBUG("WMI DISCONNECT: %d\n", len); IndicateCurrentWLANOperatingChannel(pInfo, 0); break; case (WMI_ERROR_REPORT_EVENTID): A_DEBUG("WMI ERROR REPORT: %d\n", len); break; case (WMI_SCAN_COMPLETE_EVENTID): A_DEBUG("WMI SCAN COMPLETE: %d\n", len); break; case (WMI_REPORT_SLEEP_STATE_EVENTID): A_DEBUG("WMI_REPORT_SLEEP_STATE_EVENTID: %d\n", len); if(length < sizeof(WMI_REPORT_SLEEP_STATE_EVENT)) { A_ERR("[%s]Incorrect length passed - length = %d, len =%d\n", __FUNCTION__, length, len); } ev3 = (WMI_REPORT_SLEEP_STATE_EVENT *)ptr; switch(ev3->sleepState) { case WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP: HandleAdapterEvent(pInfo, ATH_ADAPTER_REMOVED); break; case WMI_REPORT_SLEEP_STATUS_IS_AWAKE: Abf_WlanIssueFrontEndConfig( pInfo); HandleAdapterEvent(pInfo, ATH_ADAPTER_ARRIVED); break; } break; default: //A_DEBUG("Event: 0x%x, Not Handled\n", eventid); break; } } while (FALSE); return status; }
/* Internal functions */ static void * WlanEventThread(void *arg) { int left, ret, sd; struct timeval tv; socklen_t fromlen; struct nlmsghdr *h; fd_set readfds, tempfds; char buf[WLAN_EVENT_SIZE_MAX]; struct sockaddr_nl from, local; ABF_WLAN_INFO *pAbfWlanInfo = (ABF_WLAN_INFO *)arg; ATHBT_FILTER_INFO *pInfo = pAbfWlanInfo->pInfo; ATH_BT_FILTER_INSTANCE *pInstance = pInfo->pInstance; A_STATUS status; A_INFO("Starting the WLAN Event Handler task\n"); A_INFO("Checking WLAN adapter on startup .. \n"); if (!pInstance->pWlanAdapterName) { Abf_WlanCheckSettings(pAbfWlanInfo->IfName, NULL); if (pAbfWlanInfo->IfName[0]) { pAbfWlanInfo->IfIndex = if_nametoindex(pAbfWlanInfo->IfName); } } status = AcquireWlanAdapter(pAbfWlanInfo); if (A_FAILED(status)) { A_INFO("No WLAN adapter on startup (OKAY) \n"); }else { /* Communicate this to the Filter task */ HandleAdapterEvent(pInfo, ATH_ADAPTER_ARRIVED); A_INFO("WLAN Adapter Added\n"); } do { sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sd < 0) { A_ERR("[%s] socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE): %d\n", __FUNCTION__, sd); break; } A_MEMZERO(&local, sizeof(struct sockaddr_nl)); local.nl_family = AF_NETLINK; local.nl_groups = RTMGRP_LINK; if ((ret = bind(sd, (struct sockaddr *) &local, sizeof(local))) < 0) { A_ERR("[%s] bind(netlink): %d\n", __FUNCTION__, ret); close(sd); break; } FD_ZERO(&readfds); FD_SET(sd, &readfds); while (pAbfWlanInfo->Loop) { A_MEMCPY(&tempfds, &readfds, sizeof(fd_set)); tv.tv_sec = 1; tv.tv_usec = 0; ret = select(sd+1, &tempfds, NULL, NULL, &tv); if ((ret < 0) && (errno != EINTR)) { A_ERR("[%s] select failed: %d\n", __FUNCTION__, ret); break; } else if ((ret > 0) && (FD_ISSET(sd, &tempfds))) { fromlen = sizeof(from); do { left = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *) &from, &fromlen); } while (left == -1 && errno == EINTR); if (left < 0) { A_ERR("[%s] recvfrom(netlink)\n", __FUNCTION__); continue; // break; } h = (struct nlmsghdr *) buf; while (left >= sizeof(*h)) { int len, plen; len = h->nlmsg_len; plen = len - sizeof(*h); if (len > left || plen < 0) { A_ERR("[%s] malformed netlink message\n", __FUNCTION__); continue; } //A_DEBUG("RTM Message Type: %s\n", // ((h->nlmsg_type == RTM_NEWLINK) ? // "RTM_NEWLINK" : ((h->nlmsg_type == RTM_DELLINK) ? // "RTM_DELLINK" : "RTM_OTHER"))); switch (h->nlmsg_type) { case RTM_NEWLINK: NewLinkEvent(pInstance, h, plen); break; case RTM_DELLINK: DelLinkEvent(pInstance, h, plen); break; default: break; } len = NLMSG_ALIGN(len); left -= len; h = (struct nlmsghdr *) ((char *) h + len); } } } close(sd); } while (FALSE); /* Clean up the resources allocated in this task */ A_INFO("Terminating the WLAN Event Handler task\n"); A_MUTEX_LOCK(&pAbfWlanInfo->hWaitEventLock); pAbfWlanInfo->Loop = FALSE; A_COND_SIGNAL(&pAbfWlanInfo->hWaitEvent); A_MUTEX_UNLOCK(&pAbfWlanInfo->hWaitEventLock); return NULL; }
static void eventNotificationCallback ( tHCIUTILS_NOTIFICATION * pEvent) { ABF_BT_INFO *pAbfBtInfo = (ABF_BT_INFO *)g_pAbfBtInfo; ATHBT_FILTER_INFO *pInfo = pAbfBtInfo->pInfo; ATH_BT_FILTER_INSTANCE *pInstance = pInfo->pInstance; if(pEvent->tType == HCIUTILS_COMMAND) { if(pEvent->nOpCode == HCI_CMD_OPCODE_INQUIRY_START) { A_DEBUG("Device Inquiry Started \n"); pAbfBtInfo->btInquiryState |= (1 << 0); AthBtIndicateState(pInstance, ATH_BT_INQUIRY, STATE_ON); } if(pEvent->nOpCode == HCI_CMD_OPCODE_INQUIRY_CANCEL ) { A_DEBUG("Device Inquiry cancelled \n"); if(pAbfBtInfo->btInquiryState) { pAbfBtInfo->btInquiryState &= ~(1 << 0); AthBtIndicateState(pInstance, ATH_BT_INQUIRY, STATE_OFF); } } if(pEvent->nOpCode == HCI_CMD_OPCODE_CONNECT) { A_DEBUG("Bt-Connect\n"); } } if(pEvent->tType == HCIUTILS_EVENT) { #define LMP_FEATURE_ACL_EDR_2MBPS_BYTE_INDEX 3 #define LMP_FEATURE_ACL_EDR_2MBPS_BIT_MASK 0x2 #define LMP_FEATURE_ACL_EDR_3MBPS_BYTE_INDEX 3 #define LMP_FEATURE_ACL_EDR_3MBPS_BIT_MASK 0x4 #define LMP_FEATURES_LENGTH 8 if(pEvent->nOpCode == HCI_EVT_REMOTE_DEV_LMP_VERSION) { A_UINT32 i = 0; A_UINT32 len = pEvent->n_data_length; A_UCHAR * eventPtr = (A_UCHAR *)pEvent->p_notification_data_buf; A_UINT8 *lmp_features; /* Process LMP Features */ A_DUMP_BUFFER(eventPtr, len,"Remote Device LMP Features:"); eventPtr += 1; len -= 1 ; lmp_features = &eventPtr[3]; A_DUMP_BUFFER(lmp_features, sizeof(lmp_features),"Remote Device LMP Features:"); if ((lmp_features[LMP_FEATURE_ACL_EDR_2MBPS_BYTE_INDEX] & LMP_FEATURE_ACL_EDR_2MBPS_BIT_MASK) || (lmp_features[LMP_FEATURE_ACL_EDR_3MBPS_BYTE_INDEX] & LMP_FEATURE_ACL_EDR_3MBPS_BIT_MASK)) { A_DEBUG("Device is EDR capable \n"); pAbfBtInfo->DefaultAudioDeviceLmpVersion = 3; } else { A_DEBUG("Device is NOT EDR capable \n"); pAbfBtInfo->DefaultAudioDeviceLmpVersion = 2; } pAbfBtInfo->DefaultRemoteAudioDevicePropsValid = TRUE; pInfo->A2DPConnection_LMPVersion = pInfo->SCOConnection_LMPVersion = pAbfBtInfo->DefaultAudioDeviceLmpVersion; } if(pEvent->nOpCode == HCI_EVT_REMOTE_DEV_VERSION) { A_UCHAR * eventPtr = (A_UCHAR *)pEvent->p_notification_data_buf; A_UINT32 len = pEvent->n_data_length; A_DUMP_BUFFER(eventPtr, len,"Remote Device Version"); eventPtr += 1; len -= 1; A_DUMP_BUFFER(eventPtr, len,"Remote Device Version"); if (eventPtr[3] == 0) { strcpy(&pAbfBtInfo->DefaultRemoteAudioDeviceVersion[0], "1.0"); pAbfBtInfo->DefaultAudioDeviceLmpVersion = 0; A_DEBUG("Its 1.0 \n"); } else if (eventPtr[3] == 1) { strcpy(&pAbfBtInfo->DefaultRemoteAudioDeviceVersion[0], "1.1"); pAbfBtInfo->DefaultAudioDeviceLmpVersion = 1; A_DEBUG("Its 1.1 \n"); } else if (eventPtr[3] == 2) { strcpy(&pAbfBtInfo->DefaultRemoteAudioDeviceVersion[0], "1.2"); pAbfBtInfo->DefaultAudioDeviceLmpVersion = 2; A_DEBUG("Its 1.2 \n"); } else if (eventPtr[3] == 3) { strcpy(&pAbfBtInfo->DefaultRemoteAudioDeviceVersion[0], "2.0"); /* pAbfBtInfo->DefaultAudioDeviceLmpVersion = 3; */ A_DEBUG("Its 2.0 \n"); }else { strcpy(&pAbfBtInfo->DefaultRemoteAudioDeviceVersion[0], "2.1"); /* pAbfBtInfo->DefaultAudioDeviceLmpVersion = 4; */ A_DEBUG("Its 2.1 \n"); } pInfo->A2DPConnection_LMPVersion = pInfo->SCOConnection_LMPVersion = pAbfBtInfo->DefaultAudioDeviceLmpVersion; } if (pEvent->nOpCode == EVT_INQUIRY_COMPLETE) { A_DEBUG("Device Inquiry Completed\n"); if(pAbfBtInfo->btInquiryState) { pAbfBtInfo->btInquiryState &= ~(1 << 0); AthBtIndicateState(pInstance, ATH_BT_INQUIRY, STATE_OFF); } } if (pEvent->nOpCode == EVT_PIN_CODE_REQ) { A_DEBUG("Pin Code Request\n"); } if (pEvent->nOpCode == EVT_LINK_KEY_NOTIFY) { A_DEBUG("link key notify\n"); } if(pEvent->nOpCode == HCI_EVT_ROLE_CHANGE) { A_DEBUG("Role Change\n"); A_UCHAR * eventPtr = (A_UCHAR *)pEvent->p_notification_data_buf; A_UINT32 len = pEvent->n_data_length; A_DUMP_BUFFER(eventPtr, len,"Remote Device Role "); eventPtr += 8; len -= 8; if(*eventPtr == 0x00) { A_DEBUG("ROLE IS MASTER \n"); pAbfBtInfo->pInfo->A2DPConnection_Role = 0x0; } if(*eventPtr == 0x01) { A_DEBUG("ROLE IS SLAVE \n"); pAbfBtInfo->pInfo->A2DPConnection_Role = 0x1; } } if(pEvent->nOpCode == EVT_CONN_COMPLETE) { A_DEBUG("Conn complete\n"); if(pAbfBtInfo->btInquiryState) { pAbfBtInfo->btInquiryState &= ~(1 << 1); AthBtIndicateState(pInstance, ATH_BT_INQUIRY, STATE_OFF); } } if(pEvent->nOpCode == HCI_EVT_SCO_CONNECT_COMPLETE) { A_UINT32 len = pEvent->n_data_length; A_UCHAR * eventPtr = (A_UCHAR*)pEvent->p_notification_data_buf; A_DUMP_BUFFER(eventPtr, len,"SCO CONNECT_COMPLETE"); A_DEBUG("SCO CONNECT COMPLETE \n"); pInfo->SCOConnection_LMPVersion = pAbfBtInfo->DefaultAudioDeviceLmpVersion; pInfo->SCOConnectInfo.LinkType = eventPtr[10]; pInfo->SCOConnectInfo.TransmissionInterval = eventPtr[11]; pInfo->SCOConnectInfo.RetransmissionInterval = eventPtr[12]; pInfo->SCOConnectInfo.RxPacketLength = eventPtr[13]; pInfo->SCOConnectInfo.TxPacketLength = eventPtr[15]; pInfo->SCOConnectInfo.Valid = TRUE; A_INFO("HCI SYNC_CONN_COMPLETE event captured, conn info (%d, %d, %d, %d, %d) \n", pInfo->SCOConnectInfo.LinkType, pInfo->SCOConnectInfo.TransmissionInterval, pInfo->SCOConnectInfo.RetransmissionInterval, pInfo->SCOConnectInfo.RxPacketLength, pInfo->SCOConnectInfo.TxPacketLength); AthBtIndicateState(pInstance, pInfo->SCOConnectInfo.LinkType == BT_LINK_TYPE_ESCO? ATH_BT_ESCO: ATH_BT_SCO, STATE_ON); } if(pEvent->nOpCode == HCI_EVT_DISCONNECT) { A_UINT32 bitmap = FCore_GetCurrentBTStateBitMap(&pInfo->FilterCore); A_DEBUG("HCI_EVT_DISCONNECT event \n"); if( (bitmap & (1 << ATH_BT_SCO))|| (bitmap & (1 << ATH_BT_ESCO))) { AthBtIndicateState(pInstance, pInfo->SCOConnectInfo.LinkType == BT_LINK_TYPE_ESCO? ATH_BT_ESCO: ATH_BT_SCO, STATE_OFF); } ForgetRemoteAudioDevice(pAbfBtInfo); pInfo->SCOConnectInfo.Valid = FALSE; pAbfBtInfo->pInfo->A2DPConnection_Role = 0x0; } } }
int main(int argc, char *argv[]) { int ret; char *config_file = NULL; int opt = 0, daemonize = 1, debug = 0, console_output=0; progname = argv[0]; A_STATUS status; struct sigaction sa; ATHBT_FILTER_INFO *pInfo; A_UINT32 btfiltFlags = 0; A_MEMZERO(&g_AthBtFilterInstance, sizeof(ATH_BT_FILTER_INSTANCE)); /* * Keep an option to specify the wireless extension. By default, * assume it to be equal to WIRELESS_EXT TODO */ /* Get user specified options */ while ((opt = getopt(argc, argv, "bsvandczxf:w:")) != EOF) { switch (opt) { case 'n': daemonize = 0; break; case 'd': debug = 1; break; case 'f': if (optarg) { config_file = strdup(optarg); } break; case 'c': console_output = 1; break; case 'a': btfiltFlags |= ABF_ENABLE_AFH_CHANNEL_CLASSIFICATION; break; case 'z': btfiltFlags |= ABF_USE_HCI_FILTER_FOR_HEADSET_PROFILE; break; case 'v': btfiltFlags |= ABF_WIFI_CHIP_IS_VENUS ; A_DEBUG("wifi chip is venus\n"); break; case 'x': btfiltFlags |= ABF_BT_CHIP_IS_ATHEROS ; A_DEBUG("bt chip is atheros\n"); break; case 's': btfiltFlags |= ABF_FE_ANT_IS_SA ; A_DEBUG("Front End Antenna Configuration is single antenna \n"); break; case 'w': memset(wifname, '\0', IFNAMSIZ); strcpy(wifname, optarg); g_AthBtFilterInstance.pWlanAdapterName = (A_CHAR *)&wifname; break; case 'b': btfiltFlags |= ABF_USE_ONLY_DBUS_FILTERING; break; default: usage(); exit(1); } } /* Launch the daemon if desired */ if (daemonize && daemon(0, console_output ? 1 : 0)) { printf("Can't daemonize: %s\n", strerror(errno)); exit(1); } /* Initialize the debug infrastructure */ A_DBG_INIT("ATHBT", "Ath BT Filter Daemon"); if (debug) { if (console_output) { A_DBG_SET_OUTPUT_TO_CONSOLE(); } // setlogmask(LOG_INFO | LOG_DEBUG | LOG_ERR); A_INFO("Enabling Debug Information\n"); A_SET_DEBUG(1); } if (config_file) { A_DEBUG("Config file: %s\n", config_file); if (!(gConfigFile = fopen(config_file, "r"))) { A_ERR("[%s] fopen failed\n", __FUNCTION__); } } A_MEMZERO(&sa, sizeof(struct sigaction)); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = Abf_SigTerm; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); Abf_HciLibInit(&btfiltFlags); /* Initialize the Filter core */ do { Abf_WlanCheckSettings(wifname, &btfiltFlags); ret = AthBtFilter_Attach(&g_AthBtFilterInstance, btfiltFlags ); if (ret) { A_ERR("Filter initialization failed\n"); break; } /* Initialize the WLAN notification mechanism */ status = Abf_WlanStackNotificationInit(&g_AthBtFilterInstance, btfiltFlags ); if (A_FAILED(status)) { AthBtFilter_Detach(&g_AthBtFilterInstance); A_ERR("WLAN stack notification init failed\n"); break; } /* Initialize the BT notification mechanism */ status = Abf_BtStackNotificationInit(&g_AthBtFilterInstance,btfiltFlags); if (A_FAILED(status)) { Abf_WlanStackNotificationDeInit(&g_AthBtFilterInstance); AthBtFilter_Detach(&g_AthBtFilterInstance); A_ERR("BT stack notification init failed\n"); break; } /* Check for errors on the return value TODO */ pInfo = g_AthBtFilterInstance.pContext; GpInfo = pInfo; A_DEBUG("Service running, waiting for termination .... \n"); /* wait for termination signal */ while (!terminated) { sleep(1); } } while(FALSE); /* Initiate the shutdown sequence */ if(GpInfo != NULL) { AthBtFilter_State_Off(GpInfo); } Abf_ShutDown(); Abf_HciLibDeInit(); /* Shutdown */ if (gConfigFile) { fclose(gConfigFile); } if (config_file) { A_FREE(config_file); } A_DEBUG("Service terminated \n"); A_MEMZERO(&g_AthBtFilterInstance, sizeof(ATH_BT_FILTER_INSTANCE)); A_DBG_DEINIT(); return 0; }