• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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