/**************************************************************************** * drivers/wireless/cc3000/wlan.c - CC3000 Host Driver Implementation. * * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT * OWNER 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. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "cc3000.h" #include "cc3000drv.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define SMART_CONFIG_PROFILE_SIZE 67 /* 67 = 32 (max ssid) + 32 (max key) + * 1 (SSID length) + 1 (security type) + * 1 (key length) */ /* SOCKET_SELECT_PARAMS_LEN + SPI_HEADER_SIZE++SIMPLE_LINK_HCI_DATA_HEADER_SIZ */ #define MAX_HCI_CMD_LENGTH (44+SIMPLE_LINK_HCI_DATA_HEADER_SIZE+SPI_HEADER_SIZE) /* Patches type */ #define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01 #define PATCHES_HOST_TYPE_WLAN_FW 0x02 #define PATCHES_HOST_TYPE_BOOTLOADER 0x03 #define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16) #define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3) #define ETH_ALEN (6) #define MAXIMAL_SSID_LENGTH (32) #define SL_PATCHES_REQUEST_DEFAULT (0) #define SL_PATCHES_REQUEST_FORCE_HOST (1) #define SL_PATCHES_REQUEST_FORCE_NONE (2) #define WLAN_SEC_UNSEC (0) #define WLAN_SEC_WEP (1) #define WLAN_SEC_WPA (2) #define WLAN_SEC_WPA2 (3) #define WLAN_SL_INIT_START_PARAMS_LEN (1) #define WLAN_PATCH_PARAMS_LENGTH (8) #define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12) #define WLAN_DEL_PROFILE_PARAMS_LEN (4) #define WLAN_SET_MASK_PARAMS_LEN (4) #define WLAN_SET_SCAN_PARAMS_LEN (100) #define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4) #define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24) #define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36) #define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44) #define WLAN_CONNECT_PARAM_LEN (29) #define WLAN_SMART_CONFIG_START_PARAMS_LEN (4) /**************************************************************************** * Private Data ****************************************************************************/ /**************************************************************************** * Public Data ****************************************************************************/ volatile sSimplLinkInformation tSLInformation; #ifndef CC3000_UNENCRYPTED_SMART_CONFIG uint8_t akey[AES128_KEY_SIZE]; uint8_t profileArray[SMART_CONFIG_PROFILE_SIZE]; #endif /* CC3000_UNENCRYPTED_SMART_CONFIG */ /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: SimpleLink_Init_Start * * Input Parameters: * usPatchesAvailableAtHost flag to indicate if patches available * from host or from EEPROM. Due to the * fact the patches are burn to the EEPROM * using the patch programmer utility, the * patches will be available from the EEPROM * and not from the host. * * Returned Value: * None * * Description: * Send HCI_CMND_SIMPLE_LINK_START to CC3000 * ****************************************************************************/ static void SimpleLink_Init_Start(uint16_t usPatchesAvailableAtHost) { uint8_t *ptr; uint8_t *args; ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); if (usPatchesAvailableAtHost <= SL_PATCHES_REQUEST_DEFAULT || usPatchesAvailableAtHost > SL_PATCHES_REQUEST_FORCE_NONE) { usPatchesAvailableAtHost = SL_PATCHES_REQUEST_DEFAULT; } UINT8_TO_STREAM(args, usPatchesAvailableAtHost); /* IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000 */ hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN); SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0); } /**************************************************************************** * Name: wlan_init * * Input Parameters: * sWlanCB Asynchronous events callback. * 0 no event call back. * - call back parameters: * 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, * HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, * HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, * HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, * HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR * HCI_EVNT_WLAN_KEEPALIVE keepalive. * 2) data: pointer to extra data that received by the event * (NULL no data). * 3) length: data length. * - Events with extra data: * HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, * 4 bytes default gateway, 4 bytes DHCP server and 4 bytes * for DNS server. * HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, * 4 bytes Packets received, 4 bytes Min round time, * 4 bytes Max round time and 4 bytes for Avg round time. * * sFWPatches 0 no patch or pointer to FW patches * sDriverPatches 0 no patch or pointer to driver patches * sBootLoaderPatches 0 no patch or pointer to bootloader patches * * Returned Value: * None * * Description: * Initialize wlan driver * * WARNING: This function must be called before ANY other wlan driver function * ****************************************************************************/ void wlan_init(size_t max_tx_len, tWlanCB sWlanCB, tFWPatches sFWPatches, tDriverPatches sDriverPatches, tBootLoaderPatches sBootLoaderPatches) { void *old = NULL; cc3000_lib_lock(); tSLInformation.sFWPatches = sFWPatches; tSLInformation.sDriverPatches = sDriverPatches; tSLInformation.sBootLoaderPatches = sBootLoaderPatches; /* Allocate the memory for the RX/TX data transactions */ if (tSLInformation.pucTxCommandBuffer != NULL) { old = tSLInformation.pucTxCommandBuffer; } tSLInformation.pucTxCommandBuffer = malloc(max_tx_len); tSLInformation.usrBuffer.pbuffer = &tSLInformation.pucTxCommandBuffer[MAX_HCI_CMD_LENGTH]; tSLInformation.usrBuffer.len = max_tx_len - MAX_HCI_CMD_LENGTH; /* Init I/O callback */ /* Init asynchronous events callback */ tSLInformation.sWlanCB = sWlanCB; /* By default TX Complete events are routed to host too */ tSLInformation.InformHostOnTxComplete = 1; cc3000_lib_unlock(); if (old) { free(old); } } /**************************************************************************** * Name: SpiReceiveHandler * * Input Parameters: * pvBuffer - pointer to the received data buffer * * Returned Value: * None * * Description: * The function triggers Received event/data processing. It is * called from the SPI library to receive the data * ****************************************************************************/ void SpiReceiveHandler(void *pvBuffer) { uint16_t event_type; tSLInformation.pucReceivedData = (uint8_t *)pvBuffer; tSLInformation.usEventOrDataReceived = 1; STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET, event_type); ninfo("Evnt:0x%x\n", event_type); UNUSED(event_type); hci_unsolicited_event_handler(); } /**************************************************************************** * Name: wlan_start * * Input Parameters: * usPatchesAvailableAtHost - flag to indicate if patches available * from host or from EEPROM. Due to the * fact the patches are burn to the EEPROM * using the patch programmer utility, the * patches will be available from the EEPROM * and not from the host. * * Returned Value: * None * * Description: * Start WLAN device. This function asserts the enable pin of * the device (WLAN_EN), starting the HW initialization process. * The function blocked until device Initialization is completed. * Function also configure patches (FW, driver or bootloader) * and calls appropriate device callbacks. * * NOTE: Prior calling the function wlan_init shall be called. * WARNING: This function must be called after wlan_init and before any * other wlan API * ****************************************************************************/ void wlan_start(uint16_t usPatchesAvailableAtHost) { cc3000_lib_lock(); tSLInformation.NumberOfSentPackets = 0; tSLInformation.NumberOfReleasedPackets = 0; tSLInformation.usRxEventOpcode = 0; tSLInformation.usNumberOfFreeBuffers = 0; tSLInformation.usSlBufferLength = 0; tSLInformation.usBufferSize = 0; tSLInformation.usRxDataPending = 0; tSLInformation.slTransmitDataError = 0; tSLInformation.usEventOrDataReceived = 0; tSLInformation.pucReceivedData = 0; /* Init spi */ cc3000_open(SpiReceiveHandler); SimpleLink_Init_Start(usPatchesAvailableAtHost); /* Read Buffer's size and finish */ hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0); SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0); cc3000_lib_unlock(); } /**************************************************************************** * Name: wlan_get_buffer * * Input Parameters: * pdes - Location to return the buffer pointer. * * Returned Value: * None * ****************************************************************************/ void wlan_get_buffer(wlan_buffer_desc *pdes) { *pdes = tSLInformation.usrBuffer; } /**************************************************************************** * Name: wlan_stop * * Input Parameters: * None * * Returned Value: * None * * Description: * Stop WLAN device by putting it into reset state. * ****************************************************************************/ void wlan_stop(void) { cc3000_lib_lock(); cc3000_close(); cc3000_lib_unlock(); } /**************************************************************************** * Name: wlan_connect * * Input Parameters: * sec_type security options: * WLAN_SEC_UNSEC, * WLAN_SEC_WEP (ASCII support only), * WLAN_SEC_WPA or WLAN_SEC_WPA2 * ssid up to 32 bytes and is ASCII SSID of the AP * ssid_len length of the SSID * bssid 6 bytes specified the AP bssid * key up to 16 bytes specified the AP security key * key_len key length * * Returned Value: * On success, zero is returned. On error, negative is returned. * Note that even though a zero is returned on success to trigger * connection operation, it does not mean that CCC3000 is already * connected. An asynchronous "Connected" event is generated when * actual association process finishes and CC3000 is connected to * the AP. If DHCP is set, An asynchronous "DHCP" event is * generated when DHCP process is finish. * * Description: * Connect to AP * * WARNING: Please Note that when connection to AP configured with security * type WEP, please confirm that the key is set as ASCII and not * as HEX. * ****************************************************************************/ #ifndef CC3000_TINY_DRIVER long wlan_connect(unsigned long ulSecType, FAR const char *ssid, long ssid_len, FAR const uint8_t *bssid, FAR const uint8_t *key, long key_len) { long ret; uint8_t *ptr; uint8_t *args; uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); /* Fill in command buffer */ args = UINT32_TO_STREAM(args, 0x0000001c); args = UINT32_TO_STREAM(args, ssid_len); args = UINT32_TO_STREAM(args, ulSecType); args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); args = UINT32_TO_STREAM(args, key_len); args = UINT16_TO_STREAM(args, 0); /* Padding shall be zeroed */ if (bssid) { ARRAY_TO_STREAM(args, bssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } ARRAY_TO_STREAM(args, ssid, ssid_len); if (key_len && key) { ARRAY_TO_STREAM(args, key, key_len); } /* Initiate a HCI command */ hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + ssid_len + key_len - 1); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); set_errno(ret); cc3000_lib_unlock(); return ret; } #else long wlan_connect(FAR const char *ssid, long ssid_len) { long ret; uint8_t *ptr; uint8_t *args; uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); /* Fill in command buffer */ args = UINT32_TO_STREAM(args, 0x0000001c); args = UINT32_TO_STREAM(args, ssid_len); args = UINT32_TO_STREAM(args, 0); args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); args = UINT32_TO_STREAM(args, 0); args = UINT16_TO_STREAM(args, 0); /* Padding shall be zeroed */ ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); ARRAY_TO_STREAM(args, ssid, ssid_len); /* Initiate a HCI command */ hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + ssid_len - 1); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); set_errno(ret); cc3000_lib_unlock(); return ret; } #endif /**************************************************************************** * Name: wlan_disconnect * * Input Parameters: * None * * Returned Value: * 0 disconnected done, other CC3000 already disconnected * * Description: * Disconnect connection from AP. * ****************************************************************************/ long wlan_disconnect(void) { long ret; uint8_t *ptr; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret); set_errno(ret); cc3000_lib_unlock(); return ret; } /**************************************************************************** * Name: wlan_ioctl_set_connection_policy * * Input Parameters: * should_connect_to_open_ap enable(1), disable(0) connect to any * available AP. This parameter corresponds to the configuration of * item # 3 in the brief description. * should_use_fast_connect enable(1), disable(0). if enabled, tries * to connect to the last connected AP. This parameter corresponds * to the configuration of item # 1 in the brief description. * auto_start enable(1), disable(0) auto connect * after reset and periodically reconnect if needed. This * configuration configures option 2 in the above description. * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * When auto is enabled, the device tries to connect according * the following policy: * 1) If fast connect is enabled and last connection is valid, * the device will try to connect to it without the scanning * procedure (fast). The last connection will be marked as * invalid, due to adding/removing profile. * 2) If profile exists, the device will try to connect it * (Up to seven profiles). * 3) If fast and profiles are not found, and open mode is * enabled, the device will try to connect to any AP. * * Note that the policy settings are stored in the CC3000 NVMEM. * ****************************************************************************/ long wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap, unsigned long ulShouldUseFastConnect, unsigned long ulUseProfiles) { long ret; uint8_t *ptr; uint8_t *args; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); /* Fill in HCI packet structure */ args = UINT32_TO_STREAM(args, should_connect_to_open_ap); args = UINT32_TO_STREAM(args, ulShouldUseFastConnect); args = UINT32_TO_STREAM(args, ulUseProfiles); /* Initiate a HCI command */ hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret); cc3000_lib_unlock(); return ret; } /**************************************************************************** * Name: wlan_add_profile * * Input Parameters: * ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 * ucSsid ssid SSID up to 32 bytes * ulSsidLen ssid length * ucBssid bssid 6 bytes * ulPriority ulPriority profile priority. Lowest priority:0. * ulPairwiseCipher_Or_TxKeyLen key length for WEP security * ulGroupCipher_TxKeyIndex key index * ulKeyMgmt KEY management * ucPf_OrKey security key * ulPassPhraseLen security key length for WPA\WPA2 * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * When auto start is enabled, the device connects to * station from the profiles table. Up to 7 profiles are supported. * If several profiles configured the device choose the highest * priority profile, within each priority group, device will choose * profile based on security policy, signal strength, etc * parameters. All the profiles are stored in CC3000 NVMEM. * ****************************************************************************/ #ifndef CC3000_TINY_DRIVER long wlan_add_profile(unsigned long ulSecType, uint8_t *ucSsid, unsigned long ulSsidLen, uint8_t *ucBssid, unsigned long ulPriority, unsigned long ulPairwiseCipher_Or_TxKeyLen, unsigned long ulGroupCipher_TxKeyIndex, unsigned long ulKeyMgmt, uint8_t *ucPf_OrKey, unsigned long ulPassPhraseLen) { uint16_t arg_len = 0; long ret; uint8_t *ptr; long i = 0; uint8_t *args; uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; cc3000_lib_lock(); ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); args = UINT32_TO_STREAM(args, ulSecType); /* Setup arguments in accordance with the security type */ switch (ulSecType) { /* OPEN */ case WLAN_SEC_UNSEC: { args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if (ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen; } break; /* WEP */ case WLAN_SEC_WEP: { args = UINT32_TO_STREAM(args, 0x00000020); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if (ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen); args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); for (i = 0; i < 4; i++) { uint8_t *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen]; ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen); } arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen + ulPairwiseCipher_Or_TxKeyLen * 4; } break; /* WPA, WPA2 */ case WLAN_SEC_WPA: case WLAN_SEC_WPA2: { args = UINT32_TO_STREAM(args, 0x00000028); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if (ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); args = UINT32_TO_STREAM(args, ulKeyMgmt); args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen); args = UINT32_TO_STREAM(args, ulPassPhraseLen); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen); arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen; } break; } /* Initiate a HCI command */ hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, ptr, arg_len); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); cc3000_lib_unlock(); return ret; } #else long wlan_add_profile(unsigned long ulSecType, uint8_t * ucSsid, uint8_t ulSsidLen, uint8_t *ucBssid, unsigned long ulPriority, unsigned long ulPairwiseCipher_Or_TxKeyLen, unsigned long ulGroupCipher_TxKeyIndex, unsigned long ulKeyMgmt, uint8_t * ucPf_OrKey, unsigned long ulPassPhraseLen) { return -1; } #endif /**************************************************************************** * Name: wlan_ioctl_del_profile * * Input Parameters: * index number of profile to delete * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * Delete WLAN profile * * @Note In order to delete all stored profile, set index to 255. * ****************************************************************************/ long wlan_ioctl_del_profile(unsigned long ulIndex) { long ret; uint8_t *ptr; uint8_t *args; cc3000_lib_lock(); ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); /* Fill in HCI packet structure */ args = UINT32_TO_STREAM(args, ulIndex); ret = EFAIL; /* Initiate a HCI command */ hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, ptr, WLAN_DEL_PROFILE_PARAMS_LEN); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret); cc3000_lib_unlock(); return ret; } /**************************************************************************** * Name: wlan_ioctl_get_scan_results * * Input Parameters: * scan_timeout parameter not supported * ucResults scan results (_wlan_full_scan_results_args_t) * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * Gets entry from scan result table. * The scan results are returned one by one, and each entry * represents a single AP found in the area. The following is a * format of the scan result: * - 4 Bytes: number of networks found * - 4 Bytes: The status of the scan: 0 - aged results, * 1 - results valid, 2 - no results * - 42 bytes: Result entry, where the bytes are arranged as follows: * - 1 bit isValid - is result valid or not * - 7 bits rssi - RSSI value; * - 2 bits: securityMode - security mode of the AP: * 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 * - 6 bits: SSID name length * - 2 bytes: the time at which the entry has entered into * scans result table * - 32 bytes: SSID name * - 6 bytes: BSSID * * NOTE: scan_timeout, is not supported on this version. * ****************************************************************************/ #ifndef CC3000_TINY_DRIVER long wlan_ioctl_get_scan_results(unsigned long ulScanTimeout, uint8_t *ucResults) { uint8_t *ptr; uint8_t *args; cc3000_lib_lock(); ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); /* Fill in temporary command buffer */ args = UINT32_TO_STREAM(args, ulScanTimeout); /* Initiate a HCI command */ hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults); cc3000_lib_unlock(); return 0; } #endif /**************************************************************************** * Name: wlan_ioctl_set_scan_params * * Input Parameters: * uiEnable - start/stop application scan: * 1 = start scan with default interval value of 10 min. * in order to set a different scan interval value apply the value * in milliseconds. minimum 1 second. 0=stop). Wlan reset * (wlan_stop() wlan_start()) is needed when changing scan interval * value. Saved: No * uiMinDwellTime minimum dwell time value to be used for each * channel, in milliseconds. Saved: yes * Recommended Value: 100 (Default: 20) * uiMaxDwellTime maximum dwell time value to be used for each * channel, in milliseconds. Saved: yes * Recommended Value: 100 (Default: 30) * uiNumOfProbeRequests max probe request between dwell time. * Saved: yes. Recommended Value: 5 (Default:2) * uiChannelMask bitwise, up to 13 channels (0x1fff). * Saved: yes. Default: 0x7ff * uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) * uiSNRThreshold NSR threshold. Saved: yes (Default: 0) * uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) * aiIntervalList pointer to array with 16 entries (16 channels) * each entry (unsigned long) holds timeout between periodic scan * (connection scan) - in millisecond. Saved: yes. Default 2000ms. * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * start and stop scan procedure. Set scan parameters. * * @Note uiDefaultTxPower, is not supported on this version. * ****************************************************************************/ #ifndef CC3000_TINY_DRIVER long wlan_ioctl_set_scan_params(unsigned long uiEnable, unsigned long uiMinDwellTime, unsigned long uiMaxDwellTime, unsigned long uiNumOfProbeRequests, unsigned long uiChannelMask, long iRSSIThreshold, unsigned long uiSNRThreshold, unsigned long uiDefaultTxPower, unsigned long *aiIntervalList) { unsigned long uiRes; uint8_t *ptr; uint8_t *args; cc3000_lib_lock(); ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); /* Fill in temporary command buffer */ args = UINT32_TO_STREAM(args, 36); args = UINT32_TO_STREAM(args, uiEnable); args = UINT32_TO_STREAM(args, uiMinDwellTime); args = UINT32_TO_STREAM(args, uiMaxDwellTime); args = UINT32_TO_STREAM(args, uiNumOfProbeRequests); args = UINT32_TO_STREAM(args, uiChannelMask); args = UINT32_TO_STREAM(args, iRSSIThreshold); args = UINT32_TO_STREAM(args, uiSNRThreshold); args = UINT32_TO_STREAM(args, uiDefaultTxPower); ARRAY_TO_STREAM(args, aiIntervalList, sizeof(unsigned long) * SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE); /* Initiate a HCI command */ hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, ptr, WLAN_SET_SCAN_PARAMS_LEN); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes); cc3000_lib_unlock(); return uiRes; } #endif /**************************************************************************** * Name: wlan_set_event_mask * * Input Parameters: * mask mask option: * HCI_EVNT_WLAN_UNSOL_CONNECT connect event * HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event * HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done * HCI_EVNT_WLAN_UNSOL_INIT init done * HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report * HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report * HCI_EVNT_WLAN_KEEPALIVE keepalive * HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission * Saved: no. * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * Mask event according to bit mask. In case that event is * masked (1), the device will not send the masked event to host. * ****************************************************************************/ long wlan_set_event_mask(unsigned long ulMask) { long ret; uint8_t *ptr; uint8_t *args; cc3000_lib_lock(); if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE) { tSLInformation.InformHostOnTxComplete = 0; /* Since an event is a virtual event - i.e. it is not coming from CC3000 * there is no need to send anything to the device if it was an only event */ if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE) { return 0; } ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE; ulMask |= HCI_EVNT_WLAN_UNSOL_BASE; } else { tSLInformation.InformHostOnTxComplete = 1; } ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); /* Fill in HCI packet structure */ args = UINT32_TO_STREAM(args, ulMask); /* Initiate a HCI command */ hci_command_send(HCI_CMND_EVENT_MASK, ptr, WLAN_SET_MASK_PARAMS_LEN); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret); cc3000_lib_unlock(); return ret; } /**************************************************************************** * Name: wlan_ioctl_statusget * * Input Parameters: * None * * Returned Value: * WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, * STATUS_CONNECTING or WLAN_STATUS_CONNECTED * * Description: * get wlan status: disconnected, scanning, connecting or connected * ****************************************************************************/ #ifndef CC3000_TINY_DRIVER long wlan_ioctl_statusget(void) { long ret; uint8_t *ptr; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET, ptr, 0); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret); cc3000_lib_unlock(); return ret; } #endif /**************************************************************************** * Name: wlan_smart_config_start * * Input Parameters: * algoEncryptedFlag indicates whether the information is encrypted * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * Start to acquire device profile. The device acquire its own * profile, if profile message is found. The acquired AP information * is stored in CC3000 EEPROM only in case AES128 encryption is used. * In case AES128 encryption is not used, a profile is created by * CC3000 internally. * * @Note An asynchronous event - Smart Config Done will be generated as soon * as the process finishes successfully. * ****************************************************************************/ long wlan_smart_config_start(unsigned long algoEncryptedFlag) { long ret; uint8_t *ptr; uint8_t *args; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); /* Fill in HCI packet structure */ args = UINT32_TO_STREAM(args, algoEncryptedFlag); hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr, WLAN_SMART_CONFIG_START_PARAMS_LEN); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret); cc3000_lib_unlock(); return ret; } /**************************************************************************** * Name: wlan_smart_config_stop * * Input Parameters: * algoEncryptedFlag indicates whether the information is encrypted * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * Stop the acquire profile procedure * ****************************************************************************/ long wlan_smart_config_stop(void) { long ret; uint8_t *ptr; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret); cc3000_lib_unlock(); return ret; } /**************************************************************************** * Name: wlan_smart_config_set_prefix * * Input Parameters: * newPrefix 3 bytes identify the SSID prefix for the Smart Config. * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * Configure station ssid prefix. The prefix is used internally * in CC3000. It should always be TTT. * * @Note The prefix is stored in CC3000 NVMEM * ****************************************************************************/ long wlan_smart_config_set_prefix(FAR char *cNewPrefix) { long ret; uint8_t *ptr; uint8_t *args; cc3000_lib_lock(); ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); if (cNewPrefix == NULL) { return ret; } /* With the new Smart Config, prefix must be TTT */ else { *cNewPrefix = 'T'; *(cNewPrefix + 1) = 'T'; *(cNewPrefix + 2) = 'T'; } ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH); hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr, SL_SIMPLE_CONFIG_PREFIX_LENGTH); /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret); cc3000_lib_unlock(); return ret; } /**************************************************************************** * Name: aes_read_key * * Description: * Reads AES128 key from EEPROM. Reads the AES128 key from fileID #12 in * EEPROM returns an error if the key does not exist. * * Input Parameters: * key AES128 key of size 16 bytes * * Returned Value * On success 0, error otherwise. * ****************************************************************************/ #ifndef CC3000_UNENCRYPTED_SMART_CONFIG signed long aes_read_key(uint8_t *key) { signed long returnValue; returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); return returnValue; } #endif /**************************************************************************** * Name: aes_write_key * * Description: * Writes AES128 key from EEPROM Writes the AES128 key to fileID #12 in * EEPROM * * Input Parameters: * key AES128 key of size 16 bytes * * Returned Value * On success 0, error otherwise. * ****************************************************************************/ #if 0 //#ifndef CC3000_UNENCRYPTED_SMART_CONFIG signed long aes_write_key(uint8_t *key) { signed long returnValue; returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); return returnValue; } #endif /**************************************************************************** * Name: wlan_smart_config_process * * Input Parameters: * None * * Returned Value: * On success, zero is returned. On error, -1 is returned * * Description: * process the acquired data and store it as a profile. The acquired * AP information is stored in CC3000 EEPROM encrypted. * The encrypted data is decrypted and stored as a profile. * behavior is as defined by connection policy. * ****************************************************************************/ #ifndef CC3000_UNENCRYPTED_SMART_CONFIG long wlan_smart_config_process() { signed long returnValue; unsigned long ssidLen, keyLen; uint8_t *decKeyPtr; uint8_t *ssidPtr; /* Read the key from EEPROM - fileID 12 */ returnValue = aes_read_key(akey); if (returnValue != 0) { return returnValue; } /* Read the received data from fileID #13 and parse it according to the followings: * 1) SSID LEN - not encrypted * 2) SSID - not encrypted * 3) KEY LEN - not encrypted. always 32 bytes long * 4) Security type - not encrypted * 5) KEY - encrypted together with true key length as the first byte in KEY * to elaborate, there are two corner cases: * 1) the KEY is 32 bytes long. In this case, the first byte does not represent * KEY length * 2) the KEY is 31 bytes long. In this case, the first byte represent KEY * length and equals 31 */ returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray); if (returnValue != 0) { return returnValue; } ssidPtr = &profileArray[1]; ssidLen = profileArray[0]; decKeyPtr = &profileArray[profileArray[0] + 3]; aes_decrypt(decKeyPtr, akey); if (profileArray[profileArray[0] + 1] > 16) { aes_decrypt((uint8_t *)(decKeyPtr + 16), akey); } if (*(uint8_t *)(decKeyPtr +31) != 0) { if (*decKeyPtr == 31) { keyLen = 31; decKeyPtr++; } else { keyLen = 32; } } else { keyLen = *decKeyPtr; decKeyPtr++; } /* Add a profile */ switch (profileArray[profileArray[0] + 2]) { case WLAN_SEC_UNSEC: /* None */ { returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], /* Security type */ ssidPtr, /* SSID */ ssidLen, /* SSID length */ NULL, /* BSSID */ 1, /* Priority */ 0, 0, 0, 0, 0); break; } case WLAN_SEC_WEP: /* WEP */ { returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], /* Security type */ ssidPtr, /* SSID */ ssidLen, /* SSID length */ NULL, /* BSSID */ 1, /* Priority */ keyLen, /* KEY length */ 0, /* KEY index */ 0, decKeyPtr, /* KEY */ 0); break; } case WLAN_SEC_WPA: /* WPA */ case WLAN_SEC_WPA2: /* WPA2 */ { returnValue = wlan_add_profile(WLAN_SEC_WPA2, /* Security type */ ssidPtr, ssidLen, NULL, /* BSSID */ 1, /* Priority */ 0x18, /* PairwiseCipher */ 0x1e, /* GroupCipher */ 2, /* KEY management */ decKeyPtr, /* KEY */ keyLen); /* KEY length */ break; } } return returnValue; } #endif /* CC3000_UNENCRYPTED_SMART_CONFIG */