Home | History | Annotate | Download | only in src
      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