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
CuOs_Start_Scan(THandle hCuWext,OS_802_11_SSID * ssid)231 S32 CuOs_Start_Scan(THandle hCuWext, OS_802_11_SSID* ssid)
232 {
233 TCuWext* pCuWext = (TCuWext*)hCuWext;
234 struct iw_scan_req tReq;
235 S32 res;
236
237 if (ssid->SsidLength > IW_ESSID_MAX_SIZE)
238 {
239 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Start_Scan - too long SSID (%lu)\n",ssid->SsidLength);
240 return OSAL_ERROR;
241 }
242
243 if (ssid->Ssid[0] && ssid->SsidLength)
244 {
245 os_memset(&tReq, 0, sizeof(tReq));
246 tReq.essid_len = ssid->SsidLength;
247 /*
248 * tReq.bssid.sa_family = ARPHRD_ETHER;
249 * os_memset(tReq.bssid.sa_data, 0xff, ETH_ALEN);
250 */
251 os_memcpy(tReq.essid, ssid->Ssid, ssid->SsidLength);
252 pCuWext->scan_req = &tReq;
253 pCuWext->req_data.data.flags = IW_SCAN_THIS_ESSID;
254 }
255 else
256 {
257 pCuWext->req_data.data.flags = 0;
258 }
259
260 pCuWext->req_data.data.pointer = &tReq;
261 pCuWext->req_data.data.length = sizeof(struct iw_scan_req);
262
263 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWSCAN, &pCuWext->req_data, sizeof(struct iw_point));
264 if(res != OK)
265 return res;
266
267 return OK;
268 }
269
CuOs_GetBssidList(THandle hCuWext,OS_802_11_BSSID_LIST_EX * bssidList)270 S32 CuOs_GetBssidList(THandle hCuWext, OS_802_11_BSSID_LIST_EX *bssidList)
271 {
272 TCuWext* pCuWext = (TCuWext*)hCuWext;
273 S32 res, NumberOfItems;
274
275 /* allocate the scan result buffer */
276 U8* buffer = os_MemoryCAlloc(IW_SCAN_MAX_DATA, sizeof(U8));
277 if(buffer == NULL)
278 {
279 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - CuOs_Get_BssidList - cant allocate scan result buffer\n");
280 return EOALERR_CU_WEXT_ERROR_CANT_ALLOCATE;
281 }
282
283 NumberOfItems = 0;
284 pCuWext->req_data.data.pointer = buffer;
285 pCuWext->req_data.data.flags = 0;
286 do
287 {
288 pCuWext->req_data.data.length = IW_SCAN_MAX_DATA;
289
290 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWSCAN, &pCuWext->req_data, sizeof(struct iw_point));
291 if(res != OK)
292 {
293 os_MemoryFree(buffer);
294 return res;
295 }
296
297 /* parse the scan results */
298 if(pCuWext->req_data.data.length)
299 {
300 struct iw_event iwe;
301 struct stream_descr stream;
302 S32 ret;
303
304 /* init the event stream */
305 os_memset((char *)&stream, '\0', sizeof(struct stream_descr));
306 stream.current = (char *)buffer;
307 stream.end = (char *)(buffer + pCuWext->req_data.data.length);
308
309 do
310 {
311 /* Extract an event and print it */
312 ret = ParsEvent_GetEvent(&stream, &iwe);
313 if(ret > 0)
314 NumberOfItems += CuWext_FillBssidList(&iwe, bssidList->Bssid, NumberOfItems);
315 }
316 while(ret > 0);
317 }
318
319 } while(pCuWext->req_data.data.flags);
320
321 bssidList->NumberOfItems = NumberOfItems;
322
323 /* free the scan result buffer */
324 os_MemoryFree(buffer);
325
326 return OK;
327 }
328
329
CuOs_Set_BSSID(THandle hCuWext,TMacAddr bssid)330 S32 CuOs_Set_BSSID(THandle hCuWext, TMacAddr bssid)
331 {
332 TCuWext* pCuWext = (TCuWext*)hCuWext;
333 S32 res;
334
335 os_memcpy(pCuWext->req_data.ap_addr.sa_data, bssid, MAC_ADDR_LEN);
336
337 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWAP, &pCuWext->req_data, sizeof(struct sockaddr));
338
339 if(res != OK)
340 return res;
341
342 return OK;
343 }
344
CuOs_Set_ESSID(THandle hCuWext,OS_802_11_SSID * ssid)345 S32 CuOs_Set_ESSID(THandle hCuWext, OS_802_11_SSID* ssid)
346 {
347 TCuWext* pCuWext = (TCuWext*)hCuWext;
348 S32 res;
349
350 pCuWext->req_data.essid.pointer = (PVOID)ssid->Ssid;
351 pCuWext->req_data.essid.length = ssid->SsidLength;
352 if(ssid->SsidLength)
353 pCuWext->req_data.essid.flags = 1;
354 else
355 pCuWext->req_data.essid.flags = 0;
356 pCuWext->req_data.essid.flags |= SET_SSID_WITHOUT_SUPPL;
357
358 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWESSID, &pCuWext->req_data, sizeof(struct sockaddr));
359
360 if(res != OK)
361 return res;
362
363 return OK;
364 }
365
CuOs_GetTxPowerLevel(THandle hCuWext,S32 * pTxPowerLevel)366 S32 CuOs_GetTxPowerLevel(THandle hCuWext, S32* pTxPowerLevel)
367 {
368 TCuWext* pCuWext = (TCuWext*)hCuWext;
369 S32 res;
370
371 os_memset(&pCuWext->req_data.txpower, 0, sizeof(struct iw_param));
372
373 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWTXPOW, &pCuWext->req_data, sizeof(struct iw_param));
374
375 if(res != OK)
376 return res;
377
378 *pTxPowerLevel = pCuWext->req_data.txpower.value;
379
380 return OK;
381 }
382
CuOs_SetTxPowerLevel(THandle hCuWext,S32 txPowerLevel)383 S32 CuOs_SetTxPowerLevel(THandle hCuWext, S32 txPowerLevel)
384 {
385 TCuWext* pCuWext = (TCuWext*)hCuWext;
386 S32 res;
387
388 os_memset(&pCuWext->req_data.txpower, 0, sizeof(struct iw_param));
389
390 pCuWext->req_data.txpower.value = txPowerLevel;
391
392 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWTXPOW, &pCuWext->req_data, sizeof(struct iw_param));
393
394 if(res != OK)
395 return res;
396
397 return OK;
398 }
399
CuOs_GetRtsTh(THandle hCuWext,PS32 pRtsTh)400 S32 CuOs_GetRtsTh(THandle hCuWext, PS32 pRtsTh)
401 {
402 TCuWext* pCuWext = (TCuWext*)hCuWext;
403 S32 res;
404
405 os_memset(&pCuWext->req_data.rts, 0, sizeof(struct iw_param));
406
407 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWRTS, &pCuWext->req_data, sizeof(struct iw_param));
408 if(res != OK)
409 return res;
410
411 *pRtsTh = pCuWext->req_data.rts.value;
412
413 return OK;
414 }
415
416
CuOs_SetRtsTh(THandle hCuWext,S32 RtsTh)417 S32 CuOs_SetRtsTh(THandle hCuWext, S32 RtsTh)
418 {
419 TCuWext* pCuWext = (TCuWext*)hCuWext;
420 S32 res;
421
422 os_memset(&pCuWext->req_data.rts, 0, sizeof(struct iw_param));
423 pCuWext->req_data.rts.value = RtsTh;
424
425 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWRTS, &pCuWext->req_data, sizeof(struct iw_param));
426 if(res != OK)
427 return res;
428
429
430
431 return OK;
432 }
433
CuOs_GetFragTh(THandle hCuWext,PS32 pFragTh)434 S32 CuOs_GetFragTh(THandle hCuWext, PS32 pFragTh)
435 {
436 TCuWext* pCuWext = (TCuWext*)hCuWext;
437 S32 res;
438
439 os_memset(&pCuWext->req_data.frag, 0, sizeof(struct iw_param));
440
441 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCGIWFRAG, &pCuWext->req_data, sizeof(struct iw_param));
442 if(res != OK)
443 return res;
444
445 *pFragTh = pCuWext->req_data.frag.value;
446
447 return OK;
448 }
449
CuOs_SetFragTh(THandle hCuWext,S32 FragTh)450 S32 CuOs_SetFragTh(THandle hCuWext, S32 FragTh)
451 {
452 TCuWext* pCuWext = (TCuWext*)hCuWext;
453 S32 res;
454
455 os_memset(&pCuWext->req_data.frag, 0, sizeof(struct iw_param));
456 pCuWext->req_data.frag.value = FragTh;
457
458 res = IPC_STA_Wext_Send(pCuWext->hIpcSta, SIOCSIWFRAG, &pCuWext->req_data, sizeof(struct iw_param));
459 if(res != OK)
460 return res;
461
462 return OK;
463 }
464 /*stab function (should be filled later on for Linux to get ThreadID of the WLAN driver*/
CuOs_GetDriverThreadId(THandle hCuWext,U32 * threadid)465 S32 CuOs_GetDriverThreadId(THandle hCuWext, U32* threadid)
466 {
467 return OK;
468 }
469