1 /* 2 * cu_wext.c 3 * 4 * Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /**************************************************************************** 20 * 21 * MODULE: CU_Wext.c 22 * 23 * PURPOSE: 24 * 25 * DESCRIPTION: 26 * ============ 27 * 28 * 29 ****************************************************************************/ 30 31 /* includes */ 32 /************/ 33 #include "cu_osapi.h" 34 #include "oserr.h" 35 #include <net/if.h> 36 #include <linux/rtnetlink.h> 37 #include <linux/wireless.h> 38 #include <string.h> 39 #include <stdlib.h> 40 41 #include "TWDriver.h" 42 #include "STADExternalIf.h" 43 #include "ParsEvent.h" 44 #include "ipc_sta.h" 45 #include "cu_os.h" 46 47 /* defines */ 48 /***********/ 49 50 /* local types */ 51 /***************/ 52 /* Module control block */ 53 typedef struct 54 { 55 THandle hIpcSta; 56 union iwreq_data req_data; 57 58 struct iw_scan_req *scan_req; 59 U16 scan_flag; 60 } TCuWext; 61 62 /* local variables */ 63 /*******************/ 64 65 /* local fucntions */ 66 /*******************/ 67 static S32 CuWext_FillBssidList(struct iw_event *iwe, OS_802_11_BSSID_EX* bssidList, S32 index) 68 { 69 S32 res = 0; 70 switch(iwe->cmd) 71 { 72 case SIOCGIWAP: 73 os_memcpy(bssidList[index].MacAddress, iwe->u.ap_addr.sa_data, MAC_ADDR_LEN); 74 bssidList[index].Configuration.BeaconPeriod = 0; /* default configuration */ 75 res = 1; 76 break; 77 case SIOCGIWESSID: 78 bssidList[index-1].Ssid.SsidLength = iwe->u.data.length; 79 os_memcpy(bssidList[index-1].Ssid.Ssid, iwe->u.data.pointer, bssidList[index-1].Ssid.SsidLength); 80 if(iwe->u.data.length != MAX_SSID_LEN) 81 bssidList[index-1].Ssid.Ssid[bssidList[index-1].Ssid.SsidLength] = 0; 82 break; 83 case SIOCGIWNAME: 84 { 85 unsigned i; 86 S8 buffer[IFNAMSIZ]; 87 static const char *ieee80211_modes[] = { 88 "?", 89 "IEEE 802.11 B", 90 "IEEE 802.11 A", 91 "IEEE 802.11 BG", 92 "IEEE 802.11 ABG" }; 93 94 os_memset(buffer, 0, IFNAMSIZ); 95 os_memcpy(buffer, iwe->u.name, IFNAMSIZ); 96 for(i=0;i<SIZE_ARR(ieee80211_modes); i++) 97 if (0 == os_strcmp((PS8)ieee80211_modes[i], buffer)) 98 break; 99 bssidList[index-1].NetworkTypeInUse = i; 100 } 101 break; 102 case SIOCGIWMODE: 103 if(iwe->u.mode == IW_MODE_ADHOC) 104 bssidList[index-1].InfrastructureMode = os802_11IBSS; 105 else if (iwe->u.mode == IW_MODE_INFRA) 106 bssidList[index-1].InfrastructureMode = os802_11Infrastructure; 107 else if (iwe->u.mode == IW_MODE_AUTO) 108 bssidList[index-1].InfrastructureMode = os802_11AutoUnknown; 109 else 110 bssidList[index-1].InfrastructureMode = os802_11InfrastructureMax; 111 112 break; 113 case SIOCGIWFREQ: 114 bssidList[index-1].Configuration.Union.channel = iwe->u.freq.m; 115 break; 116 case IWEVQUAL: 117 bssidList[index-1].Rssi = (S8)iwe->u.qual.level; 118 break; 119 case SIOCGIWENCODE: 120 if(iwe->u.data.flags == (IW_ENCODE_ENABLED | IW_ENCODE_NOKEY)) 121 { 122 bssidList[index-1].Privacy = TRUE; 123 bssidList[index-1].Capabilities |= CAP_PRIVACY_MASK<<CAP_PRIVACY_SHIFT; 124 } 125 else 126 { 127 bssidList[index-1].Privacy = FALSE; 128 bssidList[index-1].Capabilities &= ~(CAP_PRIVACY_MASK<<CAP_PRIVACY_SHIFT); 129 } 130 break; 131 case SIOCGIWRATE: 132 break; 133 case IWEVCUSTOM: 134 { 135 S8 buffer[100]; 136 137 os_memset(buffer, 0, 100); 138 os_memcpy(buffer, iwe->u.data.pointer, iwe->u.data.length); 139 140 if(!os_strncmp(buffer, (PS8)"Bcn", 3)) 141 { 142 char *p1; 143 p1 = strtok(&buffer[10], " "); 144 bssidList[index-1].Configuration.BeaconPeriod = atoi(p1); 145 } 146 } 147 break; 148 } 149 150 return res; 151 } 152 153 154 /* functions */ 155 /*************/ 156 157 THandle CuOs_Create(THandle hIpcSta) 158 { 159 TCuWext* pCuWext = (TCuWext*)os_MemoryCAlloc(sizeof(TCuWext), sizeof(U8)); 160 if(pCuWext == NULL) 161 { 162 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Create - cant allocate control block\n"); 163 return NULL; 164 } 165 166 pCuWext->hIpcSta = hIpcSta; 167 168 return pCuWext; 169 } 170 171 VOID CuOs_Destroy(THandle hCuWext) 172 { 173 TCuWext* pCuWext = (TCuWext*)hCuWext; 174 175 os_MemoryFree(pCuWext); 176 } 177 178 S32 CuOs_Get_SSID(THandle hCuWext, OS_802_11_SSID* ssid) 179 { 180 TCuWext* pCuWext = (TCuWext*)hCuWext; 181 S32 res; 182 183 os_memset(ssid->Ssid, 0, sizeof(OS_802_11_SSID) - sizeof(U32)); 184 185 pCuWext->req_data.essid.pointer = (PVOID)ssid->Ssid; 186 pCuWext->req_data.essid.length = sizeof(OS_802_11_SSID) - sizeof(U32); 187 pCuWext->req_data.essid.flags = 0; 188 189 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWESSID, &pCuWext->req_data, sizeof(struct iw_point)); 190 if(res != OK) 191 return res; 192 193 ssid->SsidLength = pCuWext->req_data.essid.length; 194 195 return OK; 196 } 197 198 S32 CuOs_Get_BSSID(THandle hCuWext, TMacAddr bssid) 199 { 200 TCuWext* pCuWext = (TCuWext*)hCuWext; 201 S32 res,i; 202 203 os_memset(&pCuWext->req_data.ap_addr, 0x00, sizeof(struct sockaddr)); 204 205 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWAP, &pCuWext->req_data, sizeof(struct sockaddr)); 206 if(res != OK) 207 return res; 208 209 for(i=0;i<MAC_ADDR_LEN;i++) 210 bssid[i] = pCuWext->req_data.ap_addr.sa_data[i]; 211 212 return OK; 213 } 214 215 S32 CuOs_GetCurrentChannel(THandle hCuWext, U32* channel) 216 { 217 TCuWext* pCuWext = (TCuWext*)hCuWext; 218 S32 res; 219 220 pCuWext->req_data.freq.m = 0; 221 222 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWFREQ, &pCuWext->req_data, sizeof(struct iw_freq )); 223 if(res != OK) 224 return res; 225 226 *channel = pCuWext->req_data.freq.m; 227 228 return OK; 229 } 230 231 /*Usage example of SIOCGIWSTATS. This WEXT is used by wireless tools such as iwconfig, iwlib etc.*/ 232 S32 CuOs_GetCurrentStats(THandle hCuWext, S32* rssi) 233 { 234 TCuWext* pCuWext = (TCuWext*)hCuWext; 235 S32 res; 236 struct iw_statistics stat; 237 *rssi = 0; 238 239 pCuWext->req_data.data.pointer = &stat; 240 241 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWSTATS, &pCuWext->req_data, sizeof(struct iw_statistics)); 242 if(res != OK) 243 return res; 244 245 *rssi = stat.qual.level; 246 247 return OK; 248 } 249 250 S32 CuOs_Start_Scan(THandle hCuWext, OS_802_11_SSID* ssid, U8 scanType) 251 { 252 TCuWext* pCuWext = (TCuWext*)hCuWext; 253 struct iw_scan_req tReq; 254 S32 res; 255 256 if (ssid->SsidLength > IW_ESSID_MAX_SIZE) 257 { 258 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Start_Scan - too long SSID (%lu)\n",ssid->SsidLength); 259 return OSAL_ERROR; 260 } 261 262 if (ssid->Ssid[0] && ssid->SsidLength) 263 { 264 os_memset(&tReq, 0, sizeof(tReq)); 265 tReq.essid_len = ssid->SsidLength; 266 /* 267 * tReq.bssid.sa_family = ARPHRD_ETHER; 268 * os_memset(tReq.bssid.sa_data, 0xff, ETH_ALEN); 269 */ 270 os_memcpy(tReq.essid, ssid->Ssid, ssid->SsidLength); 271 pCuWext->scan_req = &tReq; 272 pCuWext->req_data.data.flags = IW_SCAN_THIS_ESSID; 273 } 274 else 275 { 276 pCuWext->req_data.data.flags = 0; 277 } 278 279 tReq.scan_type = scanType; 280 pCuWext->req_data.data.pointer = &tReq; 281 pCuWext->req_data.data.length = sizeof(struct iw_scan_req); 282 283 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWSCAN, &pCuWext->req_data, sizeof(struct iw_point)); 284 if(res != OK) 285 return res; 286 287 return OK; 288 } 289 290 S32 CuOs_GetBssidList(THandle hCuWext, OS_802_11_BSSID_LIST_EX *bssidList) 291 { 292 TCuWext* pCuWext = (TCuWext*)hCuWext; 293 S32 res, NumberOfItems; 294 295 /* allocate the scan result buffer */ 296 U8* buffer = os_MemoryCAlloc(IW_SCAN_MAX_DATA, sizeof(U8)); 297 if(buffer == NULL) 298 { 299 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Get_BssidList - cant allocate scan result buffer\n"); 300 return EOALERR_CU_WEXT_ERROR_CANT_ALLOCATE; 301 } 302 303 NumberOfItems = 0; 304 pCuWext->req_data.data.pointer = buffer; 305 pCuWext->req_data.data.flags = 0; 306 do 307 { 308 pCuWext->req_data.data.length = IW_SCAN_MAX_DATA; 309 310 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWSCAN, &pCuWext->req_data, sizeof(struct iw_point)); 311 if(res != OK) 312 { 313 os_MemoryFree(buffer); 314 return res; 315 } 316 317 /* parse the scan results */ 318 if(pCuWext->req_data.data.length) 319 { 320 struct iw_event iwe; 321 struct stream_descr stream; 322 S32 ret; 323 324 /* init the event stream */ 325 os_memset((char *)&stream, '\0', sizeof(struct stream_descr)); 326 stream.current = (char *)buffer; 327 stream.end = (char *)(buffer + pCuWext->req_data.data.length); 328 329 do 330 { 331 /* Extract an event and print it */ 332 ret = ParsEvent_GetEvent(&stream, &iwe); 333 if(ret > 0) 334 NumberOfItems += CuWext_FillBssidList(&iwe, bssidList->Bssid, NumberOfItems); 335 } 336 while(ret > 0); 337 } 338 339 } while(pCuWext->req_data.data.flags); 340 341 bssidList->NumberOfItems = NumberOfItems; 342 343 /* free the scan result buffer */ 344 os_MemoryFree(buffer); 345 346 return OK; 347 } 348 349 350 S32 CuOs_Set_BSSID(THandle hCuWext, TMacAddr bssid) 351 { 352 TCuWext* pCuWext = (TCuWext*)hCuWext; 353 S32 res; 354 355 os_memcpy(pCuWext->req_data.ap_addr.sa_data, bssid, MAC_ADDR_LEN); 356 357 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWAP, &pCuWext->req_data, sizeof(struct sockaddr)); 358 359 if(res != OK) 360 return res; 361 362 return OK; 363 } 364 365 S32 CuOs_Set_ESSID(THandle hCuWext, OS_802_11_SSID* ssid) 366 { 367 TCuWext* pCuWext = (TCuWext*)hCuWext; 368 S32 res; 369 370 pCuWext->req_data.essid.pointer = (PVOID)ssid->Ssid; 371 pCuWext->req_data.essid.length = ssid->SsidLength; 372 if(ssid->SsidLength) 373 pCuWext->req_data.essid.flags = 1; 374 else 375 pCuWext->req_data.essid.flags = 0; 376 pCuWext->req_data.essid.flags |= SET_SSID_WITHOUT_SUPPL; 377 378 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWESSID, &pCuWext->req_data, sizeof(struct sockaddr)); 379 380 if(res != OK) 381 return res; 382 383 return OK; 384 } 385 386 S32 CuOs_GetTxPowerLevel(THandle hCuWext, S32* pTxPowerLevel) 387 { 388 TCuWext* pCuWext = (TCuWext*)hCuWext; 389 S32 res; 390 391 os_memset(&pCuWext->req_data.txpower, 0, sizeof(struct iw_param)); 392 393 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWTXPOW, &pCuWext->req_data, sizeof(struct iw_param)); 394 395 if(res != OK) 396 return res; 397 398 *pTxPowerLevel = pCuWext->req_data.txpower.value; 399 400 return OK; 401 } 402 403 S32 CuOs_SetTxPowerLevel(THandle hCuWext, S32 txPowerLevel) 404 { 405 TCuWext* pCuWext = (TCuWext*)hCuWext; 406 S32 res; 407 408 os_memset(&pCuWext->req_data.txpower, 0, sizeof(struct iw_param)); 409 410 pCuWext->req_data.txpower.value = txPowerLevel; 411 412 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWTXPOW, &pCuWext->req_data, sizeof(struct iw_param)); 413 414 if(res != OK) 415 return res; 416 417 return OK; 418 } 419 420 S32 CuOs_GetRtsTh(THandle hCuWext, PS32 pRtsTh) 421 { 422 TCuWext* pCuWext = (TCuWext*)hCuWext; 423 S32 res; 424 425 os_memset(&pCuWext->req_data.rts, 0, sizeof(struct iw_param)); 426 427 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWRTS, &pCuWext->req_data, sizeof(struct iw_param)); 428 if(res != OK) 429 return res; 430 431 *pRtsTh = pCuWext->req_data.rts.value; 432 433 return OK; 434 } 435 436 437 S32 CuOs_SetRtsTh(THandle hCuWext, S32 RtsTh) 438 { 439 TCuWext* pCuWext = (TCuWext*)hCuWext; 440 S32 res; 441 442 os_memset(&pCuWext->req_data.rts, 0, sizeof(struct iw_param)); 443 pCuWext->req_data.rts.value = RtsTh; 444 445 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWRTS, &pCuWext->req_data, sizeof(struct iw_param)); 446 if(res != OK) 447 return res; 448 449 450 451 return OK; 452 } 453 454 S32 CuOs_GetFragTh(THandle hCuWext, PS32 pFragTh) 455 { 456 TCuWext* pCuWext = (TCuWext*)hCuWext; 457 S32 res; 458 459 os_memset(&pCuWext->req_data.frag, 0, sizeof(struct iw_param)); 460 461 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWFRAG, &pCuWext->req_data, sizeof(struct iw_param)); 462 if(res != OK) 463 return res; 464 465 *pFragTh = pCuWext->req_data.frag.value; 466 467 return OK; 468 } 469 470 S32 CuOs_SetFragTh(THandle hCuWext, S32 FragTh) 471 { 472 TCuWext* pCuWext = (TCuWext*)hCuWext; 473 S32 res; 474 475 os_memset(&pCuWext->req_data.frag, 0, sizeof(struct iw_param)); 476 pCuWext->req_data.frag.value = FragTh; 477 478 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWFRAG, &pCuWext->req_data, sizeof(struct iw_param)); 479 if(res != OK) 480 return res; 481 482 return OK; 483 } 484 /*stab function (should be filled later on for Linux to get ThreadID of the WLAN driver*/ 485 S32 CuOs_GetDriverThreadId(THandle hCuWext, U32* threadid) 486 { 487 return OK; 488 } 489