/* 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; }
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; }