820 lines
23 KiB
C++
820 lines
23 KiB
C++
|
/**
|
||
|
* @file SFE_CC3000.cpp
|
||
|
* @brief Library for the SparkFun CC3000 shield and breakout boards
|
||
|
* @author Shawn Hymel (SparkFun Electronics)
|
||
|
* @author Revisions by Jacob Rosenthal (https://github.com/jacobrosenthal)
|
||
|
*
|
||
|
* @copyright This code is public domain but you buy me a beer if you use
|
||
|
* this and we meet someday (Beerware license).
|
||
|
*
|
||
|
* This library interfaces the TI CC3000 to Arduino over SPI. The library relies
|
||
|
* on the Arduino built-in SPI commands. To use the library, instantiate an
|
||
|
* SFE_CC3000 object, call the init() function, and then call connect() with the
|
||
|
* necessary connection details.
|
||
|
*/
|
||
|
|
||
|
#include <Arduino.h>
|
||
|
#include <SPI.h>
|
||
|
|
||
|
#include "common.h"
|
||
|
#include "SFE_CC3000.h"
|
||
|
#include "SFE_CC3000_Callbacks.h"
|
||
|
#include "SFE_CC3000_SPI.h"
|
||
|
#include "hci.h"
|
||
|
#include "netapp.h"
|
||
|
#include "nvmem.h"
|
||
|
#include "socket.h"
|
||
|
#include "wlan.h"
|
||
|
|
||
|
/* Global variables */
|
||
|
uint8_t g_int_pin;
|
||
|
uint8_t g_int_num;
|
||
|
uint8_t g_en_pin;
|
||
|
uint8_t g_cs_pin;
|
||
|
bool g_socket_connected;
|
||
|
uint8_t g_saved_data_mode;
|
||
|
uint8_t g_saved_bit_order;
|
||
|
uint8_t g_saved_clock_div;
|
||
|
#if (DEBUG == 1)
|
||
|
volatile long g_debug_interrupt;
|
||
|
#endif
|
||
|
volatile unsigned long ulSmartConfigFinished;
|
||
|
volatile unsigned long ucStopSmartConfig;
|
||
|
volatile unsigned long ulCC3000Connected;
|
||
|
volatile unsigned long ulCC3000DHCP;
|
||
|
volatile unsigned long ulCC3000DHCP_configured;
|
||
|
volatile unsigned long OkToDoShutDown;
|
||
|
netapp_pingreport_args_t g_ping_report = {0};
|
||
|
|
||
|
/**
|
||
|
* @brief Constructor - Instantiates SFE_CC3000 object
|
||
|
*
|
||
|
* @param[in] int_pin pin needed for MCU interrupt
|
||
|
* @param[in] en_pin pin used for CC3000 enable
|
||
|
* @param[in] cs_pin pin for SPI chip select
|
||
|
*/
|
||
|
SFE_CC3000::SFE_CC3000(uint8_t int_pin, uint8_t en_pin, uint8_t cs_pin)
|
||
|
{
|
||
|
/* Set initialization state */
|
||
|
is_initialized_ = false;
|
||
|
|
||
|
/* Initialize access point scan variables */
|
||
|
num_access_points_ = 0;
|
||
|
access_point_count_ = 0;
|
||
|
|
||
|
/* Initialize status global variables */
|
||
|
ulSmartConfigFinished = 0;
|
||
|
ucStopSmartConfig = 0;
|
||
|
ulCC3000Connected = 0;
|
||
|
ulCC3000DHCP = 0;
|
||
|
ulCC3000DHCP_configured = 0;
|
||
|
OkToDoShutDown = 0;
|
||
|
g_socket_connected = false;
|
||
|
#if (DEBUG == 1)
|
||
|
g_debug_interrupt = 0;
|
||
|
#endif
|
||
|
|
||
|
/* Set pin definitions */
|
||
|
g_int_pin = int_pin;
|
||
|
g_en_pin = en_pin;
|
||
|
g_cs_pin = cs_pin;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Destructor
|
||
|
*/
|
||
|
SFE_CC3000::~SFE_CC3000()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configure SPI for MCU to CC3000
|
||
|
*
|
||
|
* @return True if SPI initialization completed successfully. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::init()
|
||
|
{
|
||
|
|
||
|
/* Check if CC3000 SPI is already initialized */
|
||
|
if (is_initialized_) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Determine available interrupt pins on supported microcontrollers */
|
||
|
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega168__) || \
|
||
|
defined(__AVR_ATmega328P__) || defined (__AVR_ATmega328__)
|
||
|
switch (g_int_pin) {
|
||
|
case 2:
|
||
|
g_int_num = 0;
|
||
|
break;
|
||
|
case 3:
|
||
|
g_int_num = 1;
|
||
|
break;
|
||
|
default:
|
||
|
# if (DEBUG == 1)
|
||
|
Serial.println("ERROR: Interrupt line not attached to pin 2 or 3");
|
||
|
# endif
|
||
|
return false;
|
||
|
}
|
||
|
#elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) || \
|
||
|
defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
|
||
|
|
||
|
switch (g_int_pin) {
|
||
|
case 2:
|
||
|
g_int_num = 0;
|
||
|
break;
|
||
|
case 3:
|
||
|
g_int_num = 1;
|
||
|
break;
|
||
|
case 18:
|
||
|
g_int_num = 5;
|
||
|
break;
|
||
|
case 19:
|
||
|
g_int_num = 4;
|
||
|
break;
|
||
|
case 20:
|
||
|
g_int_num = 3;
|
||
|
break;
|
||
|
case 21:
|
||
|
g_int_num = 2;
|
||
|
break;
|
||
|
default:
|
||
|
# if (DEBUG == 1)
|
||
|
Serial.println("ERROR: Interrupt not pin 2, 3, 18, 19, 20, or 21");
|
||
|
# endif
|
||
|
return false;
|
||
|
}
|
||
|
#elif defined(__AVR_ATmega32U4__)
|
||
|
switch (g_int_pin) {
|
||
|
case 3:
|
||
|
g_int_num = 0;
|
||
|
break;
|
||
|
case 2:
|
||
|
g_int_num = 1;
|
||
|
break;
|
||
|
case 0:
|
||
|
g_int_num = 2;
|
||
|
break;
|
||
|
case 1:
|
||
|
g_int_num = 3;
|
||
|
break;
|
||
|
case 7:
|
||
|
g_int_num = 4;
|
||
|
break;
|
||
|
default:
|
||
|
# if (DEBUG == 1)
|
||
|
Serial.println("ERROR: Interrupt not pin 0, 1, 2, 3, or 7");
|
||
|
# endif
|
||
|
return false;
|
||
|
}
|
||
|
#else
|
||
|
# if (DEBUG == 1)
|
||
|
Serial.println("ERROR: Microcontroller not supported");
|
||
|
# endif
|
||
|
return false;
|
||
|
#endif
|
||
|
|
||
|
/* Initialize interrupt, CS, and enable pins */
|
||
|
pinMode(g_int_pin, INPUT);
|
||
|
pinMode(g_en_pin, OUTPUT);
|
||
|
pinMode(g_cs_pin, OUTPUT);
|
||
|
digitalWrite(g_en_pin, LOW);
|
||
|
|
||
|
/* Setup SPI */
|
||
|
SPI.begin();
|
||
|
SPI.setDataMode(SPI_MODE1);
|
||
|
SPI.setBitOrder(MSBFIRST);
|
||
|
SPI.setClockDivider(SPI_CLK_DIV);
|
||
|
|
||
|
/* De-assert CS */
|
||
|
digitalWrite(g_cs_pin, HIGH);
|
||
|
|
||
|
/* Initialize CC3000 library - provide callback definitions */
|
||
|
wlan_init( cc3000AsyncCallback,
|
||
|
sendFirmwarePatch,
|
||
|
sendDriverPatch,
|
||
|
sendBootLoaderPatch,
|
||
|
readWlanInterruptPin,
|
||
|
enableWlanInterrupt,
|
||
|
disableWlanInterrupt,
|
||
|
writeWlanPin);
|
||
|
|
||
|
/* CC3000 needs a delay before starting WLAN or it gets stuck sometimes */
|
||
|
delay(100);
|
||
|
|
||
|
/* Start CC3000 - asserts enable pin and blocks until init is complete */
|
||
|
wlan_start(0);
|
||
|
|
||
|
/* Mask out non-required events */
|
||
|
wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE | HCI_EVNT_WLAN_UNSOL_INIT);
|
||
|
|
||
|
is_initialized_ = true;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Reads the firmware version from the CC3000
|
||
|
*
|
||
|
* @param[out] fw_ver firmware version in 2 bytes. [0] is major and [1] is minor
|
||
|
* @return True is firmware could be read from the CC3000. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::getFirmwareVersion(unsigned char *fw_ver)
|
||
|
{
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Read firmware version from the CC3000 */
|
||
|
if (nvmem_read_sp_version(fw_ver) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Reads the MAC address from the CC3000
|
||
|
*
|
||
|
* @param[out] mac_addr six char buffer containing the MAC address
|
||
|
* @return True if MAC address could be read from the CC3000. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::getMacAddress(unsigned char *mac_addr)
|
||
|
{
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Read MAC address from the CC3000 */
|
||
|
if (nvmem_get_mac_address(mac_addr) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Scans area for access points. Blocks operation to allow for scan.
|
||
|
*
|
||
|
* To scan for APs, first call scanAccessPoints() with an appropriate scan time
|
||
|
* (recommended scan_time = 4000ms). Create an AccessPointInfo struct and pass
|
||
|
* that to getNextAccessPoint(). Continue to call getNextAccessPoint() until it
|
||
|
* returns false (there are no more APs to scan).
|
||
|
*
|
||
|
* @param[in] scan_time time to scan networks in milliseconds
|
||
|
* @return True if scan succeeded. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::scanAccessPoints(unsigned int scan_time)
|
||
|
{
|
||
|
int i;
|
||
|
unsigned long channel_timeouts[SCAN_NUM_CHANNELS];
|
||
|
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Create channel interval list for AP scanning */
|
||
|
for (i = 0; i < SCAN_NUM_CHANNELS; i++) {
|
||
|
channel_timeouts[0] = SCAN_CHANNEL_TIMEOUT;
|
||
|
}
|
||
|
|
||
|
/* Setup access point scan */
|
||
|
if (wlan_ioctl_set_scan_params( scan_time,
|
||
|
SCAN_MIN_DWELL_TIME,
|
||
|
SCAN_MAX_DWELL_TIME,
|
||
|
SCAN_NUM_PROBE_REQS,
|
||
|
SCAN_CHANNEL_MASK,
|
||
|
SCAN_RSSI_THRESHOLD,
|
||
|
SCAN_NSR_THRESHOLD,
|
||
|
SCAN_DEFAULT_TX_POWER,
|
||
|
channel_timeouts ) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Wait for scan to complete */
|
||
|
delay(scan_time + 500);
|
||
|
|
||
|
/* Re-initialize AP counters */
|
||
|
num_access_points_ = 0;
|
||
|
access_point_count_ = 0;
|
||
|
|
||
|
/* Get first scan result in order to obtain the total number of APs */
|
||
|
if (wlan_ioctl_get_scan_results(0, (unsigned char *)&ap_scan_result_) !=
|
||
|
CC3000_SUCCESS ){
|
||
|
return false;
|
||
|
}
|
||
|
num_access_points_ = ap_scan_result_.num_networks;
|
||
|
|
||
|
/* Stop scan */
|
||
|
if (wlan_ioctl_set_scan_params( 0,
|
||
|
SCAN_MIN_DWELL_TIME,
|
||
|
SCAN_MAX_DWELL_TIME,
|
||
|
SCAN_NUM_PROBE_REQS,
|
||
|
SCAN_CHANNEL_MASK,
|
||
|
SCAN_RSSI_THRESHOLD,
|
||
|
SCAN_NSR_THRESHOLD,
|
||
|
SCAN_DEFAULT_TX_POWER,
|
||
|
channel_timeouts ) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Fills out AP info struct with next access data.
|
||
|
*
|
||
|
* To scan for APs, first call scanAccessPoints() with an appropriate scan time
|
||
|
* (recommended scan_time = 4000ms). Create an AccessPointInfo struct and pass
|
||
|
* that to getNextAccessPoint(). Continue to call getNextAccessPoint() until it
|
||
|
* returns false (there are no more APs to scan).
|
||
|
*
|
||
|
* @param[out] ap_info struct containing information about the next AP
|
||
|
* @return True if next AP obtained. False if no more APs available.
|
||
|
*/
|
||
|
bool SFE_CC3000::getNextAccessPoint(AccessPointInfo &ap_info)
|
||
|
{
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If results are invalid (e.g. no results), return false */
|
||
|
if (!ap_scan_result_.is_valid) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If we have exhausted all of the networks to list, return false */
|
||
|
if (access_point_count_ >= num_access_points_) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Fill out AP info with last AP surveyed */
|
||
|
ap_info.rssi = ap_scan_result_.rssi;
|
||
|
ap_info.security_mode = ap_scan_result_.security_mode;
|
||
|
strncpy(ap_info.ssid,
|
||
|
(char *)ap_scan_result_.ssid,
|
||
|
ap_scan_result_.ssid_length);
|
||
|
ap_info.ssid[ap_scan_result_.ssid_length] = '\0';
|
||
|
memcpy(ap_info.bssid, ap_scan_result_.bssid, BSSID_LENGTH);
|
||
|
|
||
|
/* Get next set of results */
|
||
|
if (wlan_ioctl_get_scan_results(0, (unsigned char *)&ap_scan_result_) !=
|
||
|
CC3000_SUCCESS ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Increment AP counter */
|
||
|
access_point_count_++;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Connects to a WAP using the given SSID and password
|
||
|
*
|
||
|
* @param[in] ssid the SSID for the wireless network
|
||
|
* @param[in] security type of security for the network
|
||
|
* @param[in] password optional ASCII password if connecting to a secured AP
|
||
|
* @param[in] timeout optional time (ms) to wait before stopping. 0 = no timeout
|
||
|
* @return True if connected to wireless network. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::connect( char *ssid,
|
||
|
unsigned int security,
|
||
|
char *password,
|
||
|
unsigned int timeout)
|
||
|
{
|
||
|
unsigned long time;
|
||
|
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If already connected, return false. */
|
||
|
if (getDHCPStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If security mode is not a predefined type, return false. */
|
||
|
if ( !( security == WLAN_SEC_UNSEC ||
|
||
|
security == WLAN_SEC_WEP ||
|
||
|
security == WLAN_SEC_WPA ||
|
||
|
security == WLAN_SEC_WPA2) ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Set connection profile to manual (no fast or auto connect) */
|
||
|
if (wlan_ioctl_set_connection_policy(DISABLE, DISABLE, DISABLE) !=
|
||
|
CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Connect to the given access point*/
|
||
|
time = millis();
|
||
|
while (getConnectionStatus() == false) {
|
||
|
|
||
|
/* Attempt to connect to an AP */
|
||
|
delay(10);
|
||
|
if (security == WLAN_SEC_UNSEC) {
|
||
|
|
||
|
if (wlan_connect( WLAN_SEC_UNSEC,
|
||
|
ssid,
|
||
|
strlen(ssid),
|
||
|
0,
|
||
|
0,
|
||
|
0) == CC3000_SUCCESS) {
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
if (wlan_connect( security,
|
||
|
ssid,
|
||
|
strlen(ssid),
|
||
|
0,
|
||
|
(unsigned char*)password,
|
||
|
strlen(password)) == CC3000_SUCCESS) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check against timeout. Return if out of time. */
|
||
|
if (timeout != 0) {
|
||
|
if ( (millis() - time) > timeout ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Wait for DHCP */
|
||
|
while (getDHCPStatus() == false) {
|
||
|
if (timeout != 0) {
|
||
|
if ( (millis() - time) > timeout ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Get connection information */
|
||
|
netapp_ipconfig(&connection_info_);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Begins SmartConfig. The user needs to run the SmartConfig phone app.
|
||
|
*
|
||
|
* @param[in] timeout optional time (ms) to wait before stopping. 0 = no timeout
|
||
|
* @return True if connected to wireless network. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::startSmartConfig(unsigned int timeout)
|
||
|
{
|
||
|
char cc3000_prefix[] = {'T', 'T', 'T'};
|
||
|
unsigned long time;
|
||
|
|
||
|
/* Reset all global connection variables */
|
||
|
ulSmartConfigFinished = 0;
|
||
|
ulCC3000Connected = 0;
|
||
|
ulCC3000DHCP = 0;
|
||
|
OkToDoShutDown=0;
|
||
|
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Set connection profile to manual (no fast or auto connect) */
|
||
|
if (wlan_ioctl_set_connection_policy(DISABLE, DISABLE, DISABLE) !=
|
||
|
CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Delete old connection profiles */
|
||
|
if (wlan_ioctl_del_profile(255) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Wait until CC3000 is disconnected */
|
||
|
while (getConnectionStatus()) {
|
||
|
delay(1);
|
||
|
}
|
||
|
|
||
|
/* Sets the prefix for SmartConfig. Should always be "TTT" */
|
||
|
if (wlan_smart_config_set_prefix((char*)cc3000_prefix) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Start the SmartConfig process */
|
||
|
if (wlan_smart_config_start(0) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Wait for SmartConfig to complete */
|
||
|
time = millis();
|
||
|
while (ulSmartConfigFinished == 0) {
|
||
|
if (timeout != 0) {
|
||
|
if ( (millis() - time) > timeout ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Configure to connect automatically to AP from SmartConfig process */
|
||
|
if (wlan_ioctl_set_connection_policy(DISABLE, DISABLE, ENABLE) !=
|
||
|
CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Reset CC3000 */
|
||
|
wlan_stop();
|
||
|
delay(400);
|
||
|
wlan_start(0);
|
||
|
|
||
|
/* Wait for connection and DHCP-assigned IP address */
|
||
|
while (getDHCPStatus() == false) {
|
||
|
if (timeout != 0) {
|
||
|
if ( (millis() - time) > timeout ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* If we make it this far, we need to tell the SmartConfig app to stop */
|
||
|
mdnsAdvertiser(1, DEVICE_NAME, strlen(DEVICE_NAME));
|
||
|
|
||
|
/* Get connection information */
|
||
|
netapp_ipconfig(&connection_info_);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Attempts to connect to network stored in memory.
|
||
|
*
|
||
|
* FastConnect attempts to connect to the WiFi network (AP) stored in non-
|
||
|
* volatile memory. The user needs to run SmartConfig first in order to create
|
||
|
* a network profile in memory before running FastConnect.
|
||
|
*
|
||
|
* @param[in] timeout optional time (ms) to wait before stopping. 0 = no timeout
|
||
|
* @return True if connected to wireless network. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::fastConnect(unsigned int timeout)
|
||
|
{
|
||
|
unsigned long time;
|
||
|
|
||
|
/* Reset all global connection variables */
|
||
|
ulSmartConfigFinished = 0;
|
||
|
ulCC3000Connected = 0;
|
||
|
ulCC3000DHCP = 0;
|
||
|
OkToDoShutDown=0;
|
||
|
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Set connection profile to auto-connect */
|
||
|
if (wlan_ioctl_set_connection_policy(DISABLE, DISABLE, ENABLE) !=
|
||
|
CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Wait for connection and DHCP-assigned IP address */
|
||
|
time = millis();
|
||
|
while (getDHCPStatus() == false) {
|
||
|
if (timeout != 0) {
|
||
|
if ( (millis() - time) > timeout ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Get connection information */
|
||
|
netapp_ipconfig(&connection_info_);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Disconnects from the AP
|
||
|
*
|
||
|
* @return True if disconnected successfully. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::disconnect()
|
||
|
{
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Attempt to disconnect from the network */
|
||
|
if (wlan_disconnect() == CC3000_SUCCESS) {
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Looks up the IP address of a given hostname
|
||
|
*
|
||
|
* @param[in] hostname the name of the host or website (e.g. www.google.com)
|
||
|
* @param[out] ip_address returned IP address of the hostname
|
||
|
* @return True if lookup completed successfully. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::dnsLookup(char *hostname, IPAddress *ip_address)
|
||
|
{
|
||
|
unsigned long ret_ip_addr = 0;
|
||
|
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If not connected, return false. */
|
||
|
if (!getConnectionStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If DHCP has not been assigned, return false. */
|
||
|
if (!getDHCPStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Attempt to get IP address by hostname */
|
||
|
if (!gethostbyname(hostname, strlen(hostname), &ret_ip_addr)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
*ip_address = IPAddress(
|
||
|
(uint8_t)(ret_ip_addr >> 24) & 0xFF,
|
||
|
(uint8_t)(ret_ip_addr >> 16) & 0xFF,
|
||
|
(uint8_t)(ret_ip_addr >> 8) & 0xFF,
|
||
|
(uint8_t)ret_ip_addr & 0xFF);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Pings IP address [attempts] times and returns a ping report
|
||
|
*
|
||
|
* @param[in] ip_address the IP address to ping
|
||
|
* @param[out] ping_report returned ping report with statistics
|
||
|
* @param[in] attempts optional number of times to ping the address
|
||
|
* @param[in] size optional size of ping buffer (up to 1400 bytes)
|
||
|
* @param[in] timeout optional time to wait for ping response (milliseconds)
|
||
|
* @return True if ping command succeeded. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::ping( IPAddress ip_address,
|
||
|
PingReport &ping_report,
|
||
|
unsigned int attempts,
|
||
|
unsigned int size,
|
||
|
unsigned int timeout)
|
||
|
{
|
||
|
|
||
|
unsigned long ip_addr;
|
||
|
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If not connected, return false. */
|
||
|
if (!getConnectionStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If DHCP has not been assigned, return false. */
|
||
|
if (!getDHCPStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Create unsigned long IP address out of char array */
|
||
|
ip_addr = (unsigned long)ip_address[0] |
|
||
|
((unsigned long)ip_address[1] << 8) |
|
||
|
((unsigned long)ip_address[2] << 16) |
|
||
|
((unsigned long)ip_address[3] << 24);
|
||
|
|
||
|
/* Send pings and wait for report */
|
||
|
if (netapp_ping_send(&ip_addr, attempts, size, timeout) != CC3000_SUCCESS) {
|
||
|
return false;
|
||
|
}
|
||
|
delay((timeout * attempts) * 2);
|
||
|
|
||
|
/* Copy output of ping report to return sruct */
|
||
|
memcpy(&ping_report, &g_ping_report, sizeof(PingReport));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Returns the status of DHCP
|
||
|
*
|
||
|
* @return True if DHCP has assigned an IP address. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::getDHCPStatus()
|
||
|
{
|
||
|
if (ulCC3000DHCP == 1) {
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Returns the status of connection to an access point
|
||
|
*
|
||
|
* @return True if connected. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::getConnectionStatus()
|
||
|
{
|
||
|
if (ulCC3000Connected == 1) {
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Returns the initialization state of the CC3000
|
||
|
*
|
||
|
* @return True if initialized. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::getInitStatus()
|
||
|
{
|
||
|
return is_initialized_;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Fills out ConnectionInfo struct with AP connection details
|
||
|
*
|
||
|
* @param[out] info struct containing information about the AP connection
|
||
|
* @return True if connection is valid. False otherwise.
|
||
|
*/
|
||
|
bool SFE_CC3000::getConnectionInfo(ConnectionInfo &info)
|
||
|
{
|
||
|
uint8_t i;
|
||
|
uint8_t max;
|
||
|
|
||
|
/* If CC3000 is not initialized, return false. */
|
||
|
if (!getInitStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If not connected, return false. */
|
||
|
if (!getConnectionStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* If DHCP has not been assigned, return false. */
|
||
|
if (!getDHCPStatus()) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Copy IP address to return struct. Reverse byte order. */
|
||
|
max = sizeof(connection_info_.aucIP);
|
||
|
for (i = 0; i < max; i++) {
|
||
|
info.ip_address[i] = connection_info_.aucIP[max - 1 - i];
|
||
|
}
|
||
|
|
||
|
/* Copy subnet mask to return struct. Reverse byte order. */
|
||
|
max = sizeof(connection_info_.aucSubnetMask);
|
||
|
for (i = 0; i < max; i++) {
|
||
|
info.subnet_mask[i] = connection_info_.aucSubnetMask[max - 1 - i];
|
||
|
}
|
||
|
|
||
|
/* Copy default gateway to return struct. Reverse byte order. */
|
||
|
max = sizeof(connection_info_.aucDefaultGateway);
|
||
|
for (i = 0; i < max; i++) {
|
||
|
info.default_gateway[i] = connection_info_.aucDefaultGateway[max -
|
||
|
1 - i];
|
||
|
}
|
||
|
|
||
|
/* Copy DHCP server address to return struct. Reverse byte order. */
|
||
|
max = sizeof(connection_info_.aucDHCPServer);
|
||
|
for (i = 0; i < max; i++) {
|
||
|
info.dhcp_server[i] = connection_info_.aucDHCPServer[max - 1 - i];
|
||
|
}
|
||
|
|
||
|
/* Copy DNS server address to return struct. Reverse byte order. */
|
||
|
max = sizeof(connection_info_.aucDNSServer);
|
||
|
for (i = 0; i < max; i++) {
|
||
|
info.dns_server[i] = connection_info_.aucDNSServer[max - 1 - i];
|
||
|
}
|
||
|
|
||
|
/* Copy MAC address to return struct. Reverse byte order. */
|
||
|
max = sizeof(connection_info_.uaMacAddr);
|
||
|
for (i = 0; i < max; i++) {
|
||
|
info.mac_address[i] = connection_info_.uaMacAddr[max - 1 - i];
|
||
|
}
|
||
|
|
||
|
/* Copy SSID to return struct. Keep byte order. */
|
||
|
memcpy(info.ssid, connection_info_.uaSSID, 32);
|
||
|
|
||
|
return true;
|
||
|
}
|