/* * cu_wext.c * * Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /**************************************************************************** * * MODULE: CU_Wext.c * * PURPOSE: * * DESCRIPTION: * ============ * * ****************************************************************************/ /* includes */ /************/ #include "cu_osapi.h" #include "oserr.h" #include #include #include #include #include #include "TWDriver.h" #include "STADExternalIf.h" #include "ParsEvent.h" #include "ipc_sta.h" #include "cu_os.h" /* defines */ /***********/ /* local types */ /***************/ /* Module control block */ typedef struct { THandle hIpcSta; union iwreq_data req_data; struct iw_scan_req *scan_req; U16 scan_flag; } TCuWext; /* local variables */ /*******************/ /* local fucntions */ /*******************/ static S32 CuWext_FillBssidList(struct iw_event *iwe, OS_802_11_BSSID_EX* bssidList, S32 index) { S32 res = 0; switch(iwe->cmd) { case SIOCGIWAP: os_memcpy(bssidList[index].MacAddress, iwe->u.ap_addr.sa_data, MAC_ADDR_LEN); bssidList[index].Configuration.BeaconPeriod = 0; /* default configuration */ res = 1; break; case SIOCGIWESSID: bssidList[index-1].Ssid.SsidLength = iwe->u.data.length; os_memcpy(bssidList[index-1].Ssid.Ssid, iwe->u.data.pointer, bssidList[index-1].Ssid.SsidLength); if(iwe->u.data.length != MAX_SSID_LEN) bssidList[index-1].Ssid.Ssid[bssidList[index-1].Ssid.SsidLength] = 0; break; case SIOCGIWNAME: { unsigned i; S8 buffer[IFNAMSIZ]; static const char *ieee80211_modes[] = { "?", "IEEE 802.11 B", "IEEE 802.11 A", "IEEE 802.11 BG", "IEEE 802.11 ABG" }; os_memset(buffer, 0, IFNAMSIZ); os_memcpy(buffer, iwe->u.name, IFNAMSIZ); for(i=0;iu.mode == IW_MODE_ADHOC) bssidList[index-1].InfrastructureMode = os802_11IBSS; else if (iwe->u.mode == IW_MODE_INFRA) bssidList[index-1].InfrastructureMode = os802_11Infrastructure; else if (iwe->u.mode == IW_MODE_AUTO) bssidList[index-1].InfrastructureMode = os802_11AutoUnknown; else bssidList[index-1].InfrastructureMode = os802_11InfrastructureMax; break; case SIOCGIWFREQ: bssidList[index-1].Configuration.Union.channel = iwe->u.freq.m; break; case IWEVQUAL: bssidList[index-1].Rssi = (S8)iwe->u.qual.level; break; case SIOCGIWENCODE: if(iwe->u.data.flags == (IW_ENCODE_ENABLED | IW_ENCODE_NOKEY)) { bssidList[index-1].Privacy = TRUE; bssidList[index-1].Capabilities |= CAP_PRIVACY_MASK<u.data.pointer, iwe->u.data.length); if(!os_strncmp(buffer, (PS8)"Bcn", 3)) { char *p1; p1 = strtok(&buffer[10], " "); bssidList[index-1].Configuration.BeaconPeriod = atoi(p1); } } break; } return res; } /* functions */ /*************/ THandle CuOs_Create(THandle hIpcSta) { TCuWext* pCuWext = (TCuWext*)os_MemoryCAlloc(sizeof(TCuWext), sizeof(U8)); if(pCuWext == NULL) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Create - cant allocate control block\n"); return NULL; } pCuWext->hIpcSta = hIpcSta; return pCuWext; } VOID CuOs_Destroy(THandle hCuWext) { TCuWext* pCuWext = (TCuWext*)hCuWext; os_MemoryFree(pCuWext); } S32 CuOs_Get_SSID(THandle hCuWext, OS_802_11_SSID* ssid) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memset(ssid->Ssid, 0, sizeof(OS_802_11_SSID) - sizeof(U32)); pCuWext->req_data.essid.pointer = (PVOID)ssid->Ssid; pCuWext->req_data.essid.length = sizeof(OS_802_11_SSID) - sizeof(U32); pCuWext->req_data.essid.flags = 0; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWESSID, &pCuWext->req_data, sizeof(struct iw_point)); if(res != OK) return res; ssid->SsidLength = pCuWext->req_data.essid.length; return OK; } S32 CuOs_Get_BSSID(THandle hCuWext, TMacAddr bssid) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res,i; os_memset(&pCuWext->req_data.ap_addr, 0x00, sizeof(struct sockaddr)); res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWAP, &pCuWext->req_data, sizeof(struct sockaddr)); if(res != OK) return res; for(i=0;ireq_data.ap_addr.sa_data[i]; return OK; } S32 CuOs_GetCurrentChannel(THandle hCuWext, U32* channel) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; pCuWext->req_data.freq.m = 0; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWFREQ, &pCuWext->req_data, sizeof(struct iw_freq )); if(res != OK) return res; *channel = pCuWext->req_data.freq.m; return OK; } /*Usage example of SIOCGIWSTATS. This WEXT is used by wireless tools such as iwconfig, iwlib etc.*/ S32 CuOs_GetCurrentStats(THandle hCuWext, S32* rssi) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; struct iw_statistics stat; *rssi = 0; pCuWext->req_data.data.pointer = &stat; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWSTATS, &pCuWext->req_data, sizeof(struct iw_statistics)); if(res != OK) return res; *rssi = stat.qual.level; return OK; } S32 CuOs_Start_Scan(THandle hCuWext, OS_802_11_SSID* ssid, U8 scanType) { TCuWext* pCuWext = (TCuWext*)hCuWext; struct iw_scan_req tReq; S32 res; if (ssid->SsidLength > IW_ESSID_MAX_SIZE) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Start_Scan - too long SSID (%lu)\n",ssid->SsidLength); return OSAL_ERROR; } if (ssid->Ssid[0] && ssid->SsidLength) { os_memset(&tReq, 0, sizeof(tReq)); tReq.essid_len = ssid->SsidLength; /* * tReq.bssid.sa_family = ARPHRD_ETHER; * os_memset(tReq.bssid.sa_data, 0xff, ETH_ALEN); */ os_memcpy(tReq.essid, ssid->Ssid, ssid->SsidLength); pCuWext->scan_req = &tReq; pCuWext->req_data.data.flags = IW_SCAN_THIS_ESSID; } else { pCuWext->req_data.data.flags = 0; } tReq.scan_type = scanType; pCuWext->req_data.data.pointer = &tReq; pCuWext->req_data.data.length = sizeof(struct iw_scan_req); res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWSCAN, &pCuWext->req_data, sizeof(struct iw_point)); if(res != OK) return res; return OK; } S32 CuOs_GetBssidList(THandle hCuWext, OS_802_11_BSSID_LIST_EX *bssidList) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res, NumberOfItems; /* allocate the scan result buffer */ U8* buffer = os_MemoryCAlloc(IW_SCAN_MAX_DATA, sizeof(U8)); if(buffer == NULL) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Get_BssidList - cant allocate scan result buffer\n"); return EOALERR_CU_WEXT_ERROR_CANT_ALLOCATE; } NumberOfItems = 0; pCuWext->req_data.data.pointer = buffer; pCuWext->req_data.data.flags = 0; do { pCuWext->req_data.data.length = IW_SCAN_MAX_DATA; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWSCAN, &pCuWext->req_data, sizeof(struct iw_point)); if(res != OK) { os_MemoryFree(buffer); return res; } /* parse the scan results */ if(pCuWext->req_data.data.length) { struct iw_event iwe; struct stream_descr stream; S32 ret; /* init the event stream */ os_memset((char *)&stream, '\0', sizeof(struct stream_descr)); stream.current = (char *)buffer; stream.end = (char *)(buffer + pCuWext->req_data.data.length); do { /* Extract an event and print it */ ret = ParsEvent_GetEvent(&stream, &iwe); if(ret > 0) NumberOfItems += CuWext_FillBssidList(&iwe, bssidList->Bssid, NumberOfItems); } while(ret > 0); } } while(pCuWext->req_data.data.flags); bssidList->NumberOfItems = NumberOfItems; /* free the scan result buffer */ os_MemoryFree(buffer); return OK; } S32 CuOs_Set_BSSID(THandle hCuWext, TMacAddr bssid) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memcpy(pCuWext->req_data.ap_addr.sa_data, bssid, MAC_ADDR_LEN); res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWAP, &pCuWext->req_data, sizeof(struct sockaddr)); if(res != OK) return res; return OK; } S32 CuOs_Set_ESSID(THandle hCuWext, OS_802_11_SSID* ssid) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; pCuWext->req_data.essid.pointer = (PVOID)ssid->Ssid; pCuWext->req_data.essid.length = ssid->SsidLength; if(ssid->SsidLength) pCuWext->req_data.essid.flags = 1; else pCuWext->req_data.essid.flags = 0; pCuWext->req_data.essid.flags |= SET_SSID_WITHOUT_SUPPL; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWESSID, &pCuWext->req_data, sizeof(struct sockaddr)); if(res != OK) return res; return OK; } S32 CuOs_GetTxPowerLevel(THandle hCuWext, S32* pTxPowerLevel) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memset(&pCuWext->req_data.txpower, 0, sizeof(struct iw_param)); res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWTXPOW, &pCuWext->req_data, sizeof(struct iw_param)); if(res != OK) return res; *pTxPowerLevel = pCuWext->req_data.txpower.value; return OK; } S32 CuOs_SetTxPowerLevel(THandle hCuWext, S32 txPowerLevel) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memset(&pCuWext->req_data.txpower, 0, sizeof(struct iw_param)); pCuWext->req_data.txpower.value = txPowerLevel; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWTXPOW, &pCuWext->req_data, sizeof(struct iw_param)); if(res != OK) return res; return OK; } S32 CuOs_GetRtsTh(THandle hCuWext, PS32 pRtsTh) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memset(&pCuWext->req_data.rts, 0, sizeof(struct iw_param)); res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWRTS, &pCuWext->req_data, sizeof(struct iw_param)); if(res != OK) return res; *pRtsTh = pCuWext->req_data.rts.value; return OK; } S32 CuOs_SetRtsTh(THandle hCuWext, S32 RtsTh) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memset(&pCuWext->req_data.rts, 0, sizeof(struct iw_param)); pCuWext->req_data.rts.value = RtsTh; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWRTS, &pCuWext->req_data, sizeof(struct iw_param)); if(res != OK) return res; return OK; } S32 CuOs_GetFragTh(THandle hCuWext, PS32 pFragTh) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memset(&pCuWext->req_data.frag, 0, sizeof(struct iw_param)); res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWFRAG, &pCuWext->req_data, sizeof(struct iw_param)); if(res != OK) return res; *pFragTh = pCuWext->req_data.frag.value; return OK; } S32 CuOs_SetFragTh(THandle hCuWext, S32 FragTh) { TCuWext* pCuWext = (TCuWext*)hCuWext; S32 res; os_memset(&pCuWext->req_data.frag, 0, sizeof(struct iw_param)); pCuWext->req_data.frag.value = FragTh; res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWFRAG, &pCuWext->req_data, sizeof(struct iw_param)); if(res != OK) return res; return OK; } /*stab function (should be filled later on for Linux to get ThreadID of the WLAN driver*/ S32 CuOs_GetDriverThreadId(THandle hCuWext, U32* threadid) { return OK; }