377 lines
11 KiB
C
377 lines
11 KiB
C
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stm32f4xx.h>
|
|
#include <stm32f4xx_rcc.h>
|
|
#include <stm32f4xx_gpio.h>
|
|
#include <stm32f4xx_tim.h>
|
|
#include <stm32f4xx_pwr.h>
|
|
#include <stm32f4xx_rtc.h>
|
|
#include <stm32f4xx_usart.h>
|
|
#include <stm_misc.h>
|
|
#include "std.h"
|
|
|
|
#include "misc.h"
|
|
#include "mpconfig.h"
|
|
#include "systick.h"
|
|
|
|
#include "nlr.h"
|
|
#include "misc.h"
|
|
#include "lexer.h"
|
|
#include "parse.h"
|
|
#include "compile.h"
|
|
#include "obj.h"
|
|
#include "runtime.h"
|
|
|
|
#include "cc3k/ccspi.h"
|
|
#include "cc3k/hci.h"
|
|
#include "cc3k/socket.h"
|
|
#include "cc3k/netapp.h"
|
|
#include "cc3k/wlan.h"
|
|
#include "cc3k/nvmem.h"
|
|
|
|
mp_obj_t pyb_wlan_connect(int n_args, const mp_obj_t *args) {
|
|
const char *ap;
|
|
const char *key;
|
|
if (n_args == 2) {
|
|
ap = qstr_str(mp_obj_get_qstr(args[0]));
|
|
key = qstr_str(mp_obj_get_qstr(args[1]));
|
|
} else {
|
|
ap = "your-ssid";
|
|
key = "your-password";
|
|
}
|
|
// might want to set wlan_ioctl_set_connection_policy
|
|
int ret = wlan_connect(WLAN_SEC_WPA2, ap, strlen(ap), NULL, (byte*)key, strlen(key));
|
|
return mp_obj_new_int(ret);
|
|
}
|
|
|
|
mp_obj_t pyb_wlan_disconnect(void) {
|
|
int ret = wlan_disconnect();
|
|
return mp_obj_new_int(ret);
|
|
}
|
|
|
|
mp_obj_t decode_addr(unsigned char *ip, int nBytes) {
|
|
char data[64] = "";
|
|
if (nBytes == 4) {
|
|
snprintf(data, 64, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]);
|
|
} else if (nBytes == 6) {
|
|
snprintf(data, 64, "%02x:%02x:%02x:%02x:%02x:%02x", ip[5], ip[4], ip[3], ip[2], ip[1], ip[0]);
|
|
} else if (nBytes == 32) {
|
|
snprintf(data, 64, "%s", ip);
|
|
}
|
|
return mp_obj_new_str(qstr_from_strn_copy(data, strlen(data)));
|
|
}
|
|
|
|
void _wlan_getIP_get_address(mp_obj_t object, qstr q_attr, unsigned char *ip, int nBytes) {
|
|
rt_store_attr(object, q_attr, decode_addr(ip, nBytes));
|
|
}
|
|
|
|
mp_obj_t pyb_wlan_get_ip(void) {
|
|
tNetappIpconfigRetArgs ipconfig;
|
|
netapp_ipconfig(&ipconfig);
|
|
|
|
/* If byte 1 is 0 we don't have a valid address */
|
|
if (ipconfig.aucIP[3] == 0) return mp_const_none;
|
|
|
|
mp_obj_t data = mp_module_new(); // TODO should really be a class
|
|
_wlan_getIP_get_address(data, qstr_from_str_static("ip"), &ipconfig.aucIP[0], 4);
|
|
_wlan_getIP_get_address(data, qstr_from_str_static("subnet"), &ipconfig.aucSubnetMask[0], 4);
|
|
_wlan_getIP_get_address(data, qstr_from_str_static("gateway"), &ipconfig.aucDefaultGateway[0], 4);
|
|
_wlan_getIP_get_address(data, qstr_from_str_static("dhcp"), &ipconfig.aucDHCPServer[0], 4);
|
|
_wlan_getIP_get_address(data, qstr_from_str_static("dns"), &ipconfig.aucDNSServer[0], 4);
|
|
_wlan_getIP_get_address(data, qstr_from_str_static("mac"), &ipconfig.uaMacAddr[0], 6);
|
|
_wlan_getIP_get_address(data, qstr_from_str_static("ssid"), &ipconfig.uaSSID[0], 32);
|
|
|
|
return data;
|
|
}
|
|
|
|
uint32_t last_ip = 0; // XXX such a hack!
|
|
mp_obj_t pyb_wlan_get_host(mp_obj_t host_name) {
|
|
const char *host = qstr_str(mp_obj_get_qstr(host_name));
|
|
uint32_t ip;
|
|
if (gethostbyname(host, strlen(host), &ip) < 0) {
|
|
printf("gethostbyname failed\n");
|
|
return mp_const_none;
|
|
}
|
|
if (ip == 0) {
|
|
// unknown host
|
|
return mp_const_none;
|
|
}
|
|
last_ip = ip;
|
|
byte ip_data[4];
|
|
ip_data[0] = ((ip >> 0) & 0xff);
|
|
ip_data[1] = ((ip >> 8) & 0xff);
|
|
ip_data[2] = ((ip >> 16) & 0xff);
|
|
ip_data[3] = ((ip >> 24) & 0xff);
|
|
return decode_addr(ip_data, 4);
|
|
}
|
|
|
|
mp_obj_t pyb_wlan_http_get(mp_obj_t host_name, mp_obj_t host_path) {
|
|
if (host_name == mp_const_none) {
|
|
last_ip = (192 << 24) | (168 << 16) | (0 << 8) | (3);
|
|
} else {
|
|
if (pyb_wlan_get_host(host_name) == mp_const_none) {
|
|
nlr_jump(mp_obj_new_exception_msg(qstr_from_str_static("WlanError"), "unknown host"));
|
|
}
|
|
}
|
|
int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (sd < 0) {
|
|
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd));
|
|
}
|
|
//printf("socket seemed to work\n");
|
|
//sys_tick_delay_ms(200);
|
|
sockaddr_in remote;
|
|
memset(&remote, 0, sizeof(sockaddr_in));
|
|
remote.sin_family = AF_INET;
|
|
remote.sin_port = htons(80);
|
|
remote.sin_addr.s_addr = htonl(last_ip);
|
|
int ret = connect(sd, (sockaddr*)&remote, sizeof(sockaddr));
|
|
if (ret != 0) {
|
|
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "connect failed: %d", (void*)ret));
|
|
}
|
|
//printf("connect seemed to work\n");
|
|
//sys_tick_delay_ms(200);
|
|
|
|
vstr_t *vstr = vstr_new();
|
|
vstr_printf(vstr, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: PYBv2\r\n\r\n", qstr_str(mp_obj_get_qstr(host_path)), qstr_str(mp_obj_get_qstr(host_name)));
|
|
const char *query = vstr_str(vstr);
|
|
|
|
// send query
|
|
{
|
|
int sent = 0;
|
|
while (sent < strlen(query)) {
|
|
/*
|
|
extern void SpiIntGPIOHandler(void);
|
|
SpiIntGPIOHandler();
|
|
*/
|
|
//printf("sending %d bytes\n", strlen(query + sent));
|
|
ret = send(sd, query + sent, strlen(query + sent), 0);
|
|
//printf("sent %d bytes\n", ret);
|
|
if (ret < 0) {
|
|
nlr_jump(mp_obj_new_exception_msg(qstr_from_str_static("WlanError"), "send failed"));
|
|
}
|
|
sent += ret;
|
|
//sys_tick_delay_ms(200);
|
|
}
|
|
}
|
|
|
|
//printf("send seemed to work!\n");
|
|
//sys_tick_delay_ms(5000);
|
|
|
|
// receive reply
|
|
mp_obj_t mp_ret = mp_const_none;
|
|
{
|
|
//printf("doing receive\n");
|
|
char buf[64];
|
|
vstr_reset(vstr);
|
|
|
|
for (;;) {
|
|
// do a select() call on this socket
|
|
timeval timeout;
|
|
fd_set fd_read;
|
|
|
|
memset(&fd_read, 0, sizeof(fd_read));
|
|
FD_SET(sd, &fd_read);
|
|
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 500000; // 500 millisec
|
|
|
|
int s = select(sd+1, &fd_read, NULL, NULL, &timeout);
|
|
if (s == 0) {
|
|
// no data available
|
|
break;
|
|
}
|
|
|
|
// read data
|
|
ret = recv(sd, buf, 64, 0);
|
|
if (ret < 0) {
|
|
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "recv failed %d", (void*)ret));
|
|
}
|
|
vstr_add_strn(vstr, buf, ret);
|
|
}
|
|
|
|
mp_ret = mp_obj_new_str(qstr_from_str_take(vstr_str(vstr)));
|
|
}
|
|
|
|
closesocket(sd);
|
|
|
|
return mp_ret;
|
|
}
|
|
|
|
mp_obj_t pyb_wlan_serve(void) {
|
|
printf("serve socket\n");
|
|
int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
printf("serve socket got %d\n", sd);
|
|
sys_tick_delay_ms(500);
|
|
if (sd < 0) {
|
|
printf("socket fail\n");
|
|
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd));
|
|
}
|
|
|
|
/*
|
|
if (setsockopt(sd, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, SOCK_ON, sizeof(SOCK_ON)) < 0) {
|
|
printf("couldn't set socket as non-blocking\n");
|
|
return mp_const_none;
|
|
}
|
|
*/
|
|
|
|
sockaddr_in remote;
|
|
memset(&remote, 0, sizeof(sockaddr_in));
|
|
remote.sin_family = AF_INET;
|
|
remote.sin_port = htons(8080);
|
|
remote.sin_addr.s_addr = htonl(0);
|
|
printf("serve bind\n");
|
|
int ret = bind(sd, (sockaddr*)&remote, sizeof(sockaddr));
|
|
printf("serve bind got %d\n", ret);
|
|
sys_tick_delay_ms(100);
|
|
if (ret != 0) {
|
|
printf("bind fail\n");
|
|
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "bind failed: %d", (void*)ret));
|
|
}
|
|
printf("bind seemed to work\n");
|
|
|
|
// listen
|
|
ret = listen(sd, 0);
|
|
printf("listen = %d\n", ret);
|
|
sys_tick_delay_ms(100);
|
|
|
|
// accept connections
|
|
int fd = -1;
|
|
for (;;) {
|
|
sockaddr accept_addr;
|
|
socklen_t accept_len;
|
|
fd = accept(sd, &accept_addr, &accept_len);
|
|
printf("accept = %d\n", fd);
|
|
sys_tick_delay_ms(500);
|
|
if (fd >= 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// receive some data
|
|
{
|
|
printf("receiving on sd=%d fd=%d\n", sd, fd);
|
|
char buf[64];
|
|
ret = recv(fd, buf, 64, 0);
|
|
printf("recv = %d\n", ret);
|
|
if (ret > 0) {
|
|
printf("****%.*s****\n", ret, buf);
|
|
}
|
|
sys_tick_delay_ms(100);
|
|
}
|
|
|
|
// send some data
|
|
ret = send(fd, "test data!", 10, 0);
|
|
printf("send = %d\n", ret);
|
|
sys_tick_delay_ms(100);
|
|
|
|
closesocket(fd);
|
|
closesocket(sd);
|
|
|
|
return mp_const_none;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! CC3000_UsynchCallback
|
|
//!
|
|
//! @param lEventType Event type
|
|
//! @param data
|
|
//! @param length
|
|
//!
|
|
//! @return none
|
|
//!
|
|
//! @brief The function handles asynchronous events that come from CC3000
|
|
//! device and operates a led for indicate
|
|
//
|
|
//*****************************************************************************
|
|
void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length)
|
|
{
|
|
if (lEventType == HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE)
|
|
{
|
|
//ulSmartConfigFinished = 1;
|
|
//ucStopSmartConfig = 1;
|
|
printf("WLAN: simple config done\n");
|
|
}
|
|
|
|
if (lEventType == HCI_EVNT_WLAN_UNSOL_CONNECT)
|
|
{
|
|
//ulCC3000Connected = 1;
|
|
printf("WLAN unsol connect\n");
|
|
}
|
|
|
|
if (lEventType == HCI_EVNT_WLAN_UNSOL_DISCONNECT)
|
|
{
|
|
//ulCC3000Connected = 0;
|
|
//ulCC3000DHCP = 0;
|
|
//ulCC3000DHCP_configured = 0;
|
|
printf("WLAN unsol disconnect\n");
|
|
}
|
|
|
|
if (lEventType == HCI_EVNT_WLAN_UNSOL_DHCP)
|
|
{
|
|
//ulCC3000DHCP = 1;
|
|
printf("WLAN unsol DHCP\n");
|
|
}
|
|
|
|
if (lEventType == HCI_EVENT_CC3000_CAN_SHUT_DOWN)
|
|
{
|
|
//OkToDoShutDown = 1;
|
|
printf("WLAN can shut down\n");
|
|
}
|
|
|
|
if (lEventType == HCI_EVNT_WLAN_ASYNC_PING_REPORT)
|
|
{
|
|
printf("WLAN async ping report\n");
|
|
//PRINT_F("CC3000: Ping report\n\r");
|
|
//pingReportnum++;
|
|
//memcpy(&pingReport, data, length);
|
|
}
|
|
|
|
if (lEventType == HCI_EVNT_BSD_TCP_CLOSE_WAIT) {
|
|
printf("WLAN bsd tcp close wait\n");
|
|
/*
|
|
uint8_t socketnum;
|
|
socketnum = data[0];
|
|
//PRINT_F("TCP Close wait #"); printDec(socketnum);
|
|
if (socketnum < MAX_SOCKETS)
|
|
closed_sockets[socketnum] = true;
|
|
*/
|
|
}
|
|
}
|
|
|
|
void pyb_wlan_init(void) {
|
|
SpiInit();
|
|
wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin);
|
|
|
|
mp_obj_t m = mp_module_new();
|
|
rt_store_attr(m, qstr_from_str_static("connect"), rt_make_function_var(0, pyb_wlan_connect));
|
|
rt_store_attr(m, qstr_from_str_static("disconnect"), rt_make_function_0(pyb_wlan_disconnect));
|
|
rt_store_attr(m, qstr_from_str_static("ip"), rt_make_function_0(pyb_wlan_get_ip));
|
|
rt_store_attr(m, qstr_from_str_static("get_host"), rt_make_function_1(pyb_wlan_get_host));
|
|
rt_store_attr(m, qstr_from_str_static("http_get"), rt_make_function_2(pyb_wlan_http_get));
|
|
rt_store_attr(m, qstr_from_str_static("serve"), rt_make_function_0(pyb_wlan_serve));
|
|
rt_store_name(qstr_from_str_static("wlan"), m);
|
|
}
|
|
|
|
void pyb_wlan_start(void) {
|
|
wlan_start(0);
|
|
|
|
// TODO: check return value !=0
|
|
|
|
wlan_ioctl_set_connection_policy(0, 0, 0); // don't auto-connect
|
|
wlan_ioctl_del_profile(255); // delete stored eeprom data
|
|
|
|
// Mask out all non-required events from CC3000
|
|
wlan_set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT |
|
|
//HCI_EVNT_WLAN_ASYNC_PING_REPORT |// we want ping reports
|
|
//HCI_EVNT_BSD_TCP_CLOSE_WAIT |
|
|
//HCI_EVNT_WLAN_TX_COMPLETE |
|
|
HCI_EVNT_WLAN_KEEPALIVE);
|
|
|
|
/*
|
|
byte ver[2];
|
|
int ret = nvmem_read_sp_version(ver);
|
|
printf("nvmem_read_sp_version=%d; %02x %02x\n", ret, ver[0], ver[1]);
|
|
*/
|
|
}
|