| /* |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * |
| */ |
| |
| #include "includes.h" |
| #include <sys/ioctl.h> |
| #include <net/if_arp.h> |
| #ifdef ANDROID |
| #include <cutils/properties.h> |
| #endif |
| #include "driver_ti.h" |
| #include "scanmerge.h" |
| #ifdef CONFIG_WPS |
| #include "wps_defs.h" |
| #endif |
| |
| /*-------------------------------------------------------------------*/ |
| #define TI2WPA_STATUS(s) (((s) != 0) ? -1 : 0) |
| #define TI_CHECK_DRIVER(f,r) \ |
| if( !(f) ) { \ |
| wpa_printf(MSG_ERROR,"TI: Driver not initialized yet"); \ |
| return( r ); \ |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 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 |
| } |
| |
| static int wpa_driver_tista_cipher2wext(int cipher) |
| { |
| switch (cipher) { |
| case CIPHER_NONE: |
| return IW_AUTH_CIPHER_NONE; |
| case CIPHER_WEP40: |
| return IW_AUTH_CIPHER_WEP40; |
| case CIPHER_TKIP: |
| return IW_AUTH_CIPHER_TKIP; |
| case CIPHER_CCMP: |
| return IW_AUTH_CIPHER_CCMP; |
| case CIPHER_WEP104: |
| return IW_AUTH_CIPHER_WEP104; |
| default: |
| return 0; |
| } |
| } |
| |
| static int wpa_driver_tista_keymgmt2wext(int keymgmt) |
| { |
| switch (keymgmt) { |
| case KEY_MGMT_802_1X: |
| case KEY_MGMT_802_1X_NO_WPA: |
| #ifdef CONFIG_WPS |
| case KEY_MGMT_WPS: |
| #endif |
| return IW_AUTH_KEY_MGMT_802_1X; |
| case KEY_MGMT_PSK: |
| return IW_AUTH_KEY_MGMT_PSK; |
| default: |
| return 0; |
| } |
| } |
| |
| static int wpa_driver_tista_get_bssid(void *priv, u8 *bssid) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| return wpa_driver_wext_get_bssid(drv->wext, bssid); |
| } |
| |
| static int wpa_driver_tista_get_ssid(void *priv, u8 *ssid) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| return wpa_driver_wext_get_ssid(drv->wext, ssid); |
| } |
| |
| static int wpa_driver_tista_private_send( void *priv, u32 ioctl_cmd, void *bufIn, u32 sizeIn, void *bufOut, u32 sizeOut ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| ti_private_cmd_t private_cmd; |
| struct iwreq iwr; |
| s32 res; |
| |
| private_cmd.cmd = ioctl_cmd; |
| if(bufOut == NULL) |
| private_cmd.flags = PRIVATE_CMD_SET_FLAG; |
| else |
| private_cmd.flags = PRIVATE_CMD_GET_FLAG; |
| |
| private_cmd.in_buffer = bufIn; |
| private_cmd.in_buffer_len = sizeIn; |
| private_cmd.out_buffer = bufOut; |
| private_cmd.out_buffer_len = sizeOut; |
| |
| os_memset(&iwr, 0, sizeof(iwr)); |
| os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); |
| |
| iwr.u.data.pointer = &private_cmd; |
| iwr.u.data.length = sizeof(ti_private_cmd_t); |
| iwr.u.data.flags = 0; |
| |
| res = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr); |
| if (0 != res) |
| { |
| wpa_printf(MSG_ERROR, "ERROR - wpa_driver_tista_private_send - error sending Wext private IOCTL to STA driver (ioctl_cmd = %x, res = %d, errno = %d)", ioctl_cmd, res, errno); |
| drv->errors++; |
| if (drv->errors > MAX_NUMBER_SEQUENTIAL_ERRORS) { |
| drv->errors = 0; |
| wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); |
| } |
| return -1; |
| } |
| drv->errors = 0; |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_private_send ioctl_cmd = %x res = %d", ioctl_cmd, res); |
| |
| return 0; |
| } |
| |
| static int wpa_driver_tista_driver_start( void *priv ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| u32 uDummyBuf; |
| s32 res; |
| |
| res = wpa_driver_tista_private_send(priv, DRIVER_START_PARAM, &uDummyBuf, sizeof(uDummyBuf), NULL, 0); |
| |
| if (0 != res) { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to start driver!"); |
| wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); |
| } |
| else { |
| os_sleep(0, WPA_DRIVER_WEXT_WAIT_US); /* delay 400 ms */ |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_driver_start success"); |
| } |
| return res; |
| } |
| |
| static int wpa_driver_tista_driver_stop( void *priv ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| u32 uDummyBuf; |
| s32 res; |
| |
| res = wpa_driver_tista_private_send(priv, DRIVER_STOP_PARAM, &uDummyBuf, sizeof(uDummyBuf), NULL, 0); |
| |
| if (0 != res) { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to stop driver!"); |
| wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); |
| } |
| else |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_driver_stop success"); |
| |
| return res; |
| } |
| |
| int wpa_driver_tista_parse_custom(void *ctx, const void *custom) |
| { |
| IPC_EV_DATA * pData = NULL; |
| |
| pData = (IPC_EV_DATA *)custom; |
| wpa_printf(MSG_DEBUG, "uEventType %d", pData->EvParams.uEventType); |
| switch (pData->EvParams.uEventType) { |
| case IPC_EVENT_LINK_SPEED: |
| wpa_printf(MSG_DEBUG, "IPC_EVENT_LINK_SPEED"); |
| if(pData->uBufferSize == sizeof(u32)) |
| { |
| wpa_printf(MSG_DEBUG, "update link_speed"); |
| /* Dm: pStaDrv->link_speed = *((u32 *)pData->uBuffer) / 2; */ |
| } |
| |
| /* Dm: wpa_printf(MSG_INFO,"wpa_supplicant - Link Speed = %u", pStaDrv->link_speed ); */ |
| break; |
| default: |
| wpa_printf(MSG_DEBUG, "Unknown event"); |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static void ti_init_scan_params( scan_Params_t *pScanParams, int scanType, |
| int noOfChan, int scan_probe_flag ) |
| { |
| u8 i,j; |
| int maxDwellTime = 110000; |
| |
| /* init application scan default params */ |
| pScanParams->desiredSsid.len = 0; |
| /* all scan, we will use active scan */ |
| pScanParams->scanType = scanType; |
| if ((scanType == SCAN_TYPE_NORMAL_ACTIVE) && scan_probe_flag) |
| maxDwellTime = 30000; |
| |
| pScanParams->band = RADIO_BAND_2_4_GHZ; |
| pScanParams->probeReqNumber = 3; |
| pScanParams->probeRequestRate = RATE_MASK_UNSPECIFIED; /* Let the FW select */; |
| pScanParams->Tid = 0; |
| pScanParams->numOfChannels = noOfChan; |
| for ( i = 0; i < noOfChan; i++ ) |
| { |
| for ( j = 0; j < 6; j++ ) |
| { |
| pScanParams->channelEntry[ i ].normalChannelEntry.bssId[ j ] = 0xff; |
| } |
| pScanParams->channelEntry[ i ].normalChannelEntry.earlyTerminationEvent = SCAN_ET_COND_DISABLE; |
| pScanParams->channelEntry[ i ].normalChannelEntry.ETMaxNumOfAPframes = 0; |
| pScanParams->channelEntry[ i ].normalChannelEntry.maxChannelDwellTime = maxDwellTime; |
| pScanParams->channelEntry[ i ].normalChannelEntry.minChannelDwellTime = maxDwellTime; |
| pScanParams->channelEntry[ i ].normalChannelEntry.txPowerDbm = DEF_TX_POWER; |
| pScanParams->channelEntry[ i ].normalChannelEntry.channel = i + 1; |
| } |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 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 u8 *ssid, size_t ssid_len ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); |
| struct wpa_ssid *issid; |
| scan_Params_t scanParams; |
| int scan_type, res, timeout, scan_probe_flag = 0; |
| |
| wpa_printf(MSG_DEBUG, "%s", __func__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| |
| #if 1 |
| os_memset(&scanParams, 0, sizeof(scan_Params_t)); |
| /* Initialize scan parameters */ |
| scan_type = drv->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, scan_type, drv->scan_channels, |
| scan_probe_flag); |
| |
| drv->force_merge_flag = 0; /* Set merge flag */ |
| |
| if ((scan_probe_flag && ssid) && |
| (ssid_len > 0 && ssid_len <= sizeof(scanParams.desiredSsid.str))) { |
| os_memcpy(scanParams.desiredSsid.str, ssid, ssid_len); |
| if (ssid_len < sizeof(scanParams.desiredSsid.str)) |
| scanParams.desiredSsid.str[ssid_len] = '\0'; |
| scanParams.desiredSsid.len = ssid_len; |
| drv->force_merge_flag = 1; |
| } |
| |
| drv->last_scan = scan_type; /* Remember scan type for last scan */ |
| |
| res = wpa_driver_tista_private_send(priv, TIWLN_802_11_START_APP_SCAN_SET, &scanParams, sizeof(scanParams), NULL, 0); |
| |
| if (0 != res) { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to do tista scan!"); |
| if (wpa_s->scanning) { |
| res = 0; |
| wpa_printf(MSG_ERROR, "Ongoing Scan action..."); |
| } |
| } else { |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_scan success"); |
| } |
| timeout = 30; |
| wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d sec", |
| res, timeout); |
| eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext, drv->ctx); |
| eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, |
| drv->wext, drv->ctx); |
| return res; |
| #else |
| return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); |
| #endif |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 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 *drv = (struct wpa_driver_ti_data *)priv; |
| u8 mac[ETH_ALEN] = {0}; |
| |
| TI_CHECK_DRIVER( drv->driver_is_loaded, NULL ); |
| if(0 != wpa_driver_tista_private_send(priv, CTRL_DATA_MAC_ADDRESS, NULL, 0, |
| mac, ETH_ALEN)) |
| { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to get mac address!"); |
| os_memset(drv->own_addr, 0, ETH_ALEN); |
| } |
| else |
| { |
| os_memcpy(drv->own_addr, mac, ETH_ALEN); |
| wpa_printf(MSG_DEBUG, "Macaddr = " MACSTR, MAC2STR(drv->own_addr)); |
| } |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_get_mac_addr success"); |
| |
| return (const u8 *)&drv->own_addr; |
| } |
| |
| static int wpa_driver_tista_get_rssi(void *priv, int *rssi_data, int *rssi_beacon) |
| { |
| u8 bssid[ETH_ALEN]; |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| TCuCommon_RoamingStatisticsTable buffer; |
| |
| os_memset(&buffer, 0, sizeof(TCuCommon_RoamingStatisticsTable)); |
| *rssi_data = 0; |
| *rssi_beacon = 0; |
| if (wpa_driver_tista_get_bssid(priv, bssid) == 0 && |
| os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) { |
| if(0 != wpa_driver_tista_private_send(priv, TIWLN_802_11_RSSI, NULL, 0, |
| &buffer, sizeof(TCuCommon_RoamingStatisticsTable))) { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to get rssi level"); |
| return -1; |
| } |
| *rssi_data = (s8)buffer.rssi; |
| *rssi_beacon = (s8)buffer.rssiBeacon; |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_get_rssi data %d beacon %d success", |
| *rssi_data, *rssi_beacon); |
| } |
| else { |
| wpa_printf(MSG_DEBUG, "no WiFi link."); |
| return -1; |
| } |
| return 0; |
| } |
| |
| static int wpa_driver_tista_config_power_management(void *priv, TPowerMgr_PowerMode *mode, u8 is_set) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| |
| if(is_set) /* set power mode */ |
| { |
| if((mode->PowerMode) < POWER_MODE_MAX) |
| { |
| if(0 != wpa_driver_tista_private_send(priv, TIWLN_802_11_POWER_MODE_SET, |
| mode, sizeof(TPowerMgr_PowerMode), NULL, 0)) |
| { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to set power mode"); |
| return -1; |
| } |
| } |
| else |
| { |
| wpa_printf(MSG_ERROR, "ERROR - Invalid Power Mode"); |
| return -1; |
| } |
| } |
| else /* get power mode */ |
| { |
| if(0 != wpa_driver_tista_private_send(priv, TIWLN_802_11_POWER_MODE_GET, NULL, 0, |
| mode, sizeof(TPowerMgr_PowerMode))) |
| { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to get power mode"); |
| return -1; |
| } |
| } |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_config_power_management success"); |
| |
| return 0; |
| } |
| |
| static int wpa_driver_tista_enable_bt_coe(void *priv, u32 mode) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| u32 mode_set = mode; |
| |
| /* Mapping the mode between UI enum and driver enum */ |
| switch(mode_set) |
| { |
| case BLUETOOTH_COEXISTENCE_MODE_ENABLED: |
| mode_set = SG_OPPORTUNISTIC; |
| break; |
| case BLUETOOTH_COEXISTENCE_MODE_SENSE: |
| mode_set = SG_PROTECTIVE; |
| break; |
| case BLUETOOTH_COEXISTENCE_MODE_DISABLED: |
| mode_set = SG_DISABLE; |
| break; |
| default: |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_enable_bt_coe - Unknown Mode"); |
| return -1; |
| break; |
| } |
| |
| if(0 != wpa_driver_tista_private_send(priv, SOFT_GEMINI_SET_ENABLE, |
| &mode_set, sizeof(u32), NULL, 0)) |
| { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to enable BtCoe"); |
| return -1; |
| } |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_enable_bt_coe success"); |
| |
| return 0; |
| } |
| |
| static int wpa_driver_tista_get_bt_coe_status(void *priv, u32 *mode) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| u32 mode_get = 0; |
| |
| if(0 != wpa_driver_tista_private_send(priv, SOFT_GEMINI_GET_CONFIG, NULL, 0, |
| &mode_get, sizeof(u32))) |
| { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to get bt coe status"); |
| return -1; |
| } |
| *mode = mode_get; |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_get_bt_coe_status mode %d success", *mode); |
| |
| return 0; |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 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 TRxDataFilterRequest structure |
| Return Value: 0 - success, -1 - error |
| -----------------------------------------------------------------------------*/ |
| static int prepare_filter_struct( void *priv, int type, |
| TRxDataFilterRequest *dfreq_ptr ) |
| { |
| const u8 *macaddr = NULL; |
| size_t len = 0; |
| u8 mask; |
| int ret = -1; |
| |
| wpa_printf(MSG_DEBUG, "filter type=%d", type); |
| switch (type) { |
| case RX_SELF_FILTER: |
| macaddr = wpa_driver_tista_get_mac_addr(priv); |
| len = MAC_ADDR_LEN; |
| mask = 0x3F; /* 6 bytes */ |
| break; |
| case RX_BROADCAST_FILTER: |
| macaddr = (const u8 *)"\xFF\xFF\xFF\xFF\xFF\xFF"; |
| len = MAC_ADDR_LEN; |
| mask = 0x3F; /* 6 bytes */ |
| break; |
| case RX_IPV4_MULTICAST_FILTER: |
| macaddr = (const u8 *)"\x01\x00\x5E"; |
| len = 3; |
| mask = 0x7; /* 3 bytes */ |
| break; |
| case RX_IPV6_MULTICAST_FILTER: |
| macaddr = (const u8 *)"\x33\x33"; |
| len = 2; |
| mask = 0x3; /* 2 bytes */ |
| break; |
| } |
| |
| if (macaddr != NULL) { |
| dfreq_ptr->offset = 0; |
| dfreq_ptr->maskLength = 1; |
| dfreq_ptr->mask[0] = mask; |
| dfreq_ptr->patternLength = len; |
| os_memcpy( dfreq_ptr->pattern, macaddr, MAC_ADDR_LEN ); |
| ret = 0; |
| } |
| return ret; |
| } |
| |
| static int wpa_driver_tista_driver_rx_data_filter( void *priv, TRxDataFilterRequest *dfreq_ptr, u8 is_add ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| int cmd, res; |
| |
| if (is_add) { /* add rx data filter */ |
| cmd = TIWLN_ADD_RX_DATA_FILTER; |
| wpa_printf(MSG_DEBUG, "Add RX data filter"); |
| } |
| else { /* remove rx data filter */ |
| cmd = TIWLN_REMOVE_RX_DATA_FILTER; |
| wpa_printf(MSG_DEBUG, "Remove RX data filter"); |
| } |
| |
| res = wpa_driver_tista_private_send(priv, cmd, dfreq_ptr, sizeof(TRxDataFilterRequest), NULL, 0); |
| if (0 != res) |
| wpa_printf(MSG_ERROR, "ERROR - Failed to handle rx data filter command!"); |
| else |
| wpa_printf(MSG_DEBUG, "%s success", __func__); |
| return res; |
| } |
| |
| static int wpa_driver_tista_driver_enable_rx_data_filter( void *priv ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| u32 val = TRUE; |
| int res; |
| |
| res = wpa_driver_tista_private_send(priv, TIWLN_ENABLE_DISABLE_RX_DATA_FILTERS, |
| &val, sizeof(u32), NULL, 0); |
| if (0 != res) |
| wpa_printf(MSG_ERROR, "ERROR - Failed to enable RX data filter!"); |
| else |
| wpa_printf(MSG_DEBUG, "%s success", __func__); |
| return res; |
| } |
| |
| static int wpa_driver_tista_driver_disable_rx_data_filter( void *priv ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| u32 val = FALSE; |
| int res; |
| |
| res = wpa_driver_tista_private_send(priv, TIWLN_ENABLE_DISABLE_RX_DATA_FILTERS, |
| &val, sizeof(u32), NULL, 0); |
| if (0 != res) |
| wpa_printf(MSG_ERROR, "ERROR - Failed to disable RX data filter!"); |
| else |
| wpa_printf(MSG_DEBUG, "%s success", __func__); |
| return res; |
| } |
| |
| static int wpa_driver_tista_driver_rx_data_filter_statistics( void *priv, |
| TCuCommon_RxDataFilteringStatistics *stats ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| int res; |
| |
| res = wpa_driver_tista_private_send(priv, TIWLN_GET_RX_DATA_FILTERS_STATISTICS, |
| NULL, 0, stats, sizeof(TCuCommon_RxDataFilteringStatistics)); |
| if (0 != res) |
| wpa_printf(MSG_ERROR, "ERROR - Failed to get RX data filter statistics!"); |
| else |
| wpa_printf(MSG_DEBUG, "%s success", __func__); |
| return res; |
| } |
| |
| static int get_num_of_channels(char *country) |
| { |
| int channels = NUMBER_SCAN_CHANNELS_FCC; |
| |
| if (os_strcasecmp(country, "EU")) |
| channels = NUMBER_SCAN_CHANNELS_ETSI; |
| else if (os_strcasecmp(country, "JP")) |
| channels = NUMBER_SCAN_CHANNELS_MKK1; |
| return channels; |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 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 |
| -----------------------------------------------------------------------------*/ |
| static int wpa_driver_tista_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len ) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| int ret = -1, prev_events, flags; |
| |
| wpa_printf(MSG_DEBUG, "%s %s", __func__, cmd); |
| |
| if( os_strcasecmp(cmd, "start") == 0 ) { |
| wpa_printf(MSG_DEBUG,"Start command"); |
| ret = wpa_driver_tista_driver_start(priv); |
| if( ret == 0 ) { |
| drv->driver_is_loaded = TRUE; |
| wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); |
| } |
| return( TI2WPA_STATUS(ret) ); |
| } |
| |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| |
| if( os_strcasecmp(cmd, "stop") == 0 ) { |
| wpa_printf(MSG_DEBUG,"Stop command"); |
| if ((wpa_driver_wext_get_ifflags(drv->wext, &flags) == 0) && |
| (flags & IFF_UP)) { |
| wpa_printf(MSG_ERROR, "TI: %s when iface is UP", cmd); |
| wpa_driver_wext_set_ifflags(drv->wext, flags & ~IFF_UP); |
| } |
| ret = wpa_driver_tista_driver_stop(priv); |
| if( ret == 0 ) { |
| scan_exit(drv); /* Clear scan cache */ |
| drv->driver_is_loaded = FALSE; |
| wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); |
| } |
| } |
| if( os_strcasecmp(cmd, "reload") == 0 ) { |
| wpa_printf(MSG_DEBUG,"Reload command"); |
| ret = 0; |
| wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); |
| } |
| else if( os_strcasecmp(cmd, "macaddr") == 0 ) { |
| wpa_driver_tista_get_mac_addr(priv); |
| wpa_printf(MSG_DEBUG, "Macaddr command"); |
| ret = sprintf(buf, "Macaddr = " MACSTR "\n", MAC2STR(drv->own_addr)); |
| wpa_printf(MSG_DEBUG, "buf %s", buf); |
| } |
| else if( os_strcasecmp(cmd, "scan-passive") == 0 ) { |
| wpa_printf(MSG_DEBUG,"Scan Passive command"); |
| drv->scan_type = SCAN_TYPE_NORMAL_PASSIVE; |
| ret = 0; |
| } |
| else if( os_strcasecmp(cmd, "scan-active") == 0 ) { |
| wpa_printf(MSG_DEBUG,"Scan Active command"); |
| drv->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", drv->scan_type); |
| if (ret < (int)buf_len) { |
| return( ret ); |
| } |
| } |
| else if( os_strcasecmp(cmd, "linkspeed") == 0 ) { |
| struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); |
| |
| wpa_printf(MSG_DEBUG,"Link Speed command"); |
| drv->link_speed = wpa_s->link_speed / 1000000; |
| ret = sprintf(buf,"LinkSpeed %u\n", drv->link_speed); |
| wpa_printf(MSG_DEBUG, "buf %s", buf); |
| } |
| else if( os_strncasecmp(cmd, "country", 7) == 0 ) { |
| drv->scan_channels = get_num_of_channels(cmd + 8); |
| ret = sprintf(buf,"Scan-Channels = %d\n", drv->scan_channels); |
| wpa_printf(MSG_DEBUG, "buf %s", buf); |
| } |
| else if( os_strncasecmp(cmd, "scan-channels", 13) == 0 ) { |
| int noOfChan; |
| |
| noOfChan = atoi(cmd + 13); |
| wpa_printf(MSG_DEBUG,"Scan Channels command = %d", noOfChan); |
| if( (noOfChan > 0) && (noOfChan <= MAX_NUMBER_OF_CHANNELS_PER_SCAN) ) |
| drv->scan_channels = noOfChan; |
| ret = sprintf(buf,"Scan-Channels = %d\n", drv->scan_channels); |
| wpa_printf(MSG_DEBUG, "buf %s", buf); |
| } |
| else if( os_strcasecmp(cmd, "rssi-approx") == 0 ) { |
| scan_result_t *cur_res; |
| struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); |
| scan_ssid_t *p_ssid; |
| int rssi, len; |
| |
| wpa_printf(MSG_DEBUG,"rssi-approx command"); |
| |
| if( !wpa_s ) |
| return( ret ); |
| cur_res = scan_get_by_bssid(drv, wpa_s->bssid); |
| if( cur_res ) { |
| p_ssid = scan_get_ssid(cur_res); |
| len = (int)(p_ssid->ssid_len); |
| rssi = cur_res->level; |
| if( (len > 0) && (len <= MAX_SSID_LEN) && (len < (int)buf_len)) { |
| os_memcpy((void *)buf, (void *)(p_ssid->ssid), len); |
| ret = len; |
| ret += snprintf(&buf[ret], buf_len-len, " rssi %d\n", rssi); |
| } |
| } |
| } |
| else if( os_strcasecmp(cmd, "rssi") == 0 ) { |
| u8 ssid[MAX_SSID_LEN]; |
| scan_result_t *cur_res; |
| struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); |
| int rssi_data, rssi_beacon, len; |
| |
| wpa_printf(MSG_DEBUG,"rssi command"); |
| |
| ret = wpa_driver_tista_get_rssi(priv, &rssi_data, &rssi_beacon); |
| if( ret == 0 ) { |
| len = wpa_driver_tista_get_ssid(priv, (u8 *)ssid); |
| wpa_printf(MSG_DEBUG,"rssi_data %d rssi_beacon %d", rssi_data, rssi_beacon); |
| if( (len > 0) && (len <= MAX_SSID_LEN) ) { |
| os_memcpy((void *)buf, (void *)ssid, len); |
| ret = len; |
| ret += sprintf(&buf[ret], " rssi %d\n", rssi_beacon); |
| wpa_printf(MSG_DEBUG, "buf %s", buf); |
| /* Update cached value */ |
| if( !wpa_s ) |
| return( ret ); |
| cur_res = scan_get_by_bssid(drv, wpa_s->bssid); |
| if( cur_res ) |
| cur_res->level = rssi_beacon; |
| } |
| else |
| { |
| wpa_printf(MSG_DEBUG, "Fail to get ssid when reporting rssi"); |
| ret = -1; |
| } |
| } |
| } |
| else if( os_strncasecmp(cmd, "powermode", 9) == 0 ) { |
| u32 mode; |
| TPowerMgr_PowerMode tMode; |
| |
| mode = (u32)atoi(cmd + 9); |
| wpa_printf(MSG_DEBUG,"Power Mode command = %u", mode); |
| if( mode < POWER_MODE_MAX ) |
| { |
| tMode.PowerMode = (PowerMgr_PowerMode_e)mode; |
| tMode.PowerMngPriority = POWER_MANAGER_USER_PRIORITY; |
| ret = wpa_driver_tista_config_power_management( priv, &tMode, 1 ); |
| } |
| } |
| else if (os_strncasecmp(cmd, "getpower", 8) == 0 ) { |
| u32 mode; |
| TPowerMgr_PowerMode tMode; |
| |
| os_memset(&tMode, 0, sizeof(TPowerMgr_PowerMode)); |
| ret = wpa_driver_tista_config_power_management( priv, &tMode, 0 ); |
| if( ret == 0 ) { |
| ret = sprintf(buf, "powermode = %u\n", tMode.PowerMode); |
| wpa_printf(MSG_DEBUG, "buf %s", buf); |
| } |
| } |
| else if( os_strncasecmp(cmd, "btcoexmode", 10) == 0 ) { |
| u32 mode; |
| |
| mode = (u32)atoi(cmd + 10); |
| wpa_printf(MSG_DEBUG,"BtCoex Mode command = %u", mode); |
| ret = wpa_driver_tista_enable_bt_coe( priv, mode ); |
| if( ret == 0 ) { |
| drv->btcoex_mode = mode; |
| } |
| } |
| else if( os_strcasecmp(cmd, "btcoexstat") == 0 ) { |
| u32 status = drv->btcoex_mode; |
| |
| wpa_printf(MSG_DEBUG,"BtCoex Status"); |
| ret = wpa_driver_tista_get_bt_coe_status( priv, &status ); |
| if( ret == 0 ) { |
| ret = sprintf(buf, "btcoexstatus = 0x%x\n", status); |
| wpa_printf(MSG_DEBUG, "buf %s", buf); |
| } |
| } |
| else if( os_strcasecmp(cmd, "rxfilter-start") == 0 ) { |
| wpa_printf(MSG_DEBUG,"Rx Data Filter Start command"); |
| ret = wpa_driver_tista_driver_enable_rx_data_filter( priv ); |
| } |
| else if( os_strcasecmp(cmd, "rxfilter-stop") == 0 ) { |
| wpa_printf(MSG_DEBUG,"Rx Data Filter Stop command"); |
| ret = wpa_driver_tista_driver_disable_rx_data_filter( priv ); |
| } |
| else if( os_strcasecmp(cmd, "rxfilter-statistics") == 0 ) { |
| TCuCommon_RxDataFilteringStatistics stats; |
| int len, i; |
| |
| os_memset(&stats, 0, sizeof(TCuCommon_RxDataFilteringStatistics)); |
| wpa_printf(MSG_DEBUG,"Rx Data Filter Statistics command"); |
| ret = wpa_driver_tista_driver_rx_data_filter_statistics( priv, &stats ); |
| if( ret == 0 ) { |
| ret = snprintf(buf, buf_len, "RxFilterStat: %u", (u32)stats.unmatchedPacketsCount); |
| for(i=0;( i < MAX_DATA_FILTERS );i++) { |
| ret += snprintf(&buf[ret], buf_len-ret, " %u", (u32)stats.matchedPacketsCount[i]); |
| } |
| ret += snprintf(&buf[ret], buf_len-ret, "\n"); |
| if (ret >= (int)buf_len) { |
| ret = -1; |
| } |
| } |
| } |
| else if( os_strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { |
| TRxDataFilterRequest 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 = wpa_driver_tista_driver_rx_data_filter( priv, &dfreq, 1 ); |
| } |
| } |
| } |
| } |
| else if( os_strncasecmp(cmd, "rxfilter-remove",15) == 0 ) { |
| TRxDataFilterRequest 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 = wpa_driver_tista_driver_rx_data_filter( priv, &dfreq, 0 ); |
| } |
| } |
| } |
| } |
| else { |
| wpa_printf(MSG_DEBUG,"Unsupported command"); |
| } |
| return ret; |
| } |
| |
| #ifdef WPA_SUPPLICANT_VER_0_6_X |
| /*----------------------------------------------------------------------------- |
| Routine Name: wpa_driver_tista_set_probe_req_ie |
| Routine Description: set probe request ie for WSC mode change |
| Arguments: |
| priv - pointer to private data structure |
| ies - probe_req_ie data |
| ies_len - ie data length |
| Return Value: actual buffer length - success, -1 - failure |
| -----------------------------------------------------------------------------*/ |
| static int wpa_driver_tista_set_probe_req_ie(void *priv, const u8* ies, size_t ies_len) |
| { |
| struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; |
| #ifdef CONFIG_WPS |
| TWscMode WscModeStruct; |
| |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| |
| if ((!ies || (0 == ies_len)) && (NULL == drv->probe_req_ie)) { |
| return 0; |
| } |
| |
| if (ies && drv->probe_req_ie) { |
| size_t len = wpabuf_len(drv->probe_req_ie); |
| u8* data = (u8*)wpabuf_head(drv->probe_req_ie); |
| if ((ies_len == len) && (0 == os_memcmp(ies, data, ies_len))) { |
| return 0; |
| } |
| } |
| |
| os_memset(&WscModeStruct, 0, sizeof(TWscMode)); |
| |
| if (!ies || (0 == ies_len)) { |
| WscModeStruct.WSCMode = TIWLN_SIMPLE_CONFIG_OFF; |
| } else { |
| const size_t head_len = 6; /* probeReqIe head: dd xx 00 50 f2 04 */ |
| u8 *pos, *end; |
| u16 password_id = 0; |
| size_t min_len = 0; |
| |
| pos = (u8*)ies + head_len; /* Find the WSC mode in probe_req_ie by password_id */ |
| end = (u8*)ies + ies_len; |
| while (pos < end) { |
| if (ATTR_DEV_PASSWORD_ID == WPA_GET_BE16(pos)) { |
| password_id = WPA_GET_BE16(pos+4); |
| break; |
| } |
| pos += (4 + WPA_GET_BE16(pos+2)); |
| } |
| WscModeStruct.WSCMode = (DEV_PW_PUSHBUTTON == password_id)?TIWLN_SIMPLE_CONFIG_PBC_METHOD:TIWLN_SIMPLE_CONFIG_PIN_METHOD; |
| |
| pos = (u8*)ies + head_len; |
| min_len = ies_len - head_len; |
| if (min_len > sizeof(WscModeStruct.probeReqWSCIE)) { |
| min_len = sizeof(WscModeStruct.probeReqWSCIE); |
| } |
| os_memcpy(WscModeStruct.probeReqWSCIE, pos, min_len); |
| } |
| |
| wpa_hexdump(MSG_DEBUG, "SetProbeReqIe:WscModeStruct", (u8*)&WscModeStruct, sizeof(TWscMode)); |
| if(0 == wpa_driver_tista_private_send(priv, SITE_MGR_SIMPLE_CONFIG_MODE, (void*)&WscModeStruct, sizeof(TWscMode), NULL, 0)) { |
| /* Update the cached probe req ie */ |
| wpabuf_free(drv->probe_req_ie); |
| drv->probe_req_ie = NULL; |
| |
| if (ies && ies_len) { |
| drv->probe_req_ie = wpabuf_alloc(sizeof(WscModeStruct.probeReqWSCIE)); |
| if (drv->probe_req_ie) { |
| wpabuf_put_data(drv->probe_req_ie, ies, ies_len); |
| } |
| } |
| } else { |
| wpa_printf(MSG_ERROR, "ERROR - Failed to set wsc mode!"); |
| return -1; |
| } |
| #endif |
| return 0; |
| } |
| #endif |
| |
| /** |
| * wpa_driver_tista_init - Initialize WE driver interface |
| * @ctx: context to be used when calling wpa_supplicant functions, |
| * e.g., wpa_supplicant_event() |
| * @ifname: interface name, e.g., wlan0 |
| * Returns: Pointer to private data, %NULL on failure |
| */ |
| void * wpa_driver_tista_init(void *ctx, const char *ifname) |
| { |
| struct wpa_driver_ti_data *drv; |
| |
| drv = os_zalloc(sizeof(*drv)); |
| if (drv == NULL) |
| return NULL; |
| drv->wext = wpa_driver_wext_init(ctx, ifname); |
| if (drv->wext == NULL) { |
| os_free(drv); |
| return NULL; |
| } |
| |
| drv->ctx = ctx; |
| os_strncpy(drv->ifname, ifname, sizeof(drv->ifname)); |
| drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); |
| if (drv->ioctl_sock < 0) { |
| perror("socket"); |
| wpa_driver_wext_deinit(drv->wext); |
| os_free(drv); |
| return NULL; |
| } |
| |
| /* Signal that driver is not stopped */ |
| drv->driver_is_loaded = TRUE; |
| |
| /* Set default scan type */ |
| drv->scan_type = SCAN_TYPE_NORMAL_ACTIVE; |
| drv->force_merge_flag = 0; |
| scan_init(drv); |
| |
| /* Set default amount of channels */ |
| drv->scan_channels = check_and_get_build_channels(); |
| |
| /* Link Speed will be set by the message from the driver */ |
| drv->link_speed = 0; |
| |
| /* BtCoex mode is read from tiwlan.ini file */ |
| drv->btcoex_mode = 0; /* SG_DISABLE */ |
| |
| #ifdef CONFIG_WPS |
| /* The latest probe_req_ie for WSC */ |
| drv->probe_req_ie = NULL; |
| #endif |
| |
| /* Number of sequential errors */ |
| drv->errors = 0; |
| return drv; |
| } |
| |
| /** |
| * wpa_driver_tista_deinit - Deinitialize WE driver interface |
| * @priv: Pointer to private wext data from wpa_driver_tista_init() |
| * |
| * Shut down driver interface and processing of driver events. Free |
| * private data buffer if one was allocated in wpa_driver_tista_init(). |
| */ |
| void wpa_driver_tista_deinit(void *priv) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| |
| wpa_driver_wext_deinit(drv->wext); |
| close(drv->ioctl_sock); |
| scan_exit(drv); |
| #ifdef CONFIG_WPS |
| wpabuf_free(drv->probe_req_ie); |
| drv->probe_req_ie = NULL; |
| #endif |
| os_free(drv); |
| } |
| |
| static int wpa_driver_tista_set_auth_param(struct wpa_driver_ti_data *drv, |
| int idx, u32 value) |
| { |
| struct iwreq iwr; |
| int ret = 0; |
| |
| os_memset(&iwr, 0, sizeof(iwr)); |
| os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); |
| iwr.u.param.flags = idx & IW_AUTH_INDEX; |
| iwr.u.param.value = value; |
| |
| if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { |
| perror("ioctl[SIOCSIWAUTH]"); |
| wpa_printf(MSG_ERROR, "WEXT auth param %d value 0x%x - ", |
| idx, value); |
| ret = errno == EOPNOTSUPP ? -2 : -1; |
| } |
| |
| return ret; |
| } |
| |
| static int wpa_driver_tista_set_wpa(void *priv, int enabled) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_tista_set_auth_param(drv, IW_AUTH_WPA_ENABLED, |
| enabled); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_set_auth_alg(void *priv, int auth_alg) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int algs = 0, res; |
| |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| if (auth_alg & AUTH_ALG_OPEN_SYSTEM) |
| algs |= IW_AUTH_ALG_OPEN_SYSTEM; |
| if (auth_alg & AUTH_ALG_SHARED_KEY) |
| algs |= IW_AUTH_ALG_SHARED_KEY; |
| if (auth_alg & AUTH_ALG_LEAP) |
| algs |= IW_AUTH_ALG_LEAP; |
| if (algs == 0) { |
| /* at least one algorithm should be set */ |
| algs = IW_AUTH_ALG_OPEN_SYSTEM; |
| } |
| |
| res = wpa_driver_tista_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, |
| algs); |
| |
| return res; |
| } |
| |
| static int wpa_driver_tista_set_countermeasures(void *priv, int enabled) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_tista_set_auth_param(drv, |
| IW_AUTH_TKIP_COUNTERMEASURES, |
| enabled); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_set_drop_unencrypted(void *priv, |
| int enabled) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| /* Dm: drv->use_crypt = enabled; */ |
| ret = wpa_driver_tista_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, |
| enabled); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_pmksa(struct wpa_driver_ti_data *drv, |
| u32 cmd, const u8 *bssid, const u8 *pmkid) |
| { |
| struct iwreq iwr; |
| struct iw_pmksa pmksa; |
| int ret = 0; |
| |
| os_memset(&iwr, 0, sizeof(iwr)); |
| os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); |
| os_memset(&pmksa, 0, sizeof(pmksa)); |
| pmksa.cmd = cmd; |
| pmksa.bssid.sa_family = ARPHRD_ETHER; |
| if (bssid) |
| os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); |
| if (pmkid) { |
| os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); |
| wpa_printf(MSG_DEBUG, "pmkid %s", pmkid); |
| } |
| iwr.u.data.pointer = (caddr_t)&pmksa; |
| iwr.u.data.length = sizeof(pmksa); |
| |
| if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { |
| if (errno != EOPNOTSUPP) |
| perror("ioctl[SIOCSIWPMKSA]"); |
| ret = -1; |
| } |
| return ret; |
| } |
| |
| static int wpa_driver_tista_add_pmkid(void *priv, const u8 *bssid, |
| const u8 *pmkid) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_tista_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_remove_pmkid(void *priv, const u8 *bssid, |
| const u8 *pmkid) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_tista_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_flush_pmkid(void *priv) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_tista_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_mlme(struct wpa_driver_ti_data *drv, |
| const u8 *addr, int cmd, int reason_code) |
| { |
| struct iwreq iwr; |
| struct iw_mlme mlme; |
| int ret = 0; |
| |
| os_memset(&iwr, 0, sizeof(iwr)); |
| os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); |
| os_memset(&mlme, 0, sizeof(mlme)); |
| mlme.cmd = cmd; |
| mlme.reason_code = reason_code; |
| mlme.addr.sa_family = ARPHRD_ETHER; |
| os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); |
| iwr.u.data.pointer = (caddr_t) &mlme; |
| iwr.u.data.length = sizeof(mlme); |
| |
| if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { |
| perror("ioctl[SIOCSIWMLME]"); |
| ret = -1; |
| } |
| |
| return ret; |
| } |
| |
| static int wpa_driver_tista_deauthenticate(void *priv, const u8 *addr, |
| int reason_code) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_tista_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); |
| return ret; |
| } |
| |
| |
| static int wpa_driver_tista_disassociate(void *priv, const u8 *addr, |
| int reason_code) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_tista_mlme(drv, addr, IW_MLME_DISASSOC, reason_code); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_set_key(void *priv, wpa_alg alg, |
| const u8 *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 *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __func__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_wext_set_key(drv->wext, alg, addr, key_idx, set_tx, |
| seq, seq_len, key, key_len); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_set_gen_ie(void *priv, const u8 *ie, size_t ie_len) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| struct iwreq iwr; |
| int ret = 0; |
| |
| os_memset(&iwr, 0, sizeof(iwr)); |
| os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); |
| iwr.u.data.pointer = (caddr_t)ie; |
| iwr.u.data.length = ie_len; |
| |
| if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { |
| perror("ioctl[SIOCSIWGENIE]"); |
| ret = -1; |
| } |
| |
| return ret; |
| } |
| |
| #ifdef WPA_SUPPLICANT_VER_0_6_X |
| static struct wpa_scan_results *wpa_driver_tista_get_scan_results(void *priv) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| struct wpa_scan_results *res; |
| struct wpa_scan_res **tmp; |
| unsigned ap_num; |
| |
| TI_CHECK_DRIVER( drv->driver_is_loaded, NULL ); |
| res = wpa_driver_wext_get_scan_results(drv->wext); |
| if (res == NULL) { |
| return NULL; |
| } |
| |
| wpa_printf(MSG_DEBUG, "Actual APs number %d", res->num); |
| ap_num = (unsigned)scan_count(drv) + res->num; |
| tmp = os_realloc(res->res, ap_num * sizeof(struct wpa_scan_res *)); |
| if (tmp == NULL) |
| return res; |
| res->num = scan_merge(drv, tmp, drv->force_merge_flag, res->num, ap_num); |
| wpa_printf(MSG_DEBUG, "After merge, APs number %d", res->num); |
| tmp = os_realloc(tmp, res->num * sizeof(struct wpa_scan_res *)); |
| res->res = tmp; |
| return res; |
| } |
| |
| int wpa_driver_tista_set_mode(void *priv, int mode) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ret; |
| |
| wpa_printf(MSG_DEBUG, "%s", __func__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ret = wpa_driver_wext_set_mode(drv->wext, mode); |
| return ret; |
| } |
| #else |
| /*----------------------------------------------------------------------------- |
| 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 ); |
| } |
| |
| static int wpa_driver_tista_get_scan_results(void *priv, |
| struct wpa_scan_result *results, |
| size_t max_size) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int ap_num = 0; |
| |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| ap_num = wpa_driver_wext_get_scan_results(drv->wext, results, max_size); |
| wpa_printf(MSG_DEBUG, "Actual APs number %d", ap_num); |
| |
| if (ap_num < 0) |
| return -1; |
| |
| /* Merge new results with previous */ |
| ap_num = scan_merge(drv, results, drv->force_merge_flag, ap_num, max_size); |
| wpa_printf(MSG_DEBUG, "After merge, APs number %d", ap_num); |
| qsort(results, ap_num, sizeof(struct wpa_scan_result), |
| wpa_driver_tista_scan_result_compare); |
| return ap_num; |
| } |
| #endif |
| |
| static int wpa_driver_tista_associate(void *priv, |
| struct wpa_driver_associate_params *params) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| int allow_unencrypted_eapol; |
| int value, flags, ret = 0; |
| |
| wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| |
| #ifdef WPA_SUPPLICANT_VER_0_6_X |
| #ifdef ANDROID |
| ((struct wpa_driver_wext_data *)(drv->wext))->skip_disconnect = 0; |
| #endif |
| #endif |
| |
| if (wpa_driver_wext_get_ifflags(drv->wext, &flags) == 0) { |
| if (!(flags & IFF_UP)) { |
| wpa_driver_wext_set_ifflags(drv->wext, flags | IFF_UP); |
| } |
| } |
| |
| #if 0 |
| if (!params->bssid) |
| wpa_driver_wext_set_bssid(drv->wext, NULL); |
| #endif |
| |
| #ifdef WPA_SUPPLICANT_VER_0_5_X |
| /* Set driver network mode (Adhoc/Infrastructure) according to supplied parameters */ |
| wpa_driver_wext_set_mode(drv->wext, params->mode); |
| #endif |
| wpa_driver_tista_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len); |
| |
| if (params->wpa_ie == NULL || params->wpa_ie_len == 0) |
| value = IW_AUTH_WPA_VERSION_DISABLED; |
| #ifdef WPA_SUPPLICANT_VER_0_6_X |
| else if (params->wpa_ie[0] == WLAN_EID_RSN) |
| #else |
| else if (params->wpa_ie[0] == RSN_INFO_ELEM) |
| #endif |
| value = IW_AUTH_WPA_VERSION_WPA2; |
| #ifdef CONFIG_WPS |
| else if (params->key_mgmt_suite == KEY_MGMT_WPS) |
| value = IW_AUTH_WPA_VERSION_DISABLED; |
| #endif |
| else |
| value = IW_AUTH_WPA_VERSION_WPA; |
| wpa_driver_tista_set_auth_param(drv, IW_AUTH_WPA_VERSION, value); |
| value = wpa_driver_tista_cipher2wext(params->pairwise_suite); |
| wpa_driver_tista_set_auth_param(drv, IW_AUTH_CIPHER_PAIRWISE, value); |
| value = wpa_driver_tista_cipher2wext(params->group_suite); |
| wpa_driver_tista_set_auth_param(drv, IW_AUTH_CIPHER_GROUP, value); |
| value = wpa_driver_tista_keymgmt2wext(params->key_mgmt_suite); |
| wpa_driver_tista_set_auth_param(drv, IW_AUTH_KEY_MGMT, value); |
| value = params->key_mgmt_suite != KEY_MGMT_NONE || |
| params->pairwise_suite != CIPHER_NONE || |
| params->group_suite != CIPHER_NONE || |
| #ifdef WPA_SUPPLICANT_VER_0_6_X |
| (params->wpa_ie_len && (params->key_mgmt_suite != KEY_MGMT_WPS)); |
| #else |
| params->wpa_ie_len; |
| #endif |
| wpa_driver_tista_set_auth_param(drv, IW_AUTH_PRIVACY_INVOKED, value); |
| |
| /* Allow unencrypted EAPOL messages even if pairwise keys are set when |
| * not using WPA. IEEE 802.1X specifies that these frames are not |
| * encrypted, but WPA encrypts them when pairwise keys are in use. */ |
| if (params->key_mgmt_suite == KEY_MGMT_802_1X || |
| params->key_mgmt_suite == KEY_MGMT_PSK) |
| allow_unencrypted_eapol = 0; |
| else |
| allow_unencrypted_eapol = 1; |
| |
| wpa_driver_tista_set_auth_param(drv, |
| IW_AUTH_RX_UNENCRYPTED_EAPOL, |
| allow_unencrypted_eapol); |
| |
| if (params->freq) |
| wpa_driver_wext_set_freq(drv->wext, params->freq); |
| |
| if (params->bssid) { |
| wpa_printf(MSG_DEBUG, "wpa_driver_tista_associate: 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) { |
| wpa_driver_wext_set_bssid(drv->wext, params->bssid); |
| } |
| } |
| ret = wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len); |
| return ret; |
| } |
| |
| static int wpa_driver_tista_set_operstate(void *priv, int state) |
| { |
| struct wpa_driver_ti_data *drv = priv; |
| |
| wpa_printf(MSG_DEBUG, "%s: operstate %d (%s)", |
| __func__, /*drv->operstate,*/ state, state ? "UP" : "DORMANT"); |
| TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); |
| /* Dm: drv->operstate = state; */ |
| return wpa_driver_wext_set_operstate(drv->wext, state); |
| } |
| |
| const struct wpa_driver_ops wpa_driver_custom_ops = { |
| .name = TIWLAN_DRV_NAME, |
| .desc = "TI Station Driver (1271)", |
| .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_countermeasures = wpa_driver_tista_set_countermeasures, |
| .set_drop_unencrypted = wpa_driver_tista_set_drop_unencrypted, |
| .scan = wpa_driver_tista_scan, |
| #ifdef WPA_SUPPLICANT_VER_0_6_X |
| .get_scan_results2 = wpa_driver_tista_get_scan_results, |
| .combo_scan = NULL, |
| #else |
| .get_scan_results = wpa_driver_tista_get_scan_results, |
| #endif |
| .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, |
| .init = wpa_driver_tista_init, |
| .deinit = wpa_driver_tista_deinit, |
| .add_pmkid = wpa_driver_tista_add_pmkid, |
| .remove_pmkid = wpa_driver_tista_remove_pmkid, |
| .flush_pmkid = wpa_driver_tista_flush_pmkid, |
| .set_operstate = wpa_driver_tista_set_operstate, |
| #ifdef WPA_SUPPLICANT_VER_0_6_X |
| .set_mode = wpa_driver_tista_set_mode, |
| .set_probe_req_ie = wpa_driver_tista_set_probe_req_ie, |
| #endif |
| .driver_cmd = wpa_driver_tista_driver_cmd |
| }; |