blob: b9ac23dd536d10d5c22183335a9fd263a7d2c682 [file] [log] [blame]
/*
* WPA Supplicant - driver interaction with TI station
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
*/
/* Copyright © Texas Instruments Incorporated (Oct 2005)
* THIS CODE/PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDED BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* This program has been modified from its original operation by Texas
* Instruments Incorporated. These changes are covered under version 2
* of the GNU General Public License, dated June 1991.
*
* Copyright © Google Inc (Feb 2008)
*/
/*-------------------------------------------------------------------*/
#include "includes.h"
#include <sys/ioctl.h>
#include <net/route.h>
#include <net/if.h>
#include <fcntl.h>
#include <netpacket/packet.h>
#include <stddef.h>
#include "common.h"
#include "driver.h"
#include "eloop.h"
#include "wpa.h"
#include "wpa_supplicant.h"
#include "config.h"
#include "wpa_supplicant_i.h"
#include "wpa_i.h"
#include "l2_packet.h"
#include "wpa_ctrl.h"
/*----- STA_DK files -----*/
#include "wspVer.h"
#include "driver_ti.h"
#include "scanmerge.h"
#include "scanMngrTypes.h"
#ifdef ANDROID
#include <cutils/properties.h>
#endif
/*-------------------------------------------------------------------*/
#define TI_DRIVER_MSG_PORT 9000
#define RX_SELF_FILTER 0
#define RX_BROADCAST_FILTER 1
#define RX_IPV4_MULTICAST_FILTER 2
#define RX_IPV6_MULTICAST_FILTER 3
#define TI2WPA_STATUS(s) (((s) != OK) ? -1 : 0)
#define TI_CHECK_DRIVER(f,r) \
if( !(f) ) { \
wpa_printf(MSG_ERROR,"TI: Driver not initialized yet...aborting..."); \
return( r ); \
}
/*-------------------------------------------------------------------*/
/* Lock file pointer - used to access pid-lock-file to prevent two instances of wpa_supplicant */
#ifdef CONFIG_TI_LOCKFILE
static int lfp;
#endif
/*-------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
Routine Name: check_and_get_build_channels
Routine Description: get number of allowed channels according to a build var.
Arguments: None
Return Value: Number of channels
-----------------------------------------------------------------------------*/
static int check_and_get_build_channels( void )
{
#ifdef ANDROID
char prop_status[PROPERTY_VALUE_MAX];
char *prop_name = "ro.wifi.channels";
int i, default_channels = NUMBER_SCAN_CHANNELS_FCC;
if( property_get(prop_name, prop_status, NULL) ) {
i = atoi(prop_status);
if( i != 0 )
default_channels = i;
}
return( default_channels );
#else
return( NUMBER_SCAN_CHANNELS_FCC );
#endif
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_event_receive
Routine Description: driver events callback, called from driver IPC
Arguments:
priv - pointer to private data structure
pData - pointer to event information
Return Value:
-----------------------------------------------------------------------------*/
void wpa_driver_tista_event_receive( IPC_EV_DATA *pData )
{
struct wpa_driver_ti_data *mySuppl;
struct sockaddr_in echoserver;
int res, msg_size;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_event_receive called: %d",
pData->uBufferSize);
mySuppl = pData->EvParams.hUserParam;
msg_size = (int)(pData->uBufferSize + offsetof(IPC_EV_DATA, uBuffer));
os_memset( &echoserver, 0, sizeof(echoserver) ); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = inet_addr("127.0.0.1"); /* IP address */
echoserver.sin_port = htons(TI_DRIVER_MSG_PORT); /* server port */
res = sendto(mySuppl->driverEventsSocket, pData, msg_size, 0, (struct sockaddr *)&echoserver, sizeof(echoserver));
echoserver.sin_port = htons(TI_DRIVER_MSG_PORT + 1);
res = sendto(mySuppl->driverEventsSocket, pData, msg_size, 0, (struct sockaddr *)&echoserver, sizeof(echoserver));
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_register_events
Routine Description: register to driver events
Arguments:
ctx - pointer to private data structure
Return Value: None
-----------------------------------------------------------------------------*/
void wpa_driver_tista_register_events( void *ctx )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)ctx;
IPC_EVENT_PARAMS pEvent;
int i;
os_memset( myDrv->hEvents, 0, sizeof(ULONG) * IPC_EVENT_MAX );
for(i=IPC_EVENT_ASSOCIATED;( i < IPC_EVENT_MAX );i++) {
/* Register to receive driver events */
pEvent.uEventType = i;
pEvent.uDeliveryType = DELIVERY_PUSH;
pEvent.hUserParam = (TI_HANDLE)myDrv;
pEvent.pfEventCallback = (TI_EVENT_CALLBACK)wpa_driver_tista_event_receive;
TI_RegisterEvent( myDrv->hDriver, &pEvent );
myDrv->hEvents[i] = pEvent.uEventID;
}
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_unregister_events
Routine Description: unregister driver events
Arguments:
ctx - pointer to private data structure
Return Value: None
-----------------------------------------------------------------------------*/
void wpa_driver_tista_unregister_events( void *ctx )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)ctx;
IPC_EVENT_PARAMS pEvent;
int idx;
for(idx=0;( idx < IPC_EVENT_MAX );idx++) {
if( myDrv->hEvents[idx] ) {
pEvent.uEventType = idx;
pEvent.uEventID = myDrv->hEvents[idx];
TI_UnRegisterEvent( myDrv->hDriver, &pEvent );
}
}
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_get_bssid
Routine Description: get current BSSID from driver
Arguments:
priv - pointer to private data structure
bssid - pointer to hold bssid
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_get_bssid( void *priv, u8 *bssid )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
OS_802_11_MAC_ADDRESS tiAPMacAddr;
TI_STATUS retValue;
wpa_printf(MSG_DEBUG, "wpa_driver_tista_get_bssid called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
/* Get MAC address of current AP */
if( TI_GetBSSID( myDrv->hDriver, &tiAPMacAddr ) != TI_RESULT_OK )
return( -1 );
/* Copy BSSID into caller pointer provided in routine parameters */
os_memcpy( (void *)bssid, (void *)&tiAPMacAddr, MAC_ADDR_LEN );
wpa_hexdump(MSG_DEBUG, "get_bssid:", bssid, MAC_ADDR_LEN);
return( 0 );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_get_ssid
Routine Description: get current SSID
Arguments:
priv - pointer to private data structure
ssid - pointer to hold current bssid
Return Value: Length of SSID string
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_get_ssid( void *priv, u8 *ssid )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
OS_802_11_SSID myssid;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_get_ssid called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
/* Get current SSID from driver */
if( TI_GetCurrentSSID(myDrv->hDriver, &myssid) != TI_RESULT_OK )
return( -1 );
/* Copy to user supplied pointer */
os_memcpy( (void *)ssid, (void *)&myssid.Ssid, myssid.SsidLength );
/* Return length of SSID */
return( myssid.SsidLength );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_ssid
Routine Description: sets current SSID (Associates)
Arguments:
priv - pointer to private data structure
ssid - pointer to ssid
ssid_len - length of ssid
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_ssid( void *priv, const u8 *ssid, size_t ssid_len )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
char ssidBuf[MAX_SSID_LEN];
int ret;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_ssid called: %s", ssid);
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
/* Copy user supplied SSID into local buffer */
os_memset( ssidBuf, 0, MAX_SSID_LEN );
os_memcpy( ssidBuf, ssid, ssid_len );
/* Set local SSID buffer to driver - triggering connection process in driver */
wpa_printf(MSG_DEBUG,"Associate: SSID = %s", ssidBuf); /* Dm: */
#ifdef STA_DK_VER_5_0_0_94
ret = (int)TI_SetSSID( myDrv->hDriver, (char *)ssidBuf );
#else
ret = (int)TI_SetSSID( myDrv->hDriver, (u8 *)ssidBuf );
#endif
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_wpa
Routine Description: enable/disable WPA support in driver - not implemented since not supported in driver. also obselete for wpa-suppl core
Arguments:
priv - pointer to private data structure
enabled - enable/disable flag
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_wpa(void *priv, int enabled)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_wpa called: %d",enabled);
return( 0 );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_proto
Routine Description: set authentication protocol (WPA/WPA2(RSN))
Arguments:
priv - pointer to private data structure
proto - authentication suite
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_proto( void *priv, int proto )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_proto called: %d", proto);
myDrv->proto = proto;
return( 0 );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_wpa_options
Routine Description: set wpa_options
Arguments:
priv - pointer to private data structure
wpa_options - WPA options (0 - disable, 3 - enable)
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_wpa_options( void *priv, int key_mgmt_suite )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
UINT32 wpa_opt = WPA_OPTIONS_DISABLE;
int ret;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_wpa_options called: %d", key_mgmt_suite);
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
myDrv->key_mgmt = key_mgmt_suite;
switch( key_mgmt_suite ) {
case KEY_MGMT_802_1X: /* Dm: EAP */
wpa_opt = WPA_OPTIONS_ENABLE; /* wpa_auth = 1; */
break;
case KEY_MGMT_PSK: /* Dm: PSK */
wpa_opt = WPA_OPTIONS_ENABLE; /* wpa_auth = 2; */
break;
case KEY_MGMT_802_1X_NO_WPA: /* Dm: ??? */
break;
case KEY_MGMT_WPA_NONE: /* Dm: ??? */
break;
case KEY_MGMT_NONE:
default:
wpa_opt = WPA_OPTIONS_DISABLE; /* wpa_auth = 255; */
break;
}
/* Set WPA Options */
ret = TI_SetWpaOptions( myDrv->hDriver, wpa_opt );
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_encryption
Routine Description: set authentication protocol (WPA/WPA2(RSN))
Arguments:
priv - pointer to private data structure
proto - authentication suite
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_encryption( void *priv, int encryption )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
int ret = -1;
OS_802_11_ENCRYPTION_TYPES wpa_cipher = OS_ENCRYPTION_TYPE_NONE;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_encryption called: %d",encryption);
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
myDrv->encryption = encryption;
switch( encryption ) {
case CIPHER_WEP40:
case CIPHER_WEP104:
wpa_printf(MSG_DEBUG, "encryption: OS_ENCRYPTION_TYPE_WEP");
wpa_cipher = OS_ENCRYPTION_TYPE_WEP;
break;
case CIPHER_TKIP:
wpa_printf(MSG_DEBUG, "encryption: OS_ENCRYPTION_TYPE_TKIP");
wpa_cipher = OS_ENCRYPTION_TYPE_TKIP;
break;
case CIPHER_CCMP:
wpa_printf(MSG_DEBUG, "encryption: OS_ENCRYPTION_TYPE_AES");
wpa_cipher = OS_ENCRYPTION_TYPE_AES;
break;
case CIPHER_NONE:
default:
wpa_printf(MSG_DEBUG, "encryption: OS_ENCRYPTION_TYPE_NONE");
wpa_cipher = OS_ENCRYPTION_TYPE_NONE;
break;
}
ret = TI_SetEncryptionType( myDrv->hDriver, wpa_cipher );
return( TI2WPA_STATUS(ret) );
}
/*---------------------------------------------------------------------------*/
void wpa_driver_tista_print_auth_mode( OS_802_11_AUTHENTICATION_MODE myAuth )
{
char *mode_name = NULL;
switch( myAuth ) {
case os802_11AuthModeOpen:
mode_name = "os802_11AuthModeOpen";
break;
case os802_11AuthModeShared:
mode_name = "os802_11AuthModeShared";
break;
case os802_11AuthModeAutoSwitch:
mode_name = "os802_11AuthModeAutoSwitch";
break;
case os802_11AuthModeWPA:
mode_name = "os802_11AuthModeWPA";
break;
case os802_11AuthModeWPAPSK:
mode_name = "os802_11AuthModeWPAPSK";
break;
case os802_11AuthModeWPANone:
mode_name = "os802_11AuthModeWPANone";
break;
case os802_11AuthModeWPA2:
mode_name = "os802_11AuthModeWPA2";
break;
case os802_11AuthModeWPA2PSK:
mode_name = "os802_11AuthModeWPA2PSK";
break;
case os802_11AuthModeMax:
default:
mode_name = "Unknown";
break;
}
wpa_printf(MSG_DEBUG, "Selected AuthMode: %s", mode_name);
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_auth_mode
Routine Description:
Arguments:
priv - pointer to private data structure
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_auth_mode( void *priv )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
OS_802_11_AUTHENTICATION_MODE myAuth = os802_11AuthModeAutoSwitch;
int ret;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_auth_mode called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
wpa_driver_tista_set_proto( priv, ((struct wpa_supplicant *)myDrv->hWpaSupplicant)->wpa->proto );
wpa_printf(MSG_DEBUG, "proto: %d", myDrv->proto); /* should be set BEFORE */
wpa_printf(MSG_DEBUG, "auth_alg: %d",myDrv->auth_alg);
if( (myDrv->auth_alg == AUTH_ALG_OPEN_SYSTEM) ||
(myDrv->auth_alg == AUTH_ALG_LEAP) ) {
switch( myDrv->key_mgmt ) {
case KEY_MGMT_802_1X:
if( myDrv->proto & WPA_PROTO_WPA ) {
myAuth = os802_11AuthModeWPA;
}
else if( myDrv->proto & WPA_PROTO_RSN ) {
myAuth = os802_11AuthModeWPA2;
}
break;
case KEY_MGMT_PSK:
if( myDrv->proto & WPA_PROTO_WPA ) {
myAuth = os802_11AuthModeWPAPSK;
}
else if( myDrv->proto & WPA_PROTO_RSN ) {
myAuth = os802_11AuthModeWPA2PSK;
}
break;
case KEY_MGMT_802_1X_NO_WPA:
case KEY_MGMT_WPA_NONE:
myAuth = os802_11AuthModeWPANone;
break;
case KEY_MGMT_NONE:
default:
myAuth = os802_11AuthModeOpen;
break;
}
}
else if( myDrv->auth_alg == AUTH_ALG_SHARED_KEY ) {
myAuth = os802_11AuthModeShared;
}
if( myDrv->auth_alg == AUTH_ALG_LEAP ) {
TI_SetEAPType( myDrv->hDriver, OS_EAP_TYPE_LEAP );
TI_SetEAPTypeDriver( myDrv->hDriver, OS_EAP_TYPE_LEAP );
}
wpa_driver_tista_print_auth_mode( myAuth );
ret = TI_SetAuthenticationMode( myDrv->hDriver, myAuth );
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_del_key
Routine Description: remove key from driver
Arguments:
priv - pointer to private data structure
key_idx - key index
addr - key address (unicast/broadcast)
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_del_key(void *priv, int key_idx,
const unsigned char *addr)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
OS_802_11_REMOVE_KEY myKey;
int ret;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_del_key called");
wpa_printf(MSG_DEBUG,"key_idx = %d, addr = " TIMACSTR, key_idx, MAC2STR(addr));
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
/* copy parameters (MAC of key to remove, etc) to local structure */
myKey.Length = sizeof(OS_802_11_REMOVE_KEY);
os_memcpy(&myKey.BSSID,addr,MAC_ADDR_LEN);
myKey.KeyIndex = key_idx;
/* Call Utility adapter to remove the key */
ret = TI_RemoveKey( myDrv->hDriver, &myKey );
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_key
Routine Description: set key in driver
Arguments:
priv - pointer to private data structure
alg - type of key
addr - key address (unicast/broadcast)
key_idx - key index
set_tx - use key for immidiate tx
seq - sequence counter (for replay detection)
seq_len - sequence counter buffer len
key - key content
key_len - length of key (32 for TKIP, 16 for AES)
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_key(void *priv, wpa_alg alg,
const unsigned char *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
OS_802_11_KEY myKey;
OS_802_11_WEP myWepKey;
UINT8 temp[TKIP_KEY_LENGTH];
int ret = -1;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_key called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
wpa_printf(MSG_DEBUG, "add_key (addr): " MACSTR, MAC2STR(addr));
wpa_printf(MSG_DEBUG, "add_key (key_idx): %d", key_idx);
wpa_printf(MSG_DEBUG, "add_key (alg): %d", alg);
wpa_printf(MSG_DEBUG, "add_key (set_tx): %d", set_tx);
wpa_hexdump(MSG_DEBUG, "add_key (seq):", seq, seq_len);
wpa_hexdump(MSG_DEBUG, "add_key (key):", key, key_len);
switch( key_len ) {
case TKIP_KEY_LENGTH: /* 32 */
case AES_KEY_LENGTH: /* 16 */
/* Set key index */
myKey.KeyIndex = key_idx;
/* Set key length and content */
myKey.KeyLength = key_len;
/* Set structure size */
myKey.Length = sizeof(OS_802_11_KEY);
/* set key MAC address - FF:FF:FF:FF:FF:FF for broadcast, other for unicast */
os_memcpy( &myKey.BSSID, addr, MAC_ADDR_LEN );
if( seq_len ) {
/* Set key RSC */
os_memcpy( &myKey.KeyRSC, seq, seq_len );
myKey.KeyIndex |= TIWLAN_KEY_FLAGS_SET_KEY_RSC;
}
if( set_tx ) {
myKey.KeyIndex |= TIWLAN_KEY_FLAGS_TRANSMIT;
}
if( myKey.BSSID[0] != 0xFF ) {
myKey.KeyIndex |= TIWLAN_KEY_FLAGS_PAIRWISE;
}
os_memcpy( &temp, key, AES_KEY_LENGTH );
if( key_len == TKIP_KEY_LENGTH ) {
/* need to switch RX and TX MIC set with key (to match driver API) */
os_memcpy( (UINT8*)(((UINT8*)&temp)+24), (UINT8*)(((UINT8*)key)+16), 8 );
os_memcpy( (UINT8*)(((UINT8*)&temp)+16), (UINT8*)(((UINT8*)key)+24), 8 );
}
os_memcpy( &myKey.KeyMaterial, &temp, key_len );
ret = TI_AddKey( myDrv->hDriver, &myKey );
break;
case WEP_KEY_LENGTH_40: /* 5 */
case WEP_KEY_LENGTH_104: /* 13 */
if( key_len != 0 ) {
/* Set key index */
myWepKey.KeyIndex = key_idx;
/* Set key length and content */
myWepKey.KeyLength = key_len;
/* Set structure size */
myWepKey.Length = sizeof(OS_802_11_WEP);
if( set_tx ) {
myWepKey.KeyIndex |= TIWLAN_KEY_FLAGS_TRANSMIT;
wpa_printf(MSG_DEBUG, "setting this key to be the index: 0x%x", myWepKey.KeyIndex);
}
os_memcpy( &myWepKey.KeyMaterial, key, key_len );
wpa_printf(MSG_DEBUG, "Adding WEP key index: 0x%x", key_idx);
ret = TI_AddWEPKey( myDrv->hDriver, &myWepKey );
}
else {
wpa_printf(MSG_DEBUG, "Removing WEP key index: 0x%x", key_idx);
ret = TI_RemoveWEPKey( myDrv->hDriver, key_idx );
}
break;
default:
wpa_printf(MSG_ERROR,"Set_key: Wrong Key\n");
break;
}
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_countermeasures
Routine Description: start/stop countermeasures (drop packets due to replay attack detection)
Arguments:
priv - pointer to private data structure
enabled - enable/disable flag
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_countermeasures(void *priv, int enabled)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_countermeasures called: %d", enabled);
return( 0 );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_drop_unencrypted
Routine Description: enable/disable EAPOL-only tx by driver
Arguments:
priv - pointer to private data structure
enabled - enable/disable flag
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_drop_unencrypted(void *priv, int enabled)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
wpa_printf(MSG_DEBUG,"TI: wpa_driver_tista_set_drop_unencrypted called: %d - not implemented", enabled);
return( 0 );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_deauthenticate
Routine Description: send deauthentication packet
Arguments:
priv - pointer to private data structure
addr - address to send deauth packet to
reason_code - reason code supplied in deauth packet
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_deauthenticate(void *priv, const UINT8 *addr, int reason_code)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
int ret;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_deauthenticate called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
/* Block any pending disassoc event until successfully connected */
if( myDrv->block_disassoc_events == NO_BLOCK )
myDrv->block_disassoc_events = NO_BLOCK_DISASSOC_IN_PROGRESS;
ret = TI_Disassociate( myDrv->hDriver );
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_disassociate
Routine Description: disassociate from AP
Arguments:
priv - pointer to private data structure
addr - address to send deauth packet to
reason_code - reason code supplied in deauth packet
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_disassociate(void *priv, const UINT8 *addr, int reason_code)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
int ret;
wpa_printf(MSG_DEBUG,"TI: wpa_driver_tista_disassociate called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
/* Block any pending disassoc event until successfully connected */
if( myDrv->block_disassoc_events == NO_BLOCK )
myDrv->block_disassoc_events = NO_BLOCK_DISASSOC_IN_PROGRESS;
ret = TI_Disassociate( myDrv->hDriver );
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_associate
Routine Description: associate with AP
Arguments:
priv - pointer to private data structure
params - struct wpa_driver_associate_params (ssid, bssid, etc)
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_associate(void *priv, struct wpa_driver_associate_params *params)
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
OS_802_11_MAC_ADDRESS bssid = { 0xff,0xff,0xff,0xff,0xff,0xff };
int wpa_opt, wpa_cipher, ret;
wpa_printf(MSG_DEBUG,"TI: wpa_driver_tista_associate called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
if( myDrv->block_disassoc_events == NO_BLOCK_DISASSOC_IN_PROGRESS )
myDrv->block_disassoc_events = BLOCK_DISASSOC;
if( params->bssid ) {
wpa_printf(MSG_DEBUG, "TI: BSSID=" MACSTR, MAC2STR(params->bssid));
/* if there is bssid -> set it */
if( os_memcmp( params->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN ) != 0 ) {
os_memcpy( &bssid, params->bssid, ETH_ALEN );
TI_SetBSSID( myDrv->hDriver, &bssid );
}
}
else {
/* else set it to {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} */
TI_SetBSSID( myDrv->hDriver, &bssid );
}
/* Set driver network mode (Adhoc/Infrastructure) according to supplied parameters */
if( params->mode == IEEE80211_MODE_INFRA ) {
wpa_printf(MSG_DEBUG,"TI: setting os802_11Infrastructure mode...");
TI_SetBSSType( myDrv->hDriver, os802_11Infrastructure );
}
else if( params->mode == IEEE80211_MODE_IBSS ) {
wpa_printf(MSG_DEBUG,"TI: setting os802_11IBSS mode...");
TI_SetBSSType( myDrv->hDriver, os802_11IBSS );
}
else {
wpa_printf(MSG_ERROR,"TI: Associate: invalid mode specified...");
}
wpa_driver_tista_set_wpa_options( priv, params->key_mgmt_suite );
wpa_driver_tista_set_auth_mode( priv );
wpa_driver_tista_set_encryption( priv, params->pairwise_suite );
/* And trigger connection/association process in driver by setting SSID */
ret = wpa_driver_tista_set_ssid( priv, params->ssid, params->ssid_len);
return( ret );
}
/*-----------------------------------------------------------------------------
Routine Name: ti_init_scan_params
Routine Description: int scan parameters before scan command
Arguments:
pScanParams - pointer to scan paramters structure
pScanPolicy - pointer to scan policy structure
scanType - scan type
noOfChan - number of allowed channels
Return Value: None
-----------------------------------------------------------------------------*/
static void ti_init_scan_params( scan_Params_t *pScanParams,
scan_Policy_t *pScanPolicy,
int scan_type,
struct wpa_driver_ti_data *myDrv )
{
UINT32 scanMaxDwellTime = SME_SCAN_BG_MAX_DWELL_TIME_DEF;
UINT32 scanMinDwellTime = SME_SCAN_BG_MIN_DWELL_TIME_DEF;
UINT32 chanMaxDwellTime = SME_SCAN_BG_MIN_DWELL_TIME_DEF;
UINT32 chanMinDwellTime = SME_SCAN_BG_MIN_DWELL_TIME_DEF / 2;
int scanType = scan_type;
int noOfChan = myDrv->scan_channels;
int btCoexScan = myDrv->btcoex_scan;
int i, j;
UINT8 tid = 0, probeNum = 3;
if( noOfChan > MAX_NUMBER_OF_CHANNELS_PER_SCAN )
noOfChan = MAX_NUMBER_OF_CHANNELS_PER_SCAN;
/* init application scan default params */
pScanParams->desiredSsid.len = 0;
pScanParams->band = RADIO_BAND_2_4_GHZ;
if( btCoexScan ) { /* Changing scan parameteres to coexist with BT A2DP */
if( scanType == SCAN_TYPE_NORMAL_PASSIVE )
scanType = SCAN_TYPE_TRIGGERED_PASSIVE;
else if( scanType == SCAN_TYPE_NORMAL_ACTIVE )
scanType = SCAN_TYPE_TRIGGERED_ACTIVE;
probeNum = 1;
tid = 0xFF;
scanMaxDwellTime /= 6;
scanMinDwellTime /= 6;
chanMaxDwellTime /= 6;
chanMinDwellTime /= 6;
}
pScanParams->scanType = scanType;
pScanParams->probeReqNumber = probeNum;
pScanParams->Tid = tid;
pScanParams->probeRequestRate = DRV_RATE_MASK_2_BARKER;
pScanParams->numOfChannels = (UINT8)noOfChan;
for(i=0;( i < noOfChan );i++) {
for(j=0;( j < MAC_ADDR_LEN );j++) {
pScanParams->channelEntry[ i ].normalChannelEntry.bssId.addr[ j ] = 0xff;
}
pScanParams->channelEntry[ i ].normalChannelEntry.earlyTerminationEvent = SCAN_ET_COND_DISABLE;
pScanParams->channelEntry[ i ].normalChannelEntry.ETMaxNumOfAPframes = 0;
pScanParams->channelEntry[ i ].normalChannelEntry.maxChannelDwellTime = scanMaxDwellTime;
pScanParams->channelEntry[ i ].normalChannelEntry.minChannelDwellTime = scanMinDwellTime;
#ifdef STA_DK_VER_5_0_0_94
pScanParams->channelEntry[ i ].normalChannelEntry.txPowerLevel = 1;
#else
pScanParams->channelEntry[ i ].normalChannelEntry.txPowerDbm = MAX_TX_POWER;
#endif
pScanParams->channelEntry[ i ].normalChannelEntry.channel = i + 1;
}
/* init default scan policy */
pScanPolicy->normalScanInterval = 10000;
pScanPolicy->deterioratingScanInterval = 5000;
pScanPolicy->maxTrackFailures = 3;
pScanPolicy->BSSListSize = 4;
pScanPolicy->BSSNumberToStartDiscovery = 1;
pScanPolicy->numOfBands = 1;
pScanPolicy->bandScanPolicy[ 0 ].band = RADIO_BAND_2_4_GHZ;
pScanPolicy->bandScanPolicy[ 0 ].rxRSSIThreshold = -80;
pScanPolicy->bandScanPolicy[ 0 ].numOfChannles = (UINT8)noOfChan;
pScanPolicy->bandScanPolicy[ 0 ].numOfChannlesForDiscovery = 3;
for(i=0;( i < noOfChan );i++) {
pScanPolicy->bandScanPolicy[ 0 ].channelList[ i ] = i + 1;
}
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.scanType = SCAN_TYPE_NO_SCAN;
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.earlyTerminationEvent = SCAN_ET_COND_DISABLE;
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.ETMaxNumberOfApFrames = 0;
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.maxChannelDwellTime = chanMaxDwellTime;
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.minChannelDwellTime = chanMinDwellTime;
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.probReqParams.bitrate = DRV_RATE_MASK_1_BARKER;
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.probReqParams.numOfProbeReqs = pScanParams->probeReqNumber;
#ifdef STA_DK_VER_5_0_0_94
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.probReqParams.txLevel = 1;
#else
pScanPolicy->bandScanPolicy[ 0 ].trackingMethod.method.basicMethodParams.probReqParams.txPowerDbm = MAX_TX_POWER;
#endif
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.scanType = SCAN_TYPE_NO_SCAN;
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.earlyTerminationEvent = SCAN_ET_COND_DISABLE;
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.ETMaxNumberOfApFrames = 0;
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.maxChannelDwellTime = chanMaxDwellTime;
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.minChannelDwellTime = chanMinDwellTime;
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.probReqParams.bitrate = DRV_RATE_MASK_2_BARKER;
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.probReqParams.numOfProbeReqs = pScanParams->probeReqNumber;
#ifdef STA_DK_VER_5_0_0_94
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.probReqParams.txLevel = 1;
#else
pScanPolicy->bandScanPolicy[ 0 ].discoveryMethod.method.basicMethodParams.probReqParams.txPowerDbm = MAX_TX_POWER;
#endif
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.scanType = btCoexScan ? SCAN_TYPE_TRIGGERED_ACTIVE : SCAN_TYPE_NORMAL_ACTIVE;
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.earlyTerminationEvent = SCAN_ET_COND_DISABLE;
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.ETMaxNumberOfApFrames = 0;
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.maxChannelDwellTime = chanMaxDwellTime;
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.minChannelDwellTime = chanMinDwellTime;
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.probReqParams.bitrate = DRV_RATE_MASK_5_5_CCK;
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.probReqParams.numOfProbeReqs = pScanParams->probeReqNumber;
#ifdef STA_DK_VER_5_0_0_94
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.probReqParams.txLevel = 1;
#else
pScanPolicy->bandScanPolicy[ 0 ].immediateScanMethod.method.basicMethodParams.probReqParams.txPowerDbm = MAX_TX_POWER;
#endif
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_scan
Routine Description: request scan from driver
Arguments:
priv - pointer to private data structure
ssid - ssid buffer
ssid_len - length of ssid
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_scan( void *priv, const UINT8 *ssid, size_t ssid_len )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(myDrv->hWpaSupplicant);
struct wpa_ssid *issid;
scan_Params_t scanParams;
scan_Policy_t scanPolicy;
int scan_type, ret, scan_probe_flag = 0;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_scan called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
scan_type = myDrv->scan_type;
if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) {
if (wpa_s->prev_scan_ssid->scan_ssid) {
scan_type = SCAN_TYPE_NORMAL_ACTIVE;
scan_probe_flag = 1;
}
}
ti_init_scan_params( &scanParams, &scanPolicy, scan_type, myDrv );
myDrv->force_merge_flag = 0; /* Set merge flag */
if ((scan_probe_flag && ssid) &&
(ssid_len > 0 && ssid_len <= sizeof(scanParams.desiredSsid.ssidString))) {
os_memcpy(scanParams.desiredSsid.ssidString, ssid, ssid_len);
if (ssid_len < sizeof(scanParams.desiredSsid.ssidString))
scanParams.desiredSsid.ssidString[ssid_len] = '\0';
scanParams.desiredSsid.len = ssid_len;
myDrv->force_merge_flag = 1;
}
TI_SetScanPolicy( myDrv->hDriver, (UINT8 *)&scanPolicy, sizeof(scan_Policy_t) );
myDrv->last_scan = scan_type; /* Remember scan type for last scan */
ret = TI_StartScan( myDrv->hDriver, (scan_Params_t *)&scanParams );
return( TI2WPA_STATUS(ret) );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_set_auth_alg
Routine Description: set authentication in driver
Arguments:
priv - pointer to private data structure
auth_alg - Open/Shared/LEAP
Return Value: 0 on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_set_auth_alg( void *priv, int auth_alg )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_set_auth_alg called: %d", auth_alg);
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
myDrv->auth_alg = auth_alg;
return( 0 );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_get_bssid_info
Routine Description: retrieve bssid full info
Arguments:
hDriver - pointer to driver structure
Return Value: pointer to BSSID structure or NULL
-----------------------------------------------------------------------------*/
static OS_802_11_BSSID_EX *wpa_driver_tista_get_bssid_info( TI_HANDLE hDriver )
{
OS_802_11_BSSID_LIST_EX *bssid_list;
OS_802_11_BSSID_EX *pBssid, *nBssid = NULL;
int i, number_items, res;
OS_802_11_MAC_ADDRESS bssid;
OS_802_11_SSID ssid;
if( TI_GetBSSIDList( hDriver, &bssid_list ) || !bssid_list )
return( nBssid );
if( TI_GetBSSID( hDriver, &bssid ) != TI_RESULT_OK )
return( nBssid );
if( TI_GetCurrentSSID( hDriver, &ssid ) != TI_RESULT_OK )
return( nBssid );
pBssid = &bssid_list->Bssid[0];
number_items = (int)(bssid_list->NumberOfItems);
for(i=0;( i < number_items );i++) {
if( !os_memcmp((void *)&bssid, pBssid->MacAddress, MAC_ADDR_LEN) &&
!os_memcmp(ssid.Ssid, pBssid->Ssid.Ssid, pBssid->Ssid.SsidLength) ) {
nBssid = (OS_802_11_BSSID_EX *)os_malloc( pBssid->Length );
if( nBssid != NULL )
os_memcpy( nBssid, pBssid, pBssid->Length );
break;
}
pBssid = (OS_802_11_BSSID_EX *)(((char *)pBssid) + pBssid->Length);
}
os_free( bssid_list );
return( nBssid );
}
/*-----------------------------------------------------------------------------
Compare function for sorting scan results. Return >0 if @b is considered better.
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_scan_result_compare(const void *a, const void *b)
{
const struct wpa_scan_result *wa = a;
const struct wpa_scan_result *wb = b;
return( wb->level - wa->level );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_get_scan_results
Routine Description: retrieve driver scan results
Arguments:
priv - pointer to private data structure
results - pointer to buffer
max_size - maximum size of results buffer
Return Value: number of SSID on success, -1 on failure
-----------------------------------------------------------------------------*/
static int wpa_driver_tista_get_scan_results( void *priv,
struct wpa_scan_result *results,
size_t max_size )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
OS_802_11_BSSID_LIST_EX *bssid_list;
OS_802_11_BSSID_EX *pBssid;
OS_802_11_FIXED_IEs *pFixedIes;
OS_802_11_VARIABLE_IEs *pVarIes;
unsigned int number_items, i, index;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_get_scan_results called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
if( TI_GetBSSIDList(myDrv->hDriver, &bssid_list) || !bssid_list )
return( -1 );
pBssid = &bssid_list->Bssid[0];
number_items = (int)(bssid_list->NumberOfItems);
wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%d BSSes)",
number_items * sizeof(OS_802_11_BSSID_EX), number_items);
os_memset( results, 0, max_size * sizeof(struct wpa_scan_result) );
number_items = MIN( number_items, max_size );
for(index=0; index < number_items; index++) {
os_memcpy( results[index].bssid, &pBssid->MacAddress, ETH_ALEN );
os_memcpy( results[index].ssid, pBssid->Ssid.Ssid, pBssid->Ssid.SsidLength );
results[index].ssid_len = pBssid->Ssid.SsidLength;
#ifdef STA_DK_VER_5_0_0_94
results[index].freq = pBssid->Configuration.channel / 1000;
results[index].caps = pBssid->Capabilities;
#else
results[index].freq = pBssid->Configuration.Union.channel / 1000;
results[index].caps = pBssid->Union.Capabilities;
#endif
results[index].level = pBssid->Rssi;
results[index].maxrate = 0; /* In units of 0.5 Mb/s */
for (i = 0; i < sizeof(pBssid->SupportedRates); i++) {
if (pBssid->SupportedRates[i] > (unsigned)results[index].maxrate) {
results[index].maxrate = pBssid->SupportedRates[i];
}
}
wpa_printf(MSG_DEBUG,"TI: Net: %s Cap: 0x%04x Priv: 0x%x NetType: 0x%x InfraMode: 0x%x IELen: %d",
#ifdef STA_DK_VER_5_0_0_94
pBssid->Ssid.Ssid, pBssid->Capabilities, pBssid->Privacy, pBssid->NetworkTypeInUse,
#else
pBssid->Ssid.Ssid, pBssid->Union.Capabilities, pBssid->Privacy, pBssid->NetworkTypeInUse,
#endif
pBssid->InfrastructureMode, pBssid->IELength );
/* Fixed IEs from site entry - same Capabilities */
pFixedIes = (OS_802_11_FIXED_IEs *)&pBssid->IEs[0];
wpa_printf(MSG_DEBUG,"TI: Fixed IEs: Beacon: 0x%x Cap: 0x%x", pFixedIes->BeaconInterval, pFixedIes->Capabilities);
for(i=sizeof(OS_802_11_FIXED_IEs); i < pBssid->IELength;) {
pVarIes = (OS_802_11_VARIABLE_IEs *)&pBssid->IEs[i];
wpa_printf(MSG_DEBUG,"TI: Variable IEs: ID: 0x%x Len: %d", pVarIes->ElementID, pVarIes->Length);
wpa_hexdump(MSG_DEBUG,"TI: oui:", pVarIes->data, pVarIes->Length);
switch( pVarIes->ElementID ) {
case GENERIC_INFO_ELEM: /* 0xdd */
if( (pVarIes->Length > 3) && (os_memcmp(pVarIes->data, WPA_OUI, 4) == 0) ) {
results[index].wpa_ie_len = MIN((pVarIes->Length + 2), SSID_MAX_WPA_IE_LEN);
os_memcpy( results[index].wpa_ie, pVarIes, results[index].wpa_ie_len );
}
break;
case RSN_INFO_ELEM: /* 0x30 */
results[index].rsn_ie_len = MIN((pVarIes->Length + 2), SSID_MAX_WPA_IE_LEN);
os_memcpy( results[index].rsn_ie, pVarIes, results[index].rsn_ie_len );
break;
}
i += (pVarIes->Length + (2 * sizeof(tiUINT8)));
}
pBssid = (OS_802_11_BSSID_EX *)(((u8 *)pBssid) + pBssid->Length);
}
/* Merge new results with previous */
number_items = scan_merge( myDrv, results, myDrv->force_merge_flag, number_items, max_size );
qsort( results, number_items, sizeof(struct wpa_scan_result),
wpa_driver_tista_scan_result_compare );
os_free( bssid_list );
return( number_items );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_get_scan_results
Routine Description: retrieve driver scan results
Arguments:
sock - socket
priv - pointer to private data structure
sock_ctx - pointer to other private data
Return Value: None
-----------------------------------------------------------------------------*/
static void wpa_driver_tista_receive_driver_event( int sock, void *priv, void *sock_ctx )
{
IPC_EV_DATA myBuf;
UINT8 *buf;
UINT32 *bufLong;
union wpa_event_data myEventData;
struct wpa_driver_ti_data *mySuppl;
OS_802_11_ASSOCIATION_INFORMATION *pInfo = NULL;
OS_802_11_AUTHENTICATION_REQUEST *pMediaSpecificBuf;
OS_802_11_BSSID_EX *pSelectedBssidInfo = NULL;
OS_802_11_NETWORK_MODE myBssType;
IPC_EV_DATA *pData = &myBuf;
int res;
#ifndef STA_DK_VER_5_0_0_94
btCoexStatus_t *btCoexStatus;
#endif
wpa_printf(MSG_DEBUG,"wpa_driver_tista_receive_driver_event...");
res = recv( sock, &myBuf, sizeof(myBuf), 0 );
if( res < 0 ) {
wpa_printf(MSG_ERROR,"l2_packet_receive - recvfrom");
return;
}
mySuppl = pData->EvParams.hUserParam;
switch( ((IPC_EVENT_PARAMS*)pData)->uEventType ) {
case IPC_EVENT_ASSOCIATED:
/* Associated event is called after successfull ASSOC_RSP packet is received */
wpa_printf(MSG_DEBUG,"wpa_supplicant - Associated");
TI_GetBSSType( mySuppl->hDriver, &myBssType );
wpa_printf(MSG_DEBUG,"myBssType = %d",myBssType);
if( myBssType == os802_11Infrastructure ) {
/* Get ASSOC_REQ and ASSOC_RSP IE */
res = TI_GetAssociationInfo( mySuppl->hDriver, &pInfo );
buf = (UINT8 *)pInfo;
if( buf != NULL ) {
myEventData.assoc_info.req_ies = buf + pInfo->OffsetRequestIEs;
myEventData.assoc_info.req_ies_len = pInfo->RequestIELength;
myEventData.assoc_info.resp_ies = buf + pInfo->OffsetResponseIEs;
myEventData.assoc_info.resp_ies_len = pInfo->ResponseIELength;
myEventData.assoc_info.beacon_ies = NULL;
myEventData.assoc_info.beacon_ies_len = 0;
/* Get AP Beacon IEs - especially WPA/RSN IE */
pSelectedBssidInfo = wpa_driver_tista_get_bssid_info( mySuppl->hDriver );
if( pSelectedBssidInfo ) {
if( pSelectedBssidInfo->IELength && pSelectedBssidInfo->IEs ) { /* Dm: Fixed IEs */
myEventData.assoc_info.beacon_ies = (UINT8 *)pSelectedBssidInfo->IEs + sizeof(OS_802_11_FIXED_IEs);
myEventData.assoc_info.beacon_ies_len = pSelectedBssidInfo->IELength - sizeof(OS_802_11_FIXED_IEs);
}
}
wpa_printf(MSG_DEBUG,"myEventData.assoc_info.req_ies = 0x%x",(unsigned)myEventData.assoc_info.req_ies);
wpa_printf(MSG_DEBUG,"myEventData.assoc_info.req_ies_len = %d",myEventData.assoc_info.req_ies_len);
wpa_printf(MSG_DEBUG,"myEventData.assoc_info.resp_ies = 0x%x",(unsigned)myEventData.assoc_info.resp_ies);
wpa_printf(MSG_DEBUG,"myEventData.assoc_info.resp_ies_len = %d",myEventData.assoc_info.resp_ies_len);
wpa_printf(MSG_DEBUG,"myEventData.assoc_info.beacon_ies = 0x%x",(unsigned)myEventData.assoc_info.beacon_ies);
wpa_printf(MSG_DEBUG,"myEventData.assoc_info.beacon_ies_len = %d",myEventData.assoc_info.beacon_ies_len);
wpa_hexdump(MSG_DEBUG, "WPA: beacon_ies", myEventData.assoc_info.beacon_ies, myEventData.assoc_info.beacon_ies_len);
/* First we notify wpa_supplicant and give it all the above IEs */
wpa_supplicant_event( mySuppl->hWpaSupplicant, EVENT_ASSOCINFO, &myEventData );
/* Since both ASSOC_REQ/RSP and beacon IEs are allocated dynamically by the Utility Adapter - we need to free the buffers */
os_free( pInfo );
if( pSelectedBssidInfo ) {
os_free( pSelectedBssidInfo );
}
}
}
else {
myEventData.assoc_info.req_ies = NULL;
myEventData.assoc_info.req_ies_len = 0;
myEventData.assoc_info.resp_ies = NULL;
myEventData.assoc_info.resp_ies_len = 0;
myEventData.assoc_info.beacon_ies = NULL;
myEventData.assoc_info.beacon_ies_len = 0;
wpa_supplicant_event( mySuppl->hWpaSupplicant, EVENT_ASSOCINFO, &myEventData );
}
/* We now can notify wpa_supplicant of the association event so it could start key negotiation (if needed) */
wpa_supplicant_event( mySuppl->hWpaSupplicant, EVENT_ASSOC, NULL );
/* Allow Disassociation */
mySuppl->block_disassoc_events = NO_BLOCK;
break;
case IPC_EVENT_DISASSOCIATED:
if( mySuppl->block_disassoc_events != BLOCK_DISASSOC ) {
wpa_printf(MSG_DEBUG,"wpa_supplicant - Disassociated");
wpa_supplicant_event( mySuppl->hWpaSupplicant, EVENT_DISASSOC, NULL );
}
else {
wpa_printf(MSG_INFO,"wpa_supplicant - Disassociated (blocked)");
}
break;
case IPC_EVENT_SCAN_COMPLETE:
wpa_printf(MSG_DEBUG,"wpa_supplicant - IPC_EVENT_SCAN_COMPLETE");
wpa_supplicant_event( mySuppl->hWpaSupplicant, EVENT_SCAN_RESULTS, NULL );
break;
case IPC_EVENT_AUTH_SUCC:
wpa_printf(MSG_INFO,"wpa_supplicant - IPC_EVENT_AUTH_SUCC");
break;
case IPC_EVENT_EAPOL:
wpa_printf(MSG_DEBUG,"wpa_supplicant - EAPOL");
buf = pData->uBuffer;
wpa_supplicant_rx_eapol( mySuppl->hWpaSupplicant, (UINT8 *)(buf + MAC_ADDR_LEN),
(UINT8 *)(buf + ETHERNET_HDR_LEN), (pData->uBufferSize - ETHERNET_HDR_LEN) );
break;
case IPC_EVENT_MEDIA_SPECIFIC:
wpa_printf(MSG_DEBUG,"wpa_supplicant - Media_Specific");
bufLong = (UINT32 *)pData->uBuffer;
/* Check for Authentication type messages from driver */
if( (*bufLong) == os802_11StatusType_Authentication ) {
pMediaSpecificBuf = (OS_802_11_AUTHENTICATION_REQUEST *)(bufLong + 1);
wpa_printf(MSG_DEBUG,"wpa_supplicant - Media_Specific - Authentication message detected: %u", pMediaSpecificBuf->Flags);
/* Check for MIC failure event */
if( (pMediaSpecificBuf->Flags == OS_802_11_REQUEST_PAIRWISE_ERROR) || (pMediaSpecificBuf->Flags == OS_802_11_REQUEST_GROUP_ERROR)) {
/* Notify wpa_supplicant of MIC failure */
myEventData.michael_mic_failure.unicast = 1;
wpa_supplicant_event( mySuppl->hWpaSupplicant, EVENT_MICHAEL_MIC_FAILURE, &myEventData );
}
/* OS_802_11_REQUEST_REAUTH - is handled automatically */
/* OS_802_11_REQUEST_KEYUPDATE - no event of this type */
}
break;
case IPC_EVENT_LINK_SPEED:
bufLong = (UINT32 *)pData->uBuffer;
wpa_printf(MSG_DEBUG,"wpa_supplicant - Link Speed = %u MB/s", ((*bufLong) / 2));
/* wpa_msg(mySuppl->hWpaSupplicant, MSG_INFO, WPA_EVENT_LINK_SPEED "%u MB/s", ((*bufLong) / 2)); */
mySuppl->link_speed = (unsigned)((*bufLong) / 2);
break;
case IPC_EVENT_WPA2_PREAUTHENTICATION:
wpa_printf(MSG_DEBUG,"wpa_supplicant - WPA2_PREAUTHENTICATION");
bufLong = (UINT32 *)pData->uBuffer;
wpa_printf(MSG_DEBUG,"Preauth Status Code = %u",*bufLong);
/* Dm: wpa_supplicant_event( mySuppl->hWpaSupplicant, EVENT_PMKID_CANDIDATE, &data); */
break;
#ifndef STA_DK_VER_5_0_0_94
case IPC_EVENT_BT_COEX_MODE:
btCoexStatus = (btCoexStatus_t *)pData->uBuffer;
if( (btCoexStatus != NULL) && btCoexStatus->state ) {
wpa_printf(MSG_DEBUG,"wpa_supplicant - BT_COEX_MODE (SG is ON, minTxRate = %d)\n", btCoexStatus->minTxRate);
}
else {
wpa_printf(MSG_DEBUG,"wpa_supplicant - BT_COEX_MODE (SG is OFF)\n");
}
break;
#endif
case IPC_EVENT_LOW_SNR:
case IPC_EVENT_LOW_RSSI:
break;
default:
wpa_printf(MSG_ERROR,"wpa_supplicant - Unhandled driver event: %d", ((IPC_EVENT_PARAMS*)pData)->uEventType);
break;
}
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_init
Routine Description: init driver interface
Arguments:
priv - pointer to private data structure
ifname - return interface name
Return Value: pointer to driver structure (to be supplied later by supplicant to wrappers)
-----------------------------------------------------------------------------*/
static void *wpa_driver_tista_init( void *priv, const char *ifname )
{
struct wpa_driver_ti_data *myDrv;
int status;
UINT32 driverStatus,res;
struct sockaddr_in echoserver;
OS_802_11_MAC_ADDRESS myMac;
#ifdef CONFIG_TI_LOCKFILE
char str[10];
#endif
wpa_printf(MSG_DEBUG,"Initializing STA-DK %s interface...",SW_VERSION_STR);
#ifdef CONFIG_TI_LOCKFILE
/* Try to open the lock file */
lfp = open("./.wpa_supplicant_lockfile.pid", (O_RDWR | O_CREAT | O_EXCL), 0640);
if( lfp < 0 ) {
wpa_printf(MSG_ERROR,"Cannot open pid-file...Aborting...\n");
return( NULL );
}
/* Try to get a file lock on the pid-file. If another instance is running and already has a lock - we will fail */
#ifndef ANDROID /* Dm: !!! lockf is not implemented in Android */
if( lockf(lfp,F_TLOCK,0) < 0 ) {
wpa_printf(MSG_ERROR,"Another instance of wpa_supplicant is running...Aborting...\n");
return( NULL );
}
#endif
/* If we got here - it means that no other instance is running - write process id to pid_file */
sprintf(str, "%d\n", getpid());
write(lfp,str,os_strlen(str)); /* record pid to lockfile */
#endif
/* Allocate internal data structure to manage driver */
myDrv = os_malloc( sizeof(struct wpa_driver_ti_data) );
/* If failed to allocate */
if( myDrv == NULL ) {
wpa_printf(MSG_ERROR,"Failed to allocate memory for control structure...Aborting...");
goto label_init_error_file;
}
/* Zero memory */
os_memset( myDrv, 0, sizeof(struct wpa_driver_ti_data) );
/* Initialize Utility Adapter module */
myDrv->hDriver = TI_AdapterInit( TIWLAN_DRV_NAME );
/* If couldn't initialize - return NULL to indicate error */
if( myDrv->hDriver == 0 ) {
wpa_printf(MSG_ERROR,"Error: failed to initialize Utility Adapter interface...");
goto label_init_error_free;
}
/* Get WLAN interface mac address through Utility Adapter */
res = TI_GetCurrentAddress( myDrv->hDriver, &myMac );
if( res == (UINT32)-1 ) {
wpa_printf(MSG_ERROR,"Error: failed to initialize Utility Adapter interface...");
goto label_init_error_free;
}
os_memcpy( &myDrv->own_addr, &myMac, MAC_ADDR_LEN );
wpa_driver_tista_register_events( myDrv );
/* Block disassoc events until connected */
if( myDrv->block_disassoc_events == NO_BLOCK )
myDrv->block_disassoc_events = NO_BLOCK_DISASSOC_IN_PROGRESS;
/* Store wpa_supplicant context */
myDrv->hWpaSupplicant = priv;
myDrv->driverEventsSocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
if( myDrv->driverEventsSocket < 0 ) {
wpa_printf(MSG_ERROR,"Error: failed to create driver events socket... (%s)", strerror(errno));
goto label_init_error_free;
}
os_memset( &echoserver, 0, sizeof(echoserver) ); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* IP address */
echoserver.sin_port = htons(TI_DRIVER_MSG_PORT); /* server port */
if( bind(myDrv->driverEventsSocket, (struct sockaddr *) &echoserver, sizeof(echoserver)) < 0 ) {
wpa_printf(MSG_ERROR,"Error: failed to create driver events socket... (%s)", strerror(errno));
close(myDrv->driverEventsSocket);
goto label_init_error_free;
}
status = eloop_register_read_sock( myDrv->driverEventsSocket, wpa_driver_tista_receive_driver_event, priv, myDrv );
if( status != 0 ) {
wpa_printf(MSG_ERROR,"Error: failed to register socket handler...");
}
wpa_printf(MSG_DEBUG,"driver events socket is 0x%x...",myDrv->driverEventsSocket);
/* Signal that driver is not stopped */
myDrv->driver_is_loaded = TRUE;
/* Set default scan type */
myDrv->scan_type = SCAN_TYPE_NORMAL_ACTIVE;
myDrv->force_merge_flag = 0;
scan_init( myDrv );
/* Set default amount of channels */
myDrv->scan_channels = check_and_get_build_channels();
/* Link Speed will be set by the message from the driver */
myDrv->link_speed = 0;
/* BtCoex mode is read from tiwlan.ini file */
myDrv->btcoex_mode = 1; /* SG_DISABLE */
myDrv->btcoex_scan = FALSE;
/* RTS Threshold is read from tiwlan.ini file */
myDrv->rts_threshold = HAL_CTRL_RTS_THRESHOLD_MAX;
/* Return pointer to our driver structure */
return( myDrv );
label_init_error_free:
os_free( myDrv );
label_init_error_file:
#ifdef CONFIG_TI_LOCKFILE
/* Close and delete the pid-lock-file */
close(lfp);
unlink("./wpa_supplicant_lockfile.pid");
#endif
return( NULL );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_unload
Routine Description: unload driver
Arguments:
priv - pointer to private data structure
Return Value: None
-----------------------------------------------------------------------------*/
static void wpa_driver_tista_unload( void *priv )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_unload called");
/* Unregister driver events */
wpa_driver_tista_unregister_events( priv );
/* Close connection socket */
close(myDrv->driverEventsSocket);
/* Unload Utility Adapter */
TI_AdapterDeinit( myDrv->hDriver );
/* Free all allocated memory */
scan_exit( myDrv );
os_free( myDrv );
#ifdef CONFIG_TI_LOCKFILE
/* Close and delete the pid-lock-file */
close(lfp);
unlink("./wpa_supplicant_lockfile.pid");
#endif
wpa_printf(MSG_DEBUG,"STA-DK %s interface Deinitialized...bye!", SW_VERSION_STR);
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_get_mac_addr
Routine Description: return WLAN MAC address
Arguments:
priv - pointer to private data structure
Return Value: pointer to BSSID
-----------------------------------------------------------------------------*/
const u8 *wpa_driver_tista_get_mac_addr( void *priv )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
wpa_printf(MSG_DEBUG,"wpa_driver_tista_get_mac_addr called");
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, NULL );
return( (const u8 *)&myDrv->own_addr );
}
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_send_eapol
Routine Description: transmit EAPOL
Arguments:
priv - pointer to private data structure
data - pointer to EAPOL data
data_len - length of EAPOL data
Return Value: None
-----------------------------------------------------------------------------*/
static int ti_send_eapol( void *priv, const u8 *dest, u16 proto,
const u8 *data, size_t data_len )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
u8* DataWithHeader = NULL;
u16 protoNetwork;
int ret = 0;
wpa_printf(MSG_DEBUG,"TI send_eapol called");
#ifdef IEEE8021X_EAPOL
DataWithHeader = os_malloc(data_len + ETHERNET_HDR_LEN); /* 14 bytes */
if( DataWithHeader == NULL ) {
wpa_printf(MSG_ERROR,"TI send_eapol failed to alloc full buffer");
return( -1 );
}
os_memcpy(DataWithHeader, dest, MAC_ADDR_LEN); /* 6 bytes */
os_memcpy(DataWithHeader+MAC_ADDR_LEN, myDrv->own_addr, MAC_ADDR_LEN);
protoNetwork = htons(proto);
os_memcpy(DataWithHeader+(MAC_ADDR_LEN<<1), &protoNetwork, sizeof(u16)); /* 2 bytes */
os_memcpy(DataWithHeader+ETHERNET_HDR_LEN, data, data_len);
data_len += ETHERNET_HDR_LEN;
wpa_hexdump(MSG_DEBUG, "WPA: FULL TX EAPOL-Key", DataWithHeader, data_len);
/* Transmit EAPOL packet */
ret = TI_Send_EAPOL_Packet( myDrv->hDriver, (void *)DataWithHeader, data_len );
os_free(DataWithHeader);
#endif
return( TI2WPA_STATUS(ret) );
}
#ifndef STA_DK_VER_5_0_0_94
/*-----------------------------------------------------------------------------
Routine Name: prepare_filter_struct
Routine Description: fills rx data filter structure according to parameter type
Arguments:
priv - pointer to private data structure
type - type of mac address
dfreq_ptr - pointer to TIWLAN_DATA_FILTER_REQUEST structure
Return Value: 0 - success, -1 - error
-----------------------------------------------------------------------------*/
static int prepare_filter_struct( void *priv, int type,
TIWLAN_DATA_FILTER_REQUEST *dfreq_ptr )
{
u8 *macaddr = NULL;
size_t len = 0;
u8 mask = 0;
int ret = -1;
wpa_printf(MSG_ERROR, "%s: type=%d", __func__, type);
switch (type ) {
case RX_SELF_FILTER:
macaddr = (u8 *)wpa_driver_tista_get_mac_addr(priv);
len = MAC_ADDR_LEN;
mask = 0x3F; /* 6 bytes */
break;
case RX_BROADCAST_FILTER:
macaddr = (u8 *)"\xFF\xFF\xFF\xFF\xFF\xFF";
len = MAC_ADDR_LEN;
mask = 0x3F; /* 6 bytes */
break;
case RX_IPV4_MULTICAST_FILTER:
macaddr = (u8 *)"\x01\x00\x5E";
len = 3;
mask = 0x7; /* 3 bytes */
break;
case RX_IPV6_MULTICAST_FILTER:
macaddr = (u8 *)"\x33\x33";
len = 2;
mask = 0x3; /* 2 bytes */
break;
}
if (len && macaddr) {
dfreq_ptr->Offset = 0;
dfreq_ptr->MaskLength = 1;
dfreq_ptr->Mask[0] = mask;
dfreq_ptr->PatternLength = len;
os_memcpy( dfreq_ptr->Pattern, macaddr, len );
ret = 0;
}
return( ret );
}
#endif
/*-----------------------------------------------------------------------------
Routine Name: wpa_driver_tista_driver_cmd
Routine Description: executes driver-specific commands
Arguments:
priv - pointer to private data structure
cmd - command
buf - return buffer
buf_len - buffer length
Return Value: actual buffer length - success, -1 - failure
-----------------------------------------------------------------------------*/
int wpa_driver_tista_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len )
{
struct wpa_driver_ti_data *myDrv = (struct wpa_driver_ti_data *)priv;
int ret = -1, prev_events;
wpa_printf(MSG_DEBUG, "%s %s", __func__, cmd);
if( os_strcasecmp(cmd, "start") == 0 ) {
wpa_printf(MSG_DEBUG,"Start command");
prev_events = myDrv->block_disassoc_events;
myDrv->block_disassoc_events = myDrv->block_disassoc_prev;
ret = TI_Start( myDrv->hDriver );
if( ret == OK ) {
/* Signal that driver is not loaded yet */
myDrv->driver_is_loaded = TRUE;
wpa_msg(myDrv->hWpaSupplicant, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
}
else
myDrv->block_disassoc_events = prev_events;
return( TI2WPA_STATUS(ret) );
}
/* If driver is not initialized yet - we cannot access it so return */
TI_CHECK_DRIVER( myDrv->driver_is_loaded, -1 );
if( os_strcasecmp(cmd, "stop") == 0 ) {
wpa_printf(MSG_DEBUG,"Stop command");
myDrv->block_disassoc_prev = myDrv->block_disassoc_events;
myDrv->block_disassoc_events = BLOCK_DISASSOC; /* Block message */
ret = TI_Stop( myDrv->hDriver );
if( ret == OK ) {
/* Signal that driver is not loaded yet */
myDrv->driver_is_loaded = FALSE;
wpa_msg(myDrv->hWpaSupplicant, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
}
else
myDrv->block_disassoc_events = myDrv->block_disassoc_prev;
}
else if( os_strcasecmp(cmd, "macaddr") == 0 ) {
u8 *macaddr = (u8 *)wpa_driver_tista_get_mac_addr(priv);
wpa_printf(MSG_DEBUG,"Macaddr command");
wpa_printf(MSG_DEBUG, " Macaddr = " MACSTR, MAC2STR(macaddr));
ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
if (ret < (int)buf_len) {
return( ret );
}
}
else if( os_strcasecmp(cmd, "scan-passive") == 0 ) {
wpa_printf(MSG_DEBUG,"Scan Passive command");
myDrv->scan_type = SCAN_TYPE_NORMAL_PASSIVE;
ret = 0;
}
else if( os_strcasecmp(cmd, "scan-active") == 0 ) {
wpa_printf(MSG_DEBUG,"Scan Active command");
myDrv->scan_type = SCAN_TYPE_NORMAL_ACTIVE;
ret = 0;
}
else if( os_strcasecmp(cmd, "scan-mode") == 0 ) {
wpa_printf(MSG_DEBUG,"Scan Mode command");
ret = snprintf(buf, buf_len, "ScanMode = %u\n", myDrv->scan_type);
if (ret < (int)buf_len) {
return( ret );
}
}
else if( os_strcasecmp(cmd, "linkspeed") == 0 ) {
wpa_printf(MSG_DEBUG,"Link Speed command");
ret = snprintf(buf, buf_len, "LinkSpeed %u\n", myDrv->link_speed);
if (ret < (int)buf_len) {
return( ret );
}
}
else if( os_strncasecmp(cmd, "scan-channels", 13) == 0 ) {
int noOfChan;
char *cp = cmd + 13;
char *endp;
if (*cp != '\0') {
noOfChan = strtol(cp, &endp, 0);
if (endp != cp) {
wpa_printf(MSG_DEBUG,"Scan Channels command = %d", noOfChan);
if( (noOfChan > 0) && (noOfChan <= MAX_NUMBER_OF_CHANNELS_PER_SCAN) ) {
myDrv->scan_channels = noOfChan;
ret = 0;
}
}
} else {
ret = snprintf(buf, buf_len, "Scan-Channels = %d\n", myDrv->scan_channels);
if (ret < (int)buf_len) {
return( ret );
}
}
}
else if( os_strcasecmp(cmd, "rssi-approx") == 0 ) {
struct wpa_scan_result *cur_res;
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(myDrv->hWpaSupplicant);
int rssi, len;
wpa_printf(MSG_DEBUG,"rssi-approx command");
if( !wpa_s )
return( ret );
cur_res = scan_get_by_bssid( myDrv, wpa_s->bssid );
if( cur_res ) {
len = (int)(cur_res->ssid_len);
rssi = cur_res->level;
if( (len > 0) && (len <= MAX_SSID_LEN) && (len < (int)buf_len)) {
os_memcpy( (void *)buf, (void *)(cur_res->ssid), len );
ret = len;
ret += snprintf(&buf[ret], buf_len-len, " rssi %d\n", rssi);
if (ret < (int)buf_len) {
return( ret );
}
}
}
}
else if( os_strcasecmp(cmd, "rssi") == 0 ) {
#if 1
u8 ssid[MAX_SSID_LEN];
struct wpa_scan_result *cur_res;
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(myDrv->hWpaSupplicant);
int rssi, len;
wpa_printf(MSG_DEBUG,"rssi command");
ret = TI_GetRSSI( myDrv->hDriver, &rssi );
if( ret == OK ) {
len = wpa_driver_tista_get_ssid( priv, (u8 *)ssid );
if( (len > 0) && (len <= MAX_SSID_LEN) && (len < (int)buf_len)) {
os_memcpy( (void *)buf, (void *)ssid, len );
ret = len;
ret += snprintf(&buf[ret], buf_len-len, " rssi %d\n", rssi);
if( !wpa_s )
return( ret );
cur_res = scan_get_by_bssid( myDrv, wpa_s->bssid );
if( cur_res )
cur_res->level = rssi;
return( ret );
}
}
#else
OS_802_11_BSSID_EX bssidInfo;
wpa_printf(MSG_DEBUG,"rssi command");
ret = TI_GetSelectedBSSIDInfo( myDrv->hDriver, (OS_802_11_BSSID_EX *)&bssidInfo );
if( ret == OK ) {
if( bssidInfo.Ssid.SsidLength != 0 && bssidInfo.Ssid.SsidLength < buf_len) {
os_memcpy( (void *)buf, (void *)(bssidInfo.Ssid.Ssid), bssidInfo.Ssid.SsidLength );
ret = bssidInfo.Ssid.SsidLength;
ret += snprintf(&buf[ret], buf_len-ret, " rssi %d\n", bssidInfo.Rssi);
if (ret < (int)buf_len) {
return( ret );
}
}
ret = -1;
}
#endif
}
else if( os_strncasecmp(cmd, "powermode", 9) == 0 ) {
u32 rtsThreshold = myDrv->rts_threshold;
u32 mode;
char *cp = cmd + 9;
char *endp;
if (*cp != '\0') {
mode = (u32)strtol(cp, &endp, 0);
if (endp != cp) {
wpa_printf(MSG_DEBUG,"Power Mode command = %u", mode);
if( mode <= OS_POWER_MODE_LONG_DOZE )
ret = TI_ConfigPowerManagement( myDrv->hDriver, mode );
if( mode == OS_POWER_MODE_ACTIVE )
rtsThreshold = 0;
if( TI_SetRTSThreshold( myDrv->hDriver, rtsThreshold ) != OK )
wpa_printf(MSG_DEBUG,"Set RTS threshold = %u failed", rtsThreshold);
}
}
}
else if( os_strncasecmp(cmd, "getpower", 8) == 0 ) {
u32 mode;
ret = TI_GetPowerMode( myDrv->hDriver, (OS_802_11_POWER_PROFILE *)&mode);
if( ret == OK ) {
ret = snprintf(buf, buf_len, "powermode = %u\n", mode);
if (ret < (int)buf_len) {
return( ret );
}
}
}
else if( os_strncasecmp(cmd, "get-rts-threshold", 17) == 0 ) {
tiUINT32 rtsThreshold = 0;
ret = TI_GetRTSThreshold( myDrv->hDriver, &rtsThreshold );
wpa_printf(MSG_DEBUG,"Get RTS Threshold command = %d", rtsThreshold);
if( ret == OK ) {
ret = snprintf(buf, buf_len, "rts-threshold = %u\n", rtsThreshold);
if (ret < (int)buf_len) {
return( ret );
}
}
}
else if( os_strncasecmp(cmd, "set-rts-threshold", 17) == 0 ) {
tiUINT32 rtsThreshold = 0;
char *cp = cmd + 17;
char *endp;
if (*cp != '\0') {
rtsThreshold = (tiUINT32)strtol(cp, &endp, 0);
if (endp != cp) {
wpa_printf(MSG_DEBUG,"RTS Threshold command = %d", rtsThreshold);
if( rtsThreshold <= HAL_CTRL_RTS_THRESHOLD_MAX ) {
ret = TI_SetRTSThreshold( myDrv->hDriver, rtsThreshold );
if( ret == OK ) {
myDrv->rts_threshold = rtsThreshold;
}
}
}
}
}
else if( os_strcasecmp(cmd, "btcoexscan-start") == 0 ) {
wpa_printf(MSG_DEBUG,"BT Coex Scan Start command");
myDrv->btcoex_scan = TRUE;
ret = 0;
}
else if( os_strcasecmp(cmd, "btcoexscan-stop") == 0 ) {
wpa_printf(MSG_DEBUG,"BT Coex Scan Stop command");
myDrv->btcoex_scan = FALSE;
ret = 0;
}
#ifndef STA_DK_VER_5_0_0_94
else if( os_strcasecmp(cmd, "rxfilter-start") == 0 ) {
wpa_printf(MSG_DEBUG,"Rx Data Filter Start command");
ret = TI_EnableDisableRxDataFilters( myDrv->hDriver, TRUE );
}
else if( os_strcasecmp(cmd, "rxfilter-stop") == 0 ) {
wpa_printf(MSG_DEBUG,"Rx Data Filter Stop command");
ret = TI_EnableDisableRxDataFilters( myDrv->hDriver, FALSE );
}
else if( os_strcasecmp(cmd, "rxfilter-statistics") == 0 ) {
TIWLAN_DATA_FILTER_STATISTICS stats;
int len, i;
wpa_printf(MSG_DEBUG,"Rx Data Filter Statistics command");
ret = TI_GetRxDataFiltersStatistics( myDrv->hDriver, &stats );
if( ret == OK ) {
ret = snprintf(buf, buf_len, "RxFilterStat: %u",
stats.UnmatchedPacketsCount);
for(i=0;( i < MAX_NUM_DATA_FILTERS );i++) {
ret += snprintf(&buf[ret], buf_len-ret, " %u",
stats.MatchedPacketsCount[i]);
}
ret += snprintf(&buf[ret], buf_len-ret, "\n");
if (ret < (int)buf_len) {
return( ret );
}
}
}
else if( os_strncasecmp(cmd, "rxfilter-add", 12) == 0 ) {
TIWLAN_DATA_FILTER_REQUEST dfreq;
char *cp = cmd + 12;
char *endp;
int type;
if (*cp != '\0') {
type = (int)strtol(cp, &endp, 0);
if (endp != cp) {
wpa_printf(MSG_DEBUG,"Rx Data Filter Add [%d] command", type);
ret = prepare_filter_struct( priv, type, &dfreq );
if( ret == 0 ) {
ret = TI_AddRxDataFilter( myDrv->hDriver, &dfreq );
}
}
}
}
else if( os_strncasecmp(cmd, "rxfilter-remove",15) == 0 ) {
wpa_printf(MSG_DEBUG,"Rx Data Filter Remove command");
TIWLAN_DATA_FILTER_REQUEST dfreq;
char *cp = cmd + 15;
char *endp;
int type;
if (*cp != '\0') {
type = (int)strtol(cp, &endp, 0);
if (endp != cp) {
wpa_printf(MSG_DEBUG,"Rx Data Filter Remove [%d] command", type);
ret = prepare_filter_struct( priv, type, &dfreq );
if( ret == 0 ) {
ret = TI_RemoveRxDataFilter( myDrv->hDriver, &dfreq );
}
}
}
}
else if( os_strcasecmp(cmd, "snr") == 0 ) {
u32 snr;
ret = TI_GetSNR( myDrv->hDriver, &snr );
if( ret == OK ) {
ret = snprintf(buf, buf_len, "snr = %u\n", snr);
if (ret < (int)buf_len) {
return( ret );
}
}
}
else if( os_strncasecmp(cmd, "btcoexmode", 10) == 0 ) {
u32 mode;
char *cp = cmd + 10;
char *endp;
if (*cp != '\0') {
mode = (u32)strtol(cp, &endp, 0);
if (endp != cp) {
wpa_printf(MSG_DEBUG,"BtCoex Mode command = %u", mode);
ret = TI_SetBtCoeEnable( myDrv->hDriver, mode );
if( ret == OK ) {
myDrv->btcoex_mode = mode;
}
}
}
}
else if( os_strcasecmp(cmd, "btcoexstat") == 0 ) {
u32 status = myDrv->btcoex_mode;
wpa_printf(MSG_DEBUG,"BtCoex Status");
ret = TI_SetBtCoeGetStatus( myDrv->hDriver, (tiUINT32 *)&status );
if( ret == OK ) {
ret = snprintf(buf, buf_len, "btcoexstatus = 0x%x\n", status);
if (ret < (int)buf_len) {
return( ret );
}
}
}
#endif
else {
wpa_printf(MSG_DEBUG,"Unsupported command");
}
return( TI2WPA_STATUS(ret) );
}
/* Fill driver_ops structure to provide wpa_supplicant core with wrapper routines */
struct wpa_driver_ops wpa_driver_custom_ops = {
.name = TIWLAN_DRV_NAME,
.desc = "TI Station Driver",
.init = wpa_driver_tista_init,
.deinit = wpa_driver_tista_unload,
.get_bssid = wpa_driver_tista_get_bssid,
.get_ssid = wpa_driver_tista_get_ssid,
.set_wpa = wpa_driver_tista_set_wpa,
.set_key = wpa_driver_tista_set_key,
.set_param = NULL,
.set_countermeasures = wpa_driver_tista_set_countermeasures,
.set_drop_unencrypted = wpa_driver_tista_set_drop_unencrypted,
.scan = wpa_driver_tista_scan,
.get_scan_results = wpa_driver_tista_get_scan_results,
.deauthenticate = wpa_driver_tista_deauthenticate,
.disassociate = wpa_driver_tista_disassociate,
.associate = wpa_driver_tista_associate,
.set_auth_alg = wpa_driver_tista_set_auth_alg,
.get_mac_addr = wpa_driver_tista_get_mac_addr,
.send_eapol = ti_send_eapol,
.add_pmkid = NULL,
.remove_pmkid = NULL,
.flush_pmkid = NULL,
.get_capa = NULL,
.poll = NULL,
.get_ifname = NULL, /* Not nesessary */
.set_operstate = NULL,
#ifdef CONFIG_CLIENT_MLME
.get_hw_modes = NULL,
.set_channel = NULL,
.set_ssid = wpa_driver_tista_set_ssid,
.set_bssid = NULL,
.send_mlme = NULL,
.mlme_add_sta = NULL,
.mlme_remove_sta = NULL,
.mlme_setprotection = NULL,
#endif /* CONFIG_CLIENT_MLME */
.driver_cmd = wpa_driver_tista_driver_cmd
};