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 /*******************/
CuWext_FillBssidList(struct iw_event * iwe,OS_802_11_BSSID_EX * bssidList,S32 index)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
CuOs_Create(THandle hIpcSta)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
CuOs_Destroy(THandle hCuWext)171 VOID CuOs_Destroy(THandle hCuWext)
172 {
173 TCuWext* pCuWext = (TCuWext*)hCuWext;
174
175 os_MemoryFree(pCuWext);
176 }
177
CuOs_Get_SSID(THandle hCuWext,OS_802_11_SSID * ssid)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
CuOs_Get_BSSID(THandle hCuWext,TMacAddr bssid)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
CuOs_GetCurrentChannel(THandle hCuWext,U32 * channel)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.*/
CuOs_GetCurrentStats(THandle hCuWext,S32 * rssi)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
CuOs_Start_Scan(THandle hCuWext,OS_802_11_SSID * ssid,U8 scanType)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
CuOs_GetBssidList(THandle hCuWext,OS_802_11_BSSID_LIST_EX * bssidList)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
CuOs_Set_BSSID(THandle hCuWext,TMacAddr bssid)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
CuOs_Set_ESSID(THandle hCuWext,OS_802_11_SSID * ssid)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
CuOs_GetTxPowerLevel(THandle hCuWext,S32 * pTxPowerLevel)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
CuOs_SetTxPowerLevel(THandle hCuWext,S32 txPowerLevel)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
CuOs_GetRtsTh(THandle hCuWext,PS32 pRtsTh)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
CuOs_SetRtsTh(THandle hCuWext,S32 RtsTh)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
CuOs_GetFragTh(THandle hCuWext,PS32 pFragTh)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
CuOs_SetFragTh(THandle hCuWext,S32 FragTh)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*/
CuOs_GetDriverThreadId(THandle hCuWext,U32 * threadid)485 S32 CuOs_GetDriverThreadId(THandle hCuWext, U32* threadid)
486 {
487 return OK;
488 }
489