This example is a fairly complex program demonstrating the basic goal that drove BSP430 development: the ability to quickly develop tools to explore new capabilities in an interactive fashion without being tied to a particular MSP430 product line or board, and to abstract the capabilities as modules that could be used in other applications.
The example here uses the TI-provided host driver with a BSP430 SPI interface to provide an interactive program to invoke various capabilities of the SimpleLink hardware.
To build the program, you will need a copy of the CC3000 Host Driver. This application uses one that has been repackaged to place header files out of the application namespace, support MSPGCC, fix a few bugs, and support building as a library that can be linked into an application. It can be obtained from: http://github.com/pabigot/cc3000
The API is a command-line, it supports editing commands, and will accept the shortest unique command prefix. Below are the commands supported when built with the options above.
Although Smart Config can be used without encryption, you'll probably want to use it for any real-world application. The encryption key is stored in the NVMEM section of the CC3000. Display the NVMEM file table with this command:
If this table shows that file 12, which holds the AES key, does not have the available and valid flags (av
), create it:
The key must be ASCII and a full 16 characters. The FAT entry will update to mark the section valid:
You can now initiate the smart config process on your Android or IOS device, and at the demo application do the following:
Manual configuration works, but the startup procedure is slow. Smart Configuration is a pain when you have the ability to interact with the device. The following sequence shows how to store a set of profiles with priorities when the application is built with WITH_PROFILES=1
:
The CC3000 Host Driver library is independent of the underlying interface via SPI. A demonstration interface for specific MSP430 processors is part of the TI example programs, but it is rather confusing and has board-specific material tightly integrated.
The <bsp430/rf/cc3000spi.h> header bridges between the host driver and BSP430's serial abstraction following the specfication at the CC3000 Host Driver Porting Guide.
The bulk of the application is taken up with bridge code that interprets user input and invokes CC3000 host API calls. It is mostly of interest in that it demonstrates how to arrange command definitions so they can be easily included/excluded based on available memory.
#if (BSP430_CORE_TOOLCHAIN_GCC_MSPGCC - 0)
#include <sys/crtld.h>
#elif (BSP430_CORE_TOOLCHAIN_GCC_MSP430_ELF - 0)
#ifdef __MSP430F5438A__
#define __infob ((unsigned char *)0x1980)
#define __info_segment_size 128
#endif
#endif
#include <cc3000/host_driver_version.h>
#include <cc3000/wlan.h>
#include <cc3000/nvmem.h>
#include <cc3000/netapp.h>
#include <cc3000/hci.h>
#include <cc3000/security.h>
#include <cc3000/socket.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifndef BYPASS_SP_LOAD
#define BYPASS_SP_LOAD 0
#endif
#if ! (BSP430_PLATFORM_EXP430G2 - 0)
#define CMD_WLAN 1
#define CMD_WLAN_BROKEN 1
#define CMD_WLAN_STOP 1
#define CMD_WLAN_STATUS 1
#define CMD_WLAN_CONNECT 1
#define CMD_WLAN_IPCONFIG 1
#define CMD_WLAN_DISCONNECT 1
#define CMD_WLAN_START 1
#define CMD_WLAN_PROFILE 1
#if (BSP430_CC3000_ENABLE_SMART - 0) && (BSP430_CC3000SPI_RX_BUFFER_SIZE < 1500)
#error BSP430_CC3000_ENABLE_SMART requires BSP430_CC3000SPI_RX_BUFFER_SIZE >= 1500
#endif
#ifndef CMD_WLAN_SMART
#define CMD_WLAN_SMART (BSP430_CC3000SPI_RX_BUFFER_SIZE >= 1500)
#endif
#define CMD_NVMEM 1
#define CMD_NVMEM_SP 1
#define CMD_NVMEM_RMPARAM 1
#define CMD_NVMEM_READ 1
#define CMD_NVMEM_MAC 1
#define CMD_SCAN 1
#define CMD_INFO 1
#define CMD_HELP 1
#endif
#if (NO_HELP - 0)
#define HELP_STRING(h_) NULL
#else
#define HELP_STRING(h_) h_
#endif
#define MAGIC_CONNECT_PARAMS 0x3000
#define MAX_SSID_LEN 32
#define MAX_PASSPHRASE_LEN 64
typedef struct sConnectParams {
unsigned int magic;
int security_type;
size_t ssid_len;
size_t passphrase_len;
char ssid[MAX_SSID_LEN+1];
unsigned char passphrase[MAX_PASSPHRASE_LEN+1];
} sConnectParams;
static uint32_t lebtohl (uint8_t * vp)
{
return ((uint32_t)vp[0]
| ((uint32_t)vp[1] << 8)
| ((uint32_t)vp[2] << 16)
| ((uint32_t)vp[3] << 24));
}
static uint32_t bebtohl (uint8_t * vp)
{
return ((uint32_t)vp[3]
| ((uint32_t)vp[2] << 8)
| ((uint32_t)vp[1] << 16)
| ((uint32_t)vp[0] << 24));
}
const char *
ipv4AsText (const unsigned char * ipaddr)
{
static char buffer[16];
snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u", ipaddr[3], ipaddr[2], ipaddr[1], ipaddr[0]);
return buffer;
}
const char *
net_ipv4AsText (const unsigned char * ipaddr)
{
static char buffer[16];
snprintf(buffer, sizeof(buffer), "%u.%u.%u.%u", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
return buffer;
}
volatile unsigned long lastKeepAlive_utt;
volatile unsigned long lastCallback_utt;
volatile long lastEventType;
static void wlan_cb (long event_type,
char * data,
unsigned char length)
{
lastEventType = event_type;
if (HCI_EVNT_WLAN_KEEPALIVE == event_type) {
lastKeepAlive_utt = lastCallback_utt;
return;
}
cprintf(
"%s wlan_cb %#lx %u at %p SR %#x\n",
event_type, length, data, __read_status_register());
}
#define LAST_COMMAND NULL
#if (CMD_WLAN - 0)
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND NULL
#if (CMD_WLAN_STOP - 0)
static int
cmd_wlan_stop (const char * argstr)
{
wlan_stop();
return 0;
}
.help = HELP_STRING("# shut down CC3000"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_stop
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_stop
#endif
#if (CMD_WLAN_DISCONNECT - 0)
static int
cmd_wlan_disconnect (const char * argstr)
{
long rl = wlan_disconnect();
cprintf(
"disconnect returned %ld\n", rl);
return 0;
}
.help = HELP_STRING("# disconnect from AP"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_disconnect
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_disconnect
#endif
#if (CMD_WLAN_IPCONFIG - 0)
static int
cmd_wlan_ipconfig (const char * argstr)
{
tNetappIpconfigRetArgs ipc;
const unsigned char * p;
memset(&ipc, 0, sizeof(ipc));
netapp_ipconfig(&ipc);
cprintf(
"IP: %s\n", ipv4AsText(ipc.aucIP));
cprintf(
"NM: %s\n", ipv4AsText(ipc.aucSubnetMask));
cprintf(
"GW: %s\n", ipv4AsText(ipc.aucDefaultGateway));
cprintf(
"DHCP: %s\n", ipv4AsText(ipc.aucDHCPServer));
cprintf(
"DNS: %s\n", ipv4AsText(ipc.aucDNSServer));
p = ipc.uaMacAddr;
cprintf(
"MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
p[5], p[4], p[3], p[2], p[1], p[0]);
return 0;
}
.help = HELP_STRING("# show IP parameters"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_ipconfig
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_ipconfig
static int
cmd_wlan_dhcp (const char * argstr)
{
size_t argstr_len = strlen(argstr);
int store_ipc = 0;
long lrc;
union {
uint32_t u32;
uint8_t u8[4];
} address[4];
if (store_ipc) {
tNetappIpconfigRetArgs ipc;
memset(&ipc, 0, sizeof(ipc));
netapp_ipconfig(&ipc);
cprintf(
"Copying DHCP from IP config\n");
address[0].u32 = bebtohl(ipc.aucIP);
address[1].u32 = bebtohl(ipc.aucSubnetMask);
address[2].u32 = bebtohl(ipc.aucDefaultGateway);
address[3].u32 = bebtohl(ipc.aucDNSServer);
} else {
memset(address, 0, sizeof(address));
}
cprintf(
"IP: %s\n", net_ipv4AsText(address[0].u8));
cprintf(
"NM: %s\n", net_ipv4AsText(address[1].u8));
cprintf(
"GW: %s\n", net_ipv4AsText(address[2].u8));
cprintf(
"DNS: %s\n", net_ipv4AsText(address[3].u8));
lrc = netapp_dhcp(&address[0].u32,
&address[1].u32,
&address[2].u32,
&address[3].u32);
return 0;
}
.help = HELP_STRING("[1] # reset(0)/set(1) dhcp params"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_dhcp
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_dhcp
#endif
typedef struct sWlanSecMap {
unsigned int val;
const char * tag;
} sWlanSecMap;
static const sWlanSecMap wlanSecMap[] = {
{ WLAN_SEC_UNSEC, "unsec" },
{ WLAN_SEC_WEP, "wep" },
{ WLAN_SEC_WPA, "wpa" },
{ WLAN_SEC_WPA2, "wpa2" },
};
static const sWlanSecMap * const wlanSecMap_end = wlanSecMap + sizeof(wlanSecMap)/sizeof(*wlanSecMap);
static const sWlanSecMap * wlanSecMapFromValue (unsigned int val)
{
const sWlanSecMap * mp;
for (mp = wlanSecMap; mp < wlanSecMap_end; ++mp) {
if (mp->val == val) {
return mp;
}
}
return NULL;
}
static const sWlanSecMap * wlanSecMapFromTag (const char * tag)
{
const sWlanSecMap * mp;
for (mp = wlanSecMap; mp < wlanSecMap_end; ++mp) {
if (0 == strcmp(mp->tag, tag)) {
return mp;
}
}
return NULL;
}
#if (CMD_WLAN_CONNECT - 0)
sConnectParams connectParams;
static int
cmd_wlan_sectype (const char * argstr)
{
size_t remaining = strlen(argstr);
size_t len;
const char * tp;
const sWlanSecMap * mp;
if (0 < len) {
mp = wlanSecMapFromTag(tp);
if (0 != mp) {
connectParams.security_type = mp->val;
} else {
cprintf(
"ERR: Unrecognized sectype '%s': valid are", tp);
for (mp = wlanSecMap; mp < wlanSecMap_end; ++mp) {
}
}
}
mp = wlanSecMapFromValue(connectParams.security_type);
cprintf(
"AP security type is %s (%u)\n", (mp ? mp->tag :
"<UNDEF>"), connectParams.security_type);
return 0;
}
static int
cmd_wlan_ssid (const char * argstr)
{
size_t remaining = strlen(argstr);
size_t len;
const char * tp;
if (0 < len) {
memcpy(connectParams.ssid, tp, len);
connectParams.ssid[len] = 0;
connectParams.ssid_len = len;
}
cprintf(
"AP SSID is %s (%u chars)\n", connectParams.ssid, (
unsigned int)connectParams.ssid_len);
return 0;
}
static int
cmd_wlan_passphrase (const char * argstr)
{
size_t remaining = strlen(argstr);
size_t len;
const char * tp;
if (0 < len) {
if (sizeof(connectParams.passphrase) <= (len+1)) {
cprintf(
"ERR: Passphrase too long (> %u chars + EOS)\n", (
unsigned int)
sizeof(connectParams.passphrase));
} else {
memcpy(connectParams.passphrase, tp, len);
connectParams.passphrase[len] = 0;
connectParams.passphrase_len = len;
}
}
cprintf(
"AP passphrase is '%s' (%u chars)\n", connectParams.passphrase, (
unsigned int)connectParams.passphrase_len);
return 0;
}
static int
cmd_wlan_autocon (const char * argstr)
{
long rc;
int rv;
size_t argstr_len = strlen(argstr);
unsigned int should_connect_to_open_ap = 0;
unsigned int should_use_fast_connect = 1;
unsigned int use_profiles = 1;
uint8_t u32octets[4];
cprintf(
"Current connection policy:\n");
rc = nvmem_read(NVMEM_WLAN_CONFIG_FILEID, sizeof(uint32_t), 0x44, u32octets);
if (0 == rc) {
cprintf(
"should_connect_to_open_ap = 0x%08lx\n", lebtohl(u32octets));
}
rc = nvmem_read(NVMEM_WLAN_CONFIG_FILEID, sizeof(uint32_t), 0x48, u32octets);
if (0 == rc) {
cprintf(
"should_use_fast_connect = 0x%08lx\n", lebtohl(u32octets));
}
rc = nvmem_read(NVMEM_WLAN_CONFIG_FILEID, sizeof(uint32_t), 0x50, u32octets);
if (0 == rc) {
cprintf(
"use_profiles = 0x%08lx\n", lebtohl(u32octets));
}
if (0 == rv) {
}
if (0 == rv) {
}
cprintf(
"New connection policy: open_ap=%u fast_connect=%u use_profiles=%u\n",
should_connect_to_open_ap, should_use_fast_connect, use_profiles);
rc = wlan_ioctl_set_connection_policy(should_connect_to_open_ap, should_use_fast_connect, use_profiles);
cprintf(
"Connection policy set got %ld\n", rc);
return 0;
}
static int
cmd_wlan_connect (const char * argstr)
{
long rl;
const sWlanSecMap * mp;
unsigned long t[2];
mp = wlanSecMapFromValue(connectParams.security_type);
cprintf(
"connect to ssid '%s' by %s using '%s'\n",
connectParams.ssid, (mp ? mp->tag : "<UNDEF>"),
connectParams.passphrase);
rl = wlan_connect(connectParams.security_type,
connectParams.ssid, connectParams.ssid_len,
NULL,
connectParams.passphrase, connectParams.passphrase_len);
return 0;
}
.help = HELP_STRING("[{ssid}] # Display or set AP SSID for connect"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_ssid
};
.help = HELP_STRING("[{passphrase}] # Display or set AP passphrase"),
.next = &dcmd_wlan_ssid,
.param.simple_handler = cmd_wlan_passphrase
};
.help = HELP_STRING("[{sectype}] # Display or set AP sectype"),
.next = &dcmd_wlan_passphrase,
.param.simple_handler = cmd_wlan_sectype
};
.help = HELP_STRING("[open_ap=0 [fast_conn=1 [auto_conn=1]]]"),
.next = &dcmd_wlan_sectype,
.param.simple_handler = cmd_wlan_autocon
};
.help = HELP_STRING("# connect to specified access point using AP config"),
.next = &dcmd_wlan_autocon,
.param.simple_handler = cmd_wlan_connect
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_connect
#endif
#if (CMD_WLAN_PROFILE - 0)
static int
cmd_wlan_profile_del (const char * argstr)
{
size_t argstr_len = strlen(argstr);
long rc;
int profile = 255;
rc = wlan_ioctl_del_profile(profile);
cprintf(
"Del profile %d got %ld\n", profile, rc);
return 0;
}
typedef struct sProfileEntry {
unsigned int priority;
int security_type;
const char * ssid;
const char * passphrase;
} sProfileEntry;
static int
cmd_wlan_profile_update (const char * argstr)
{
static const sProfileEntry entries[] = {
#if (WITH_PROFILES - 0)
#include "profiles.inc"
#endif
};
const sProfileEntry * pep = entries;
const sProfileEntry * const pepe = pep + sizeof(entries)/sizeof(*entries);
long rc;
if (pep == pepe) {
cprintf(
"No profiles available\n");
return -1;
}
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2 0x00000002
#define WPA_CIPHER_NONE 0x01
#define WPA_CIPHER_WEP40 0x02
#define WPA_CIPHER_WEP104 0x04
#define WPA_CIPHER_TKIP 0x08
#define WPA_CIPHER_CCMP 0x10
while (pep < pepe) {
uint32_t pairwisecipher_or_keylen = 0;
uint32_t groupcipher_or_keyindex = 0;
uint32_t key_mgmt = 0;
uint8_t * pf_or_key = NULL;
uint32_t key_length = 0;
const sWlanSecMap * const mp = wlanSecMapFromValue(pep->security_type);
if (NULL != mp) {
if ((WLAN_SEC_WPA == pep->security_type)
|| (WLAN_SEC_WPA2 == pep->security_type)) {
pairwisecipher_or_keylen = WPA_CIPHER_TKIP | WPA_CIPHER_CCMP;
groupcipher_or_keyindex = WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104 | WPA_CIPHER_TKIP | WPA_CIPHER_CCMP;
key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
pf_or_key = (uint8_t*)pep->passphrase;
key_length = strlen(pep->passphrase);
} else if (WLAN_SEC_WEP == pep->security_type) {
pairwisecipher_or_keylen = strlen(pep->passphrase);
groupcipher_or_keyindex = 0;
key_mgmt = 0;
pf_or_key = (uint8_t*)pep->passphrase;
key_length = 0;
} else if (WLAN_SEC_UNSEC == pep->security_type) {
pairwisecipher_or_keylen = 0;
groupcipher_or_keyindex = 0;
key_mgmt = 0;
pf_or_key = NULL;
key_length = 0;
}
rc = wlan_add_profile(pep->security_type,
(uint8_t*)pep->ssid,
strlen(pep->ssid),
NULL,
pep->priority,
pairwisecipher_or_keylen,
groupcipher_or_keyindex,
key_mgmt,
pf_or_key,
key_length);
cprintf(
"Add SSID '%s' sec '%s' pri %u got %ld\n",
pep->ssid, mp->tag, pep->priority, rc);
} else {
cprintf(
"ERR: Profile %u %s has invalid security type %d\n",
(unsigned int)(pep - entries),
pep->ssid, pep->security_type);
}
++pep;
}
return 0;
}
.help = HELP_STRING("[profile=0] # delete profile, 255 for all"),
.next = NULL,
.param.simple_handler = cmd_wlan_profile_del
};
.help = HELP_STRING("[profile=0] # add configured profiles"),
.next = &dcmd_wlan_profile_del,
.param.simple_handler = cmd_wlan_profile_update
};
.next = LAST_SUB_COMMAND,
.child = &dcmd_wlan_profile_update
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_profile
#endif
#if (CMD_WLAN_SMART - 0)
static int
cmd_wlan_smart_aes (const char * argstr)
{
size_t argstr_len = strlen(argstr);
const char * key = NULL;
size_t keylen;
unsigned char keybuf[AES128_KEY_SIZE];
long rc;
while (isspace((unsigned char)*argstr)) {
++argstr;
}
argstr_len = strlen(argstr);
if (*argstr) {
memset(keybuf, 0, sizeof(keybuf));
if (sizeof(keybuf) < keylen) {
keylen = sizeof(keybuf);
}
memcpy(keybuf, key, keylen);
rc = aes_write_key(keybuf);
cprintf(
"aes_write_key got %ld\n", rc);
} else {
rc = aes_read_key(keybuf);
cprintf(
"aes_read_key got %ld\n", rc);
}
return 0;
}
static int
cmd_wlan_smart_process (const char * argstr)
{
long rc;
rc = wlan_smart_config_process();
cprintf(
"wlan_smart_config_process() got %ld\n", rc);
return 0;
}
static int
cmd_wlan_smart_stop (const char * argstr)
{
long rc;
rc = wlan_smart_config_stop();
cprintf(
"wlan_smart_config_stop() got %ld\n", rc);
return 0;
}
static int
cmd_wlan_smart_start (const char * argstr)
{
size_t argstr_len = strlen(argstr);
unsigned int encrypted = 0;
long rc;
{
char prefix[] = "123";
cprintf(
"Setting prefix to '%s'\n", prefix);
rc = wlan_smart_config_set_prefix(prefix);
cprintf(
"Prefix set returned %ld, now '%s'\n", rc, prefix);
}
if (encrypted) {
unsigned char keybuf[AES128_KEY_SIZE];
rc = aes_read_key(keybuf);
} else {
}
rc = wlan_smart_config_start(encrypted);
cprintf(
"wlan_smart_config_start(%d) got %ld\n", encrypted, rc);
return 0;
}
.help = HELP_STRING("[key] # set or read AES key"),
.next = NULL,
.param.simple_handler = cmd_wlan_smart_aes
};
.help = HELP_STRING("# process AES received data"),
.next = &dcmd_wlan_smart_aes,
.param.simple_handler = cmd_wlan_smart_process
};
.help = HELP_STRING("# stop smart config process"),
.next = &dcmd_wlan_smart_process,
.param.simple_handler = cmd_wlan_smart_stop
};
.help = HELP_STRING("[encrypted=0] # start smart config process"),
.next = &dcmd_wlan_smart_stop,
.param.simple_handler = cmd_wlan_smart_start
};
.next = LAST_SUB_COMMAND,
.child = &dcmd_wlan_smart_start
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_smart
#endif
#if (CMD_WLAN_STATUS - 0)
static int
cmd_wlan_status (const char * argstr)
{
static const char * status_str[] = {
"disconnected",
"scanning",
"connecting",
"connected"
};
long rl = wlan_ioctl_statusget();
#if (CMD_WLAN_CONNECT - 0)
{
const sWlanSecMap * mp;
mp = wlanSecMapFromValue(connectParams.security_type);
cprintf(
"AP configuration SSID '%s', passphrase '%s'\n",
connectParams.ssid, connectParams.passphrase);
cprintf(
"AP security type %s (%u)\n", (mp ? mp->tag :
"<UNDEF>"), connectParams.security_type);
}
#endif
if ((0 <= rl) && (rl < (sizeof(status_str)/sizeof(*status_str)))) {
}
return 0;
}
.help = HELP_STRING("# get CC3000 status and AP config"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_status
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_status
#endif
#if (CMD_WLAN_BROKEN - 0)
static int
cmd_wlan_timeouts (const char * argstr)
{
long rc;
struct {
unsigned long dhcp_s;
unsigned long arp_s;
unsigned long ka_s;
unsigned long inactive_s;
} params;
params.dhcp_s = 14400;
params.arp_s = 3600;
params.ka_s = 600000;
params.inactive_s = 600000;
cprintf(
"*** NOTE: No evidence this function works (KA does not)\n");
cprintf(
"DHCP timeout: %lu sec\n", params.dhcp_s);
cprintf(
"ARP timeout: %lu sec\n", params.arp_s);
cprintf(
"Keep-Alive timeout: %lu sec\n", params.ka_s);
cprintf(
"Inactive timeout: %lu sec\n", params.inactive_s);
rc = netapp_timeout_values(¶ms.dhcp_s, ¶ms.arp_s, ¶ms.ka_s, ¶ms.inactive_s);
cprintf(
"Timeout set got %ld\n", rc);
return 0;
}
.help = HELP_STRING("# set CC3000 timeouts"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_timeouts
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_timeouts
#endif
#if (CMD_WLAN_START - 0)
static int
cmd_wlan_start (const char * argstr)
{
size_t argstr_len = strlen(argstr);
unsigned int patches_available = 0;
unsigned long t[2];
wlan_start(patches_available);
return 0;
}
.help = HELP_STRING("[patchcount=0] # power-up CC3000"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_wlan_start
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_wlan_start
#endif
.next = LAST_COMMAND,
.child = LAST_SUB_COMMAND
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_wlan
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND NULL
#endif
#if (CMD_SCAN - 0)
#define X_WLAN_SCAN_STATUS_AGED 0
#define X_WLAN_SCAN_STATUS_VALID 1
#define X_WLAN_SCAN_STATUS_NONE 2
typedef struct sWLANFullScanResults {
uint32_t network_count;
uint32_t scan_status;
unsigned int isValid:1;
unsigned int rssi:7;
unsigned int securityMode:2;
unsigned int ssidNameLength:6;
uint16_t entryTime;
char ssid[32];
unsigned char bssid[6];
} sWLANFullScanResults;
static int
cmd_scan_show (const char * argstr)
{
size_t argstr_len = strlen(argstr);
int with_mem = 0;
long rc;
union {
sWLANFullScanResults structure;
unsigned char bytes[1];
} uresult;
const sWLANFullScanResults * const sp = &uresult.structure;
"SSID "
"Scty "
"BSSID "
"RSSI "
"Time"
"\n");
do {
rc = wlan_ioctl_get_scan_results(0, uresult.bytes);
if (0 != rc) {
break;
}
if (X_WLAN_SCAN_STATUS_NONE == sp->scan_status) {
break;
}
if (X_WLAN_SCAN_STATUS_AGED == sp->scan_status) {
break;
}
if (! sp->isValid) {
continue;
}
if (with_mem) {
}
{
const int nsp = sp->ssidNameLength;
int i;
for (i = 0; i < sizeof(sp->ssid); ++i) {
cputchar((i < nsp) ? sp->ssid[i] :
' ');
}
}
{
const sWlanSecMap * mp = wlanSecMapFromValue(sp->securityMode);
cprintf(
"%-5s ", (NULL == mp) ?
"???" : mp->tag);
}
{
int i;
for (i = 1; i < sizeof(sp->bssid); ++i) {
}
}
} while (1 < sp->network_count);
return 0;
}
static int
cmd_scan_start (const char * argstr)
{
size_t argstr_len = strlen(argstr);
unsigned long rc;
unsigned long interval_ms = 1;
unsigned long delays[16];
int i;
for (i = 0; i < sizeof(delays)/sizeof(*delays); ++i) {
delays[i] = 2000;
}
rc = wlan_ioctl_set_scan_params(interval_ms,
100,
150,
5,
0x7ff,
-80,
0,
205,
delays);
cprintf(
"Scan start %lu ms got %ld\n", interval_ms, rc);
return rc;
}
static int
cmd_scan_stop (const char * argstr)
{
unsigned long rc;
unsigned long delays[16];
int i;
for (i = 0; i < sizeof(delays)/sizeof(*delays); ++i) {
delays[i] = 2000;
}
rc = wlan_ioctl_set_scan_params(0, 150, 150, 5, 0x1fff, -80, 0, 205, delays);
cprintf(
"Scan stop got %ld\n", rc);
return rc;
}
.help = HELP_STRING(" [with_mem=0] # display scan results"),
.next = NULL,
.param.simple_handler = cmd_scan_show
};
.help = HELP_STRING("# disable periodic scan"),
.next = &dcmd_scan_show,
.param.simple_handler = cmd_scan_stop
};
.help = HELP_STRING(" [interval=1] # start periodic scan (ms)"),
.next = &dcmd_scan_stop,
.param.simple_handler = cmd_scan_start
};
.next = LAST_COMMAND,
.child = &dcmd_scan_start
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_scan
#endif
#if (CMD_NVMEM - 0)
typedef struct sNVMEMFileIds {
unsigned int fileid;
unsigned int size;
const char * tag;
} sNVMEMFileIds;
static const sNVMEMFileIds nvmemFiles[] = {
{ NVMEM_NVS_FILEID, 512, "NVS", },
{ NVMEM_NVS_SHADOW_FILEID, 512, "NVS (shadow)" },
{ NVMEM_WLAN_CONFIG_FILEID, 4096, "WLAN Config", },
{ NVMEM_WLAN_CONFIG_SHADOW_FILEID, 4096, "WLAN Config (shadow)" },
{ NVMEM_WLAN_DRIVER_SP_FILEID, 0, "WLAN Driver SP" },
{ NVMEM_WLAN_FW_SP_FILEID, 0, "WLAN Firmware SP" },
{ NVMEM_MAC_FILEID, 16, "MAC address" },
{ NVMEM_FRONTEND_VARS_FILEID, 0, "Front End Vars ??" },
{ NVMEM_IP_CONFIG_FILEID, 64, "IP Config" },
{ NVMEM_IP_CONFIG_SHADOW_FILEID, 64, "IP Config (shadow)" },
{ NVMEM_BOOTLOADER_SP_FILEID, 0, "Bootloader SP" },
{ NVMEM_RM_FILEID, 0, "Radio Module" },
{ NVMEM_AES128_KEY_FILEID, 0, "AES128 Key" },
{ NVMEM_SHARED_MEM_FILEID, 0, "Shared Memory ??" },
};
#if (WITH_UPDATE - 0)
const uint8_t wlan_drv_patch[] = {
#include "wlan_drv_patch.inc"
};
const uint8_t fw_patch[] = {
#include "fw_patch.inc"
};
static int
cmd_nvmem_update (const char * argstr)
{
int rc;
int stage;
const uint16_t drv_sp_size = sizeof(wlan_drv_patch);
const uint16_t fw_sp_size = sizeof(fw_patch);
uint16_t drv_sp_fatsize;
uint16_t fw_sp_fatsize;
do {
stage = __LINE__;
rc = nvmem_read(NVMEM_MAX_ENTRY, sizeof(drv_sp_fatsize), 4*(1 + NVMEM_WLAN_DRIVER_SP_FILEID) + 2, (uint8_t*)&drv_sp_fatsize);
if (0 != rc) {
break;
}
stage = __LINE__;
rc = nvmem_read(NVMEM_MAX_ENTRY, sizeof(drv_sp_fatsize), 4*(1 + NVMEM_WLAN_FW_SP_FILEID) + 2, (uint8_t*)&fw_sp_fatsize);
if (0 != rc) {
break;
}
cprintf(
"Driver update size %u, file size %u\n"
"Firmware update size %u, file size %u\n",
drv_sp_size, drv_sp_fatsize,
fw_sp_size, fw_sp_fatsize);
if ((0 == drv_sp_size) || (drv_sp_size > drv_sp_fatsize)) {
cprintf(
"ERROR: No driver, or driver too large\n");
return -1;
}
if ((0 == fw_sp_size) || (fw_sp_size > fw_sp_fatsize)) {
cprintf(
"ERROR: No firmware, or firmware too large\n");
return -1;
}
cprintf(
"Shutting down WLAN for driver update\n");
wlan_stop();
cprintf(
"Starting WLAN in patch mode\n");
wlan_start(2);
wlan_ioctl_set_connection_policy(0, 0, 0);
wlan_ioctl_del_profile(255);
wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|HCI_EVNT_WLAN_UNSOL_INIT|HCI_EVNT_WLAN_ASYNC_PING_REPORT);
cprintf(
"Updating driver firmware...");
stage = __LINE__;
rc = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID, drv_sp_size, (uint8_t *)wlan_drv_patch);
if (0 != rc) {
break;
}
"Updating firmware...");
stage = __LINE__;
rc = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID, fw_sp_size, (uint8_t *)fw_patch);
if (0 != rc) {
break;
}
"Shutting down WLAN after driver update\n");
wlan_stop();
cprintf(
"Restarting WLAN with new drivers\n");
wlan_start(0);
} while (0);
if (0 != rc) {
cprintf(
"ERROR %d in update at line %u\n", rc, stage);
}
return 0;
}
.help = HELP_STRING("# Update firmware"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_nvmem_update
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_nvmem_update
#endif
static int
cmd_nvmem_dir (const char * argstr)
{
int rc;
const unsigned int num_doc_files = sizeof(nvmemFiles) / sizeof(*nvmemFiles);
uint8_t fat[4*(NVMEM_MAX_ENTRY+1)];
const uint16_t * fp = (const uint16_t *)(fat+4);
const uint16_t * efp = (const uint16_t *)(fat+sizeof(fat));
int ffi = 0;
cprintf(
"%u NVMEM files with %u documented:\n", NVMEM_MAX_ENTRY, num_doc_files);
rc = nvmem_read(NVMEM_MAX_ENTRY, sizeof(fat), 0, fat);
if (0 != rc) {
cprintf(
"ERROR: nvmem read got %d\n", rc);
return 0;
}
if (('L' != fat[0]) || ('S' != fat[1])) {
cprintf(
"ERROR: nvmem signature %02x %02x not %02x %02x\n",
fat[0], fat[1], 'L', 'S');
return 0;
}
cprintf(
"ID Addr Size Flg : Doc ID Size Description\n");
while (fp < efp) {
(fp[0] &
BIT0) ?
'a' :
' ',
(fp[0] &
BIT1) ?
'v' :
' ',
(fp[0] &
BIT2) ?
'p' :
' ');
if (ffi < sizeof(nvmemFiles)/sizeof(*nvmemFiles)) {
nvmemFiles[ffi].fileid,
nvmemFiles[ffi].size,
nvmemFiles[ffi].tag);
}
++ffi;
fp += 2;
}
return 0;
}
.help = HELP_STRING("# describe NVMEM sections"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_nvmem_dir
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_nvmem_dir
static int
cmd_nvmem_create (const char * argstr)
{
size_t argstr_len = strlen(argstr);
unsigned int fileid = NVMEM_AES128_KEY_FILEID;
unsigned int length = AES128_KEY_SIZE;
long rc;
int rv;
if (0 == rv) {
}
rc = nvmem_create_entry(fileid, length);
cprintf(
"nvmem_create_entry(%u, %u) got %ld\n", fileid, length, rc);
return 0;
}
.help = HELP_STRING("[fileid=12 [length=16]] # create a new NVMEM section"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_nvmem_create
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_nvmem_create
#if (CMD_NVMEM_SP - 0)
static int
cmd_nvmem_sp (const char * argstr)
{
unsigned char patch_version[2];
unsigned char rv;
memset(patch_version, -1, sizeof(patch_version));
rv = nvmem_read_sp_version(patch_version);
cprintf(
"sp ret %u: %u.%u\n", rv, patch_version[0], patch_version[1]);
cprintf(
"Host driver %u\n", DRIVER_VERSION_NUMBER);
return 0;
}
.help = HELP_STRING("# read firmware service pack level"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_nvmem_sp
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_nvmem_sp
#endif
#if (CMD_NVMEM_RMPARAM - 0)
#if (WITH_RMPARAM - 0)
const uint8_t default_rm_param[] = {
#include "rm_param.inc"
};
#endif
static int
cmd_nvmem_rmparam (const char * argstr)
{
uint8_t rmparam[128];
const uint8_t * const rmpe = rmparam + sizeof(rmparam);
uint8_t * rp = rmparam;
int rc;
while (rp < rmpe) {
unsigned int offset = rp - rmparam;
unsigned int nb = rmpe - rp;
if (16 < nb) {
nb = 16;
}
rc = nvmem_read(NVMEM_RM_FILEID, nb, offset, rp);
if (0 != rc) {
cprintf(
"ERROR %d reading at offset %u\n", rc, offset);
return 0;
}
rp += nb;
}
cprintf(
"Radio module parameters:\n");
#if (WITH_RMPARAM - 0)
{
const uint8_t * drp = default_rm_param;
const uint8_t * const drpe = default_rm_param + sizeof(default_rm_param);
rp = rmparam;
while ((rp < rmpe) && (drp < drpe)) {
*rp++ ^= *drp++;
}
}
cprintf(
"Bitwise difference from default:\n");
cprintf(
"Default RM parameters:\n");
#endif
return 0;
}
.help = HELP_STRING("# display radio module parameters"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_nvmem_rmparam
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_nvmem_rmparam
#endif
#if (CMD_NVMEM_READ - 0)
static int
cmd_nvmem_read (const char * argstr)
{
int rc;
unsigned int fileid = 0;
unsigned int len = 128;
unsigned int ofs = 0;
unsigned char data[16];
unsigned int end_read;
unsigned int ui;
size_t argstr_len = strlen(argstr);
unsigned int nb;
if (0 == rc) {
fileid = ui;
}
if (0 == rc) {
len = ui;
}
if (0 == rc) {
ofs = ui;
}
end_read = ofs + len;
rc = 0;
while ((0 == rc) && (ofs < end_read)) {
nb = (end_read - ofs);
if (sizeof(data) < nb) {
nb = sizeof(data);
}
rc = nvmem_read(fileid, nb, ofs, data);
if (0 == rc) {
ofs += nb;
}
}
if (0 != rc) {
cprintf(
"\nERR: Read returned %u for %u bytes at %u of fileid %u\n",
rc, nb, ofs, fileid);
}
return 0;
}
.help = HELP_STRING("fileid [len(=128) [ofs(=0)]] # read block from nvmem file"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_nvmem_read
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_nvmem_read
#endif
#if (CMD_NVMEM_MAC - 0)
static int
cmd_nvmem_mac (const char * argstr)
{
int rc;
unsigned char mac[6];
rc = nvmem_get_mac_address(mac);
if (0 == rc) {
cprintf(
"nvmem mac is %02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} else {
cprintf(
"ERR: nvmem mac read got %u\n", rc);
}
return 0;
}
.help = HELP_STRING("# get mac address"),
.next = LAST_SUB_COMMAND,
.param.simple_handler = cmd_nvmem_mac
};
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND &dcmd_nvmem_mac
#endif
.next = LAST_COMMAND,
.child = LAST_SUB_COMMAND
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_nvmem
#undef LAST_SUB_COMMAND
#define LAST_SUB_COMMAND NULL
#endif
#if ! (BSP430_MODULE_FLASH - 0)
#undef CMD_INFO
#endif
#if (CMD_INFO - 0)
static sConnectParams * const infoConnectParams = (sConnectParams *)__infob;
static int
cmd_info_load (const char * argstr)
{
if (MAGIC_CONNECT_PARAMS != infoConnectParams->magic) {
cprintf(
"ERR: Stored connection params invalid\n");
return -1;
}
#if (CMD_WLAN_CONNECT - 0)
connectParams = *infoConnectParams;
#endif
return 0;
}
static int
cmd_info_erase_ni (void)
{
int rv;
cprintf(
"Erasing stored params at %p...", infoConnectParams);
return rv;
}
static int
cmd_info_erase (const char * argstr)
{
int rv;
do {
rv = cmd_info_erase_ni();
} while (0);
return rv;
}
static int
cmd_info_store (const char * argstr)
{
int rv;
do {
rv = cmd_info_erase_ni();
if (0 == rv) {
connectParams.magic = MAGIC_CONNECT_PARAMS;
cprintf(
"Copying current configuration...");
}
} while (0);
return rv;
}
static int
cmd_info_dump (const char * argstr)
{
cprintf(
"Configuration memory:\n");
return 0;
}
.help = HELP_STRING("# display INFO_B contents"),
.next = NULL,
.param.simple_handler = cmd_info_dump
};
.help = HELP_STRING("# store wlan AP params in INFO_B"),
.next = &dcmd_info_dump,
.param.simple_handler = cmd_info_store
};
.help = HELP_STRING("# erase INFO_B"),
.next = &dcmd_info_store,
.param.simple_handler = cmd_info_erase
};
.help = HELP_STRING("# load wlan AP params from INFO_B"),
.next = &dcmd_info_erase,
.param.simple_handler = cmd_info_load
};
.next = LAST_COMMAND,
.child = &dcmd_info_load
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_info
#endif
static int
cmd_mdns (const char * argstr)
{
size_t argstr_len = strlen(argstr);
const char * name = "CC3000";
size_t name_len;
int rc;
if (0 == name_len) {
rc = mdnsAdvertiser(0, "CC3000", strlen("CC3000"));
} else {
int i;
for (i = 0; i < name_len; ++i) {
}
rc = mdnsAdvertiser(1, (char *)name, name_len);
}
cprintf(
"mdnsAdvertiser got %d\n", rc);
return 0;
}
.help = HELP_STRING("[name] # enable/disable mDNS"),
.next = LAST_COMMAND,
.param.simple_handler = cmd_mdns
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_mdns
static int
cmd_uptime (const char * argstr)
{
unsigned long now_utt;
return 0;
}
.next = LAST_COMMAND,
.param.simple_handler = cmd_uptime
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_uptime
static int
cmd_ghbn (const char * argstr)
{
size_t argstr_len = strlen(argstr);
const char * name;
size_t name_len;
uint32_t addr = -1;
int rc;
if (0 == name_len) {
name = "ntp.pool.org";
name_len = strlen(name);
}
rc = gethostbyname((char*)name, name_len, &addr);
cprintf(
"gethostbyname(%s) returned %d, ip: %s\n", name, rc, ipv4AsText((
const uint8_t*)&addr));
return 0;
}
.next = LAST_COMMAND,
.param.simple_handler = cmd_ghbn
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_ghbn
static int
void * param,
const char * command,
size_t command_len)
{
return 0;
}
.next = LAST_COMMAND,
.handler = cmd_test
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_test
#if (CMD_HELP - 0)
static int
void * param,
const char * command,
size_t command_len)
{
return 0;
}
.next = LAST_COMMAND,
.handler = cmd_help
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_help
#endif
void main (void)
{
int rv;
const char * command;
int flags;
#if (BSP430_MODULE_SYS - 0)
unsigned long reset_causes = 0;
unsigned int reset_flags = 0;
#endif
#if (BSP430_MODULE_SYS - 0)
{
unsigned int sysrstiv;
reset_causes |= 1UL << (sysrstiv / 2);
}
#ifdef BSP430_PMM_ENTER_LPMXp5_NI
if (reset_flags & BSP430_SYS_FLAG_SYSRST_LPM5WU) {
PMMCTL0_H = PMMPW_H;
PM5CTL0 = 0;
PMMCTL0_H = 0;
}
#endif
}
#endif
cprintf(
"\ncc3000 " __DATE__
" " __TIME__
"\n");
#if (BSP430_MODULE_SYS - 0)
cprintf(
"System reset bitmask %lx; causes:\n", reset_causes);
{
int bit = 0;
while (bit < (8 * sizeof(reset_causes))) {
if (reset_causes & (1UL << bit)) {
}
++bit;
}
}
if (reset_flags) {
if (reset_flags & BSP430_SYS_FLAG_SYSRST_BOR) {
}
if (reset_flags & BSP430_SYS_FLAG_SYSRST_LPM5WU) {
}
if (reset_flags & BSP430_SYS_FLAG_SYSRST_POR) {
}
if (reset_flags & BSP430_SYS_FLAG_SYSRST_PUC) {
}
} else {
}
#endif
#ifdef BSP430_RF_CC3000_PWR_EN_PORT_PERIPH_HANDLE
#else
#endif
#if BSP430_PLATFORM_PERIPHERAL_HELP
#endif
cprintf(
"CC3000 host driver: %u\n", DRIVER_VERSION_NUMBER);
cprintf(
"RX buffer size %u, TX buffer size %u\n",
cprintf(__DATE__
" " __TIME__
"\n");
if (0 > rv) {
cprintf(
"Aborting due to failure to initialized\n");
return;
}
commandSet = LAST_COMMAND;
command = NULL;
#if (BYPASS_SP_LOAD - 0)
cprintf(
"Bypassing service packs\n");
wlan_start(2);
#else
wlan_start(0);
#endif
cprintf(
"\nAnd wlan has been started.\n");
rv = wlan_set_event_mask(0);
cprintf(
"Unmask events returned %d\n", rv);
#if (CMD_INFO - 0)
if (0 == cmd_info_load("")) {
cmd_wlan_status("");
}
#endif
while (1) {
if (flags & eBSP430cliConsole_DO_COMPLETION) {
flags &= ~eBSP430cliConsole_DO_COMPLETION;
}
if (flags & eBSP430cliConsole_READY) {
int rv;
if (0 != rv) {
cprintf(
"Command execution returned %d\n", rv);
}
command = NULL;
}
if (flags & eBSP430cliConsole_REPAINT) {
cprintf(
"\r> %s", command ? command :
"");
flags &= ~eBSP430cliConsole_REPAINT;
}
if (flags & eBSP430cliConsole_REPAINT_BEL) {
flags &= ~eBSP430cliConsole_REPAINT_BEL;
}
if (flags & eBSP430cliConsole_READY) {
flags &= ~eBSP430cliConsole_READY;
}
do {
if (0 == flags) {
}
if (0 == flags) {
}
} while (! flags);
}
}