summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/pybwlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/pybwlan.c')
-rw-r--r--stmhal/pybwlan.c379
1 files changed, 379 insertions, 0 deletions
diff --git a/stmhal/pybwlan.c b/stmhal/pybwlan.c
new file mode 100644
index 0000000000..72cb9bfd98
--- /dev/null
+++ b/stmhal/pybwlan.c
@@ -0,0 +1,379 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "stm32f4xx_hal.h"
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.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(uint n_args, const mp_obj_t *args) {
+ const char *ap;
+ const char *key;
+ if (n_args == 2) {
+ ap = mp_obj_str_get_str(args[0]);
+ key = mp_obj_str_get_str(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 n_bytes) {
+ char data[64] = "";
+ if (n_bytes == 4) {
+ snprintf(data, 64, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]);
+ } else if (n_bytes == 6) {
+ snprintf(data, 64, "%02x:%02x:%02x:%02x:%02x:%02x", ip[5], ip[4], ip[3], ip[2], ip[1], ip[0]);
+ } else if (n_bytes == 32) {
+ snprintf(data, 64, "%s", ip);
+ }
+ return mp_obj_new_str((byte*)data, strlen(data), false);
+}
+
+void decode_addr_and_store(mp_obj_t object, qstr q_attr, unsigned char *ip, int n_bytes) {
+ mp_store_attr(object, q_attr, decode_addr(ip, n_bytes));
+}
+
+static mp_obj_t net_address_type = MP_OBJ_NULL;
+
+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;
+ }
+
+ // if it doesn't already exist, make a new empty class for NetAddress objects
+ if (net_address_type == MP_OBJ_NULL) {
+ net_address_type = mp_obj_new_type(QSTR_FROM_STR_STATIC("NetAddress"), mp_const_empty_tuple, mp_obj_new_dict(0));
+ }
+
+ // make a new NetAddress object
+ mp_obj_t net_addr = mp_call_function_0(net_address_type);
+
+ // fill the NetAddress object with data
+ decode_addr_and_store(net_addr, QSTR_FROM_STR_STATIC("ip"), &ipconfig.aucIP[0], 4);
+ decode_addr_and_store(net_addr, QSTR_FROM_STR_STATIC("subnet"), &ipconfig.aucSubnetMask[0], 4);
+ decode_addr_and_store(net_addr, QSTR_FROM_STR_STATIC("gateway"), &ipconfig.aucDefaultGateway[0], 4);
+ decode_addr_and_store(net_addr, QSTR_FROM_STR_STATIC("dhcp"), &ipconfig.aucDHCPServer[0], 4);
+ decode_addr_and_store(net_addr, QSTR_FROM_STR_STATIC("dns"), &ipconfig.aucDNSServer[0], 4);
+ decode_addr_and_store(net_addr, QSTR_FROM_STR_STATIC("mac"), &ipconfig.uaMacAddr[0], 6);
+ decode_addr_and_store(net_addr, QSTR_FROM_STR_STATIC("ssid"), &ipconfig.uaSSID[0], 32);
+
+ return net_addr;
+}
+
+uint32_t last_ip = 0; // XXX such a hack!
+mp_obj_t pyb_wlan_get_host(mp_obj_t host_name) {
+ const char *host = mp_obj_str_get_str(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_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unknown host"));
+ }
+ }
+ int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sd < 0) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "socket failed: %d", sd));
+ }
+ //printf("socket seemed to work\n");
+ //HAL_Delay(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_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "connect failed: %d", ret));
+ }
+ //printf("connect seemed to work\n");
+ //HAL_Delay(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", mp_obj_str_get_str(host_path), mp_obj_str_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_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "send failed"));
+ }
+ sent += ret;
+ //HAL_Delay(200);
+ }
+ }
+
+ //printf("send seemed to work!\n");
+ //HAL_Delay(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_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "recv failed %d", ret));
+ }
+ vstr_add_strn(vstr, buf, ret);
+ }
+
+ mp_ret = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
+ }
+
+ closesocket(sd);
+ vstr_free(vstr);
+
+ 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);
+ HAL_Delay(500);
+ if (sd < 0) {
+ printf("socket fail\n");
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "socket failed: %d", 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);
+ HAL_Delay(100);
+ if (ret != 0) {
+ printf("bind fail\n");
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "bind failed: %d", ret));
+ }
+ printf("bind seemed to work\n");
+
+ // listen
+ ret = listen(sd, 0);
+ printf("listen = %d\n", ret);
+ HAL_Delay(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);
+ HAL_Delay(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);
+ }
+ HAL_Delay(100);
+ }
+
+ // send some data
+ ret = send(fd, "test data!", 10, 0);
+ printf("send = %d\n", ret);
+ HAL_Delay(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_obj_new_module(QSTR_FROM_STR_STATIC("wlan"));
+ mp_store_attr(m, QSTR_FROM_STR_STATIC("connect"), mp_make_function_var(0, pyb_wlan_connect));
+ mp_store_attr(m, QSTR_FROM_STR_STATIC("disconnect"), mp_make_function_n(0, pyb_wlan_disconnect));
+ mp_store_attr(m, QSTR_FROM_STR_STATIC("ip"), mp_make_function_n(0, pyb_wlan_get_ip));
+ mp_store_attr(m, QSTR_FROM_STR_STATIC("get_host"), mp_make_function_n(1, pyb_wlan_get_host));
+ mp_store_attr(m, QSTR_FROM_STR_STATIC("http_get"), mp_make_function_n(2, pyb_wlan_http_get));
+ mp_store_attr(m, QSTR_FROM_STR_STATIC("serve"), mp_make_function_n(0, pyb_wlan_serve));
+ mp_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]);
+ */
+}