Damien | 065f8a5 | 2013-12-05 20:38:23 +0000 | [diff] [blame] | 1 | #include <stdlib.h> |
| 2 | #include <stdint.h> |
| 3 | #include <stm32f4xx.h> |
| 4 | #include <stm32f4xx_rcc.h> |
| 5 | #include <stm32f4xx_gpio.h> |
| 6 | #include <stm32f4xx_tim.h> |
| 7 | #include <stm32f4xx_pwr.h> |
| 8 | #include <stm32f4xx_rtc.h> |
| 9 | #include <stm32f4xx_usart.h> |
| 10 | #include <stm_misc.h> |
| 11 | #include "std.h" |
| 12 | |
| 13 | #include "misc.h" |
| 14 | #include "mpyconfig.h" |
| 15 | #include "systick.h" |
| 16 | |
| 17 | #include "nlr.h" |
| 18 | #include "misc.h" |
| 19 | #include "lexer.h" |
| 20 | #include "parse.h" |
| 21 | #include "compile.h" |
| 22 | #include "runtime.h" |
| 23 | |
| 24 | #include "cc3k/ccspi.h" |
| 25 | #include "cc3k/hci.h" |
| 26 | #include "cc3k/socket.h" |
| 27 | #include "cc3k/netapp.h" |
| 28 | #include "cc3k/wlan.h" |
| 29 | #include "cc3k/nvmem.h" |
| 30 | |
| 31 | py_obj_t pyb_wlan_connect(int n_args, const py_obj_t *args) { |
| 32 | const char *ap; |
| 33 | const char *key; |
| 34 | if (n_args == 2) { |
| 35 | ap = qstr_str(py_obj_get_qstr(args[0])); |
| 36 | key = qstr_str(py_obj_get_qstr(args[1])); |
| 37 | } else { |
| 38 | ap = "Rama3"; |
| 39 | key = "underthechristmastree"; |
| 40 | } |
| 41 | // might want to set wlan_ioctl_set_connection_policy |
| 42 | int ret = wlan_connect(WLAN_SEC_WPA2, ap, strlen(ap), NULL, (byte*)key, strlen(key)); |
| 43 | return py_obj_new_int(ret); |
| 44 | } |
| 45 | |
| 46 | py_obj_t pyb_wlan_disconnect(void) { |
| 47 | int ret = wlan_disconnect(); |
| 48 | return py_obj_new_int(ret); |
| 49 | } |
| 50 | |
| 51 | py_obj_t decode_addr(unsigned char *ip, int nBytes) { |
| 52 | char data[64] = ""; |
| 53 | if (nBytes == 4) { |
| 54 | snprintf(data, 64, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]); |
| 55 | } else if (nBytes == 6) { |
| 56 | snprintf(data, 64, "%02x:%02x:%02x:%02x:%02x:%02x", ip[5], ip[4], ip[3], ip[2], ip[1], ip[0]); |
| 57 | } else if (nBytes == 32) { |
| 58 | snprintf(data, 64, "%s", ip); |
| 59 | } |
| 60 | return py_obj_new_str(qstr_from_strn_copy(data, strlen(data))); |
| 61 | } |
| 62 | |
| 63 | void _wlan_getIP_get_address(py_obj_t object, qstr q_attr, unsigned char *ip, int nBytes) { |
| 64 | rt_store_attr(object, q_attr, decode_addr(ip, nBytes)); |
| 65 | } |
| 66 | |
| 67 | py_obj_t pyb_wlan_get_ip(void) { |
| 68 | tNetappIpconfigRetArgs ipconfig; |
| 69 | netapp_ipconfig(&ipconfig); |
| 70 | |
| 71 | /* If byte 1 is 0 we don't have a valid address */ |
| 72 | if (ipconfig.aucIP[3] == 0) return py_const_none; |
| 73 | |
| 74 | py_obj_t data = py_module_new(); // TODO should really be a class |
| 75 | _wlan_getIP_get_address(data, qstr_from_str_static("ip"), &ipconfig.aucIP[0], 4); |
| 76 | _wlan_getIP_get_address(data, qstr_from_str_static("subnet"), &ipconfig.aucSubnetMask[0], 4); |
| 77 | _wlan_getIP_get_address(data, qstr_from_str_static("gateway"), &ipconfig.aucDefaultGateway[0], 4); |
| 78 | _wlan_getIP_get_address(data, qstr_from_str_static("dhcp"), &ipconfig.aucDHCPServer[0], 4); |
| 79 | _wlan_getIP_get_address(data, qstr_from_str_static("dns"), &ipconfig.aucDNSServer[0], 4); |
| 80 | _wlan_getIP_get_address(data, qstr_from_str_static("mac"), &ipconfig.uaMacAddr[0], 6); |
| 81 | _wlan_getIP_get_address(data, qstr_from_str_static("ssid"), &ipconfig.uaSSID[0], 32); |
| 82 | |
| 83 | return data; |
| 84 | } |
| 85 | |
| 86 | uint32_t last_ip = 0; // XXX such a hack! |
| 87 | py_obj_t pyb_wlan_get_host(py_obj_t host_name) { |
| 88 | const char *host = qstr_str(py_obj_get_qstr(host_name)); |
| 89 | uint32_t ip; |
| 90 | if (gethostbyname(host, strlen(host), &ip) < 0) { |
| 91 | printf("gethostbyname failed\n"); |
| 92 | return py_const_none; |
| 93 | } |
| 94 | if (ip == 0) { |
| 95 | // unknown host |
| 96 | return py_const_none; |
| 97 | } |
| 98 | last_ip = ip; |
| 99 | byte ip_data[4]; |
| 100 | ip_data[0] = ((ip >> 0) & 0xff); |
| 101 | ip_data[1] = ((ip >> 8) & 0xff); |
| 102 | ip_data[2] = ((ip >> 16) & 0xff); |
| 103 | ip_data[3] = ((ip >> 24) & 0xff); |
| 104 | return decode_addr(ip_data, 4); |
| 105 | } |
| 106 | |
| 107 | py_obj_t py_obj_new_exception_2(qstr, const char *, void*, void*); |
| 108 | |
| 109 | py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) { |
| 110 | if (host_name == py_const_none) { |
| 111 | last_ip = (192 << 24) | (168 << 16) | (0 << 8) | (3); |
| 112 | } else { |
| 113 | if (pyb_wlan_get_host(host_name) == py_const_none) { |
| 114 | nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "unknown host", NULL, NULL)); |
| 115 | } |
| 116 | } |
| 117 | int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 118 | if (sd < 0) { |
| 119 | nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd, NULL)); |
| 120 | } |
| 121 | //printf("socket seemed to work\n"); |
| 122 | //sys_tick_delay_ms(200); |
| 123 | sockaddr_in remote; |
| 124 | memset(&remote, 0, sizeof(sockaddr_in)); |
| 125 | remote.sin_family = AF_INET; |
| 126 | remote.sin_port = htons(80); |
| 127 | remote.sin_addr.s_addr = htonl(last_ip); |
| 128 | int ret = connect(sd, (sockaddr*)&remote, sizeof(sockaddr)); |
| 129 | if (ret != 0) { |
| 130 | nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "connect failed: %d", (void*)ret, NULL)); |
| 131 | } |
| 132 | //printf("connect seemed to work\n"); |
| 133 | //sys_tick_delay_ms(200); |
| 134 | |
| 135 | vstr_t *vstr = vstr_new(); |
| 136 | vstr_printf(vstr, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: PYBv2\r\n\r\n", qstr_str(py_obj_get_qstr(host_path)), qstr_str(py_obj_get_qstr(host_name))); |
| 137 | const char *query = vstr_str(vstr); |
| 138 | |
| 139 | // send query |
| 140 | { |
| 141 | int sent = 0; |
| 142 | while (sent < strlen(query)) { |
| 143 | /* |
| 144 | extern void SpiIntGPIOHandler(void); |
| 145 | SpiIntGPIOHandler(); |
| 146 | */ |
| 147 | //printf("sending %d bytes\n", strlen(query + sent)); |
| 148 | ret = send(sd, query + sent, strlen(query + sent), 0); |
| 149 | //printf("sent %d bytes\n", ret); |
| 150 | if (ret < 0) { |
| 151 | nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "send failed", NULL, NULL)); |
| 152 | } |
| 153 | sent += ret; |
| 154 | //sys_tick_delay_ms(200); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | //printf("send seemed to work!\n"); |
| 159 | //sys_tick_delay_ms(5000); |
| 160 | |
| 161 | // receive reply |
| 162 | py_obj_t py_ret = py_const_none; |
| 163 | { |
| 164 | //printf("doing receive\n"); |
| 165 | char buf[64]; |
| 166 | vstr_reset(vstr); |
| 167 | |
| 168 | for (;;) { |
| 169 | // do a select() call on this socket |
| 170 | timeval timeout; |
| 171 | fd_set fd_read; |
| 172 | |
| 173 | memset(&fd_read, 0, sizeof(fd_read)); |
| 174 | FD_SET(sd, &fd_read); |
| 175 | |
| 176 | timeout.tv_sec = 0; |
| 177 | timeout.tv_usec = 500000; // 500 millisec |
| 178 | |
| 179 | int s = select(sd+1, &fd_read, NULL, NULL, &timeout); |
| 180 | if (s == 0) { |
| 181 | // no data available |
| 182 | break; |
| 183 | } |
| 184 | |
| 185 | // read data |
| 186 | ret = recv(sd, buf, 64, 0); |
| 187 | if (ret < 0) { |
| 188 | nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "recv failed %d", (void*)ret, NULL)); |
| 189 | } |
| 190 | vstr_add_strn(vstr, buf, ret); |
| 191 | } |
| 192 | |
| 193 | py_ret = py_obj_new_str(qstr_from_str_take(vstr_str(vstr))); |
| 194 | } |
| 195 | |
| 196 | closesocket(sd); |
| 197 | |
| 198 | return py_ret; |
| 199 | } |
| 200 | |
| 201 | py_obj_t pyb_wlan_serve(void) { |
| 202 | printf("serve socket\n"); |
| 203 | int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 204 | printf("serve socket got %d\n", sd); |
| 205 | sys_tick_delay_ms(500); |
| 206 | if (sd < 0) { |
| 207 | printf("socket fail\n"); |
| 208 | nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd, NULL)); |
| 209 | } |
| 210 | |
| 211 | /* |
| 212 | if (setsockopt(sd, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, SOCK_ON, sizeof(SOCK_ON)) < 0) { |
| 213 | printf("couldn't set socket as non-blocking\n"); |
| 214 | return py_const_none; |
| 215 | } |
| 216 | */ |
| 217 | |
| 218 | sockaddr_in remote; |
| 219 | memset(&remote, 0, sizeof(sockaddr_in)); |
| 220 | remote.sin_family = AF_INET; |
| 221 | remote.sin_port = htons(8080); |
| 222 | remote.sin_addr.s_addr = htonl(0); |
| 223 | printf("serve bind\n"); |
| 224 | int ret = bind(sd, (sockaddr*)&remote, sizeof(sockaddr)); |
| 225 | printf("serve bind got %d\n", ret); |
| 226 | sys_tick_delay_ms(100); |
| 227 | if (ret != 0) { |
| 228 | printf("bind fail\n"); |
| 229 | nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "bind failed: %d", (void*)ret, NULL)); |
| 230 | } |
| 231 | printf("bind seemed to work\n"); |
| 232 | |
| 233 | // listen |
| 234 | ret = listen(sd, 0); |
| 235 | printf("listen = %d\n", ret); |
| 236 | sys_tick_delay_ms(100); |
| 237 | |
| 238 | // accept connections |
| 239 | int fd = -1; |
| 240 | for (;;) { |
| 241 | sockaddr accept_addr; |
| 242 | socklen_t accept_len; |
| 243 | fd = accept(sd, &accept_addr, &accept_len); |
| 244 | printf("accept = %d\n", fd); |
| 245 | sys_tick_delay_ms(500); |
| 246 | if (fd >= 0) { |
| 247 | break; |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | // receive some data |
| 252 | { |
| 253 | printf("receiving on sd=%d fd=%d\n", sd, fd); |
| 254 | char buf[64]; |
| 255 | ret = recv(fd, buf, 64, 0); |
| 256 | printf("recv = %d\n", ret); |
| 257 | if (ret > 0) { |
| 258 | printf("****%.*s****\n", ret, buf); |
| 259 | } |
| 260 | sys_tick_delay_ms(100); |
| 261 | } |
| 262 | |
| 263 | // send some data |
| 264 | ret = send(fd, "test data!", 10, 0); |
| 265 | printf("send = %d\n", ret); |
| 266 | sys_tick_delay_ms(100); |
| 267 | |
| 268 | closesocket(fd); |
| 269 | closesocket(sd); |
| 270 | |
| 271 | return py_const_none; |
| 272 | } |
| 273 | |
| 274 | //***************************************************************************** |
| 275 | // |
| 276 | //! CC3000_UsynchCallback |
| 277 | //! |
| 278 | //! @param lEventType Event type |
| 279 | //! @param data |
| 280 | //! @param length |
| 281 | //! |
| 282 | //! @return none |
| 283 | //! |
| 284 | //! @brief The function handles asynchronous events that come from CC3000 |
| 285 | //! device and operates a led for indicate |
| 286 | // |
| 287 | //***************************************************************************** |
| 288 | void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length) |
| 289 | { |
| 290 | if (lEventType == HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE) |
| 291 | { |
| 292 | //ulSmartConfigFinished = 1; |
| 293 | //ucStopSmartConfig = 1; |
| 294 | printf("WLAN: simple config done\n"); |
| 295 | } |
| 296 | |
| 297 | if (lEventType == HCI_EVNT_WLAN_UNSOL_CONNECT) |
| 298 | { |
| 299 | //ulCC3000Connected = 1; |
| 300 | printf("WLAN unsol connect\n"); |
| 301 | } |
| 302 | |
| 303 | if (lEventType == HCI_EVNT_WLAN_UNSOL_DISCONNECT) |
| 304 | { |
| 305 | //ulCC3000Connected = 0; |
| 306 | //ulCC3000DHCP = 0; |
| 307 | //ulCC3000DHCP_configured = 0; |
| 308 | printf("WLAN unsol disconnect\n"); |
| 309 | } |
| 310 | |
| 311 | if (lEventType == HCI_EVNT_WLAN_UNSOL_DHCP) |
| 312 | { |
| 313 | //ulCC3000DHCP = 1; |
| 314 | printf("WLAN unsol DHCP\n"); |
| 315 | } |
| 316 | |
| 317 | if (lEventType == HCI_EVENT_CC3000_CAN_SHUT_DOWN) |
| 318 | { |
| 319 | //OkToDoShutDown = 1; |
| 320 | printf("WLAN can shut down\n"); |
| 321 | } |
| 322 | |
| 323 | if (lEventType == HCI_EVNT_WLAN_ASYNC_PING_REPORT) |
| 324 | { |
| 325 | printf("WLAN async ping report\n"); |
| 326 | //PRINT_F("CC3000: Ping report\n\r"); |
| 327 | //pingReportnum++; |
| 328 | //memcpy(&pingReport, data, length); |
| 329 | } |
| 330 | |
| 331 | if (lEventType == HCI_EVNT_BSD_TCP_CLOSE_WAIT) { |
| 332 | printf("WLAN bsd tcp close wait\n"); |
| 333 | /* |
| 334 | uint8_t socketnum; |
| 335 | socketnum = data[0]; |
| 336 | //PRINT_F("TCP Close wait #"); printDec(socketnum); |
| 337 | if (socketnum < MAX_SOCKETS) |
| 338 | closed_sockets[socketnum] = true; |
| 339 | */ |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | void pyb_wlan_init(void) { |
| 344 | SpiInit(); |
| 345 | wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin); |
| 346 | |
| 347 | py_obj_t m = py_module_new(); |
| 348 | rt_store_attr(m, qstr_from_str_static("connect"), rt_make_function_var(0, pyb_wlan_connect)); |
| 349 | rt_store_attr(m, qstr_from_str_static("disconnect"), rt_make_function_0(pyb_wlan_disconnect)); |
| 350 | rt_store_attr(m, qstr_from_str_static("ip"), rt_make_function_0(pyb_wlan_get_ip)); |
| 351 | rt_store_attr(m, qstr_from_str_static("get_host"), rt_make_function_1(pyb_wlan_get_host)); |
| 352 | rt_store_attr(m, qstr_from_str_static("http_get"), rt_make_function_2(pyb_wlan_http_get)); |
| 353 | rt_store_attr(m, qstr_from_str_static("serve"), rt_make_function_0(pyb_wlan_serve)); |
| 354 | rt_store_name(qstr_from_str_static("wlan"), m); |
| 355 | } |
| 356 | |
| 357 | void pyb_wlan_start(void) { |
| 358 | wlan_start(0); |
| 359 | |
| 360 | // TODO: check return value !=0 |
| 361 | |
| 362 | wlan_ioctl_set_connection_policy(0, 0, 0); // don't auto-connect |
| 363 | wlan_ioctl_del_profile(255); // delete stored eeprom data |
| 364 | |
| 365 | // Mask out all non-required events from CC3000 |
| 366 | wlan_set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT | |
| 367 | //HCI_EVNT_WLAN_ASYNC_PING_REPORT |// we want ping reports |
| 368 | //HCI_EVNT_BSD_TCP_CLOSE_WAIT | |
| 369 | //HCI_EVNT_WLAN_TX_COMPLETE | |
| 370 | HCI_EVNT_WLAN_KEEPALIVE); |
| 371 | |
| 372 | /* |
| 373 | byte ver[2]; |
| 374 | int ret = nvmem_read_sp_version(ver); |
| 375 | printf("nvmem_read_sp_version=%d; %02x %02x\n", ret, ver[0], ver[1]); |
| 376 | */ |
| 377 | } |