Commit bcf041f1 authored by Damien George's avatar Damien George
Browse files

stmhal: Add wiznet5k module, to control WIZnet ethernet adaptor.

Allows to create socket objects that support TCP and UDP in server and
client mode.  Interface is very close to standard Python socket class,
except bind and accept do not work the same (due to hardware not
supporting them in the usual way).

Not compiled by default.  To compile this module, use:
make MICROPY_PY_WIZNET5K=1
parent cdd40f14
...@@ -606,6 +606,12 @@ void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) ...@@ -606,6 +606,12 @@ void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
getGAR(pnetinfo->gw); getGAR(pnetinfo->gw);
getSUBR(pnetinfo->sn); getSUBR(pnetinfo->sn);
getSIPR(pnetinfo->ip); getSIPR(pnetinfo->ip);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
pnetinfo->sn[0] = _SUBN_[0];
pnetinfo->sn[1] = _SUBN_[1];
pnetinfo->sn[2] = _SUBN_[2];
pnetinfo->sn[3] = _SUBN_[3];
#endif
pnetinfo->dns[0]= _DNS_[0]; pnetinfo->dns[0]= _DNS_[0];
pnetinfo->dns[1]= _DNS_[1]; pnetinfo->dns[1]= _DNS_[1];
pnetinfo->dns[2]= _DNS_[2]; pnetinfo->dns[2]= _DNS_[2];
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
//#include "Ethernet/socket.h" //#include "Ethernet/socket.h"
//#include "Internet/DNS/dns.h" //#include "Internet/DNS/dns.h"
#include "../../Ethernet/socket.h" #include "../../ethernet/socket.h"
#include "dns.h" #include "dns.h"
#ifdef _DNS_DEBUG_ #ifdef _DNS_DEBUG_
......
...@@ -9,6 +9,7 @@ endif ...@@ -9,6 +9,7 @@ endif
BUILD ?= build-$(BOARD) BUILD ?= build-$(BOARD)
include ../py/mkenv.mk include ../py/mkenv.mk
-include mpconfigport.mk
# qstr definitions (must come before including py.mk) # qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
...@@ -41,7 +42,7 @@ INC += -I$(FATFS_DIR)/src ...@@ -41,7 +42,7 @@ INC += -I$(FATFS_DIR)/src
INC += -I$(CC3K_DIR) INC += -I$(CC3K_DIR)
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_CORTEX_M4) $(COPT)
CFLAGS += -Iboards/$(BOARD) CFLAGS += -Iboards/$(BOARD)
LDFLAGS = -nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref LDFLAGS = -nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref
...@@ -196,6 +197,19 @@ SRC_CC3K = $(addprefix $(CC3K_DIR)/,\ ...@@ -196,6 +197,19 @@ SRC_CC3K = $(addprefix $(CC3K_DIR)/,\
pybcc3k.c \ pybcc3k.c \
) )
ifeq ($(MICROPY_PY_WIZNET5K),1)
WIZNET5K_DIR=drivers/wiznet5k
INC += -I$(TOP)/$(WIZNET5K_DIR)
CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=1
SRC_MOD += modwiznet5k.c
SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\
ethernet/w5200/w5200.c \
ethernet/wizchip_conf.c \
ethernet/socket.c \
internet/dns/dns.c \
)
endif
OBJ = OBJ =
OBJ += $(PY_O) OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o))
...@@ -205,6 +219,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o)) ...@@ -205,6 +219,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_USBDEV:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_USBDEV:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_FATFS:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_FATFS:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CC3K:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_CC3K:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
OBJ += $(BUILD)/pins_$(BOARD).o OBJ += $(BUILD)/pins_$(BOARD).o
# We put ff.o and stm32f4xx_hal_sd.o into the first 16K section with the ISRs. # We put ff.o and stm32f4xx_hal_sd.o into the first 16K section with the ISRs.
......
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "stm32f4xx_hal.h"
#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
#include "pin.h"
#include "genhdr/pins.h"
#include "spi.h"
#include MICROPY_HAL_H
#include "ethernet/wizchip_conf.h"
#include "ethernet/socket.h"
#include "internet/dns/dns.h"
#define IPADDR_BUF_SIZE (4)
STATIC const mp_obj_type_t wiznet5k_type;
STATIC const mp_obj_type_t wiznet5k_socket_type;
STATIC mp_obj_t wiznet5k_socket_new(uint8_t sn, mp_uint_t type);
typedef struct _wiznet5k_obj_t {
mp_obj_base_t base;
mp_uint_t cris_state;
const pin_obj_t *cs;
const pin_obj_t *rst;
SPI_HandleTypeDef *spi;
uint8_t socket_used;
} wiznet5k_obj_t;
STATIC wiznet5k_obj_t wiznet5k_obj;
STATIC void wiz_cris_enter(void) {
wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION();
}
STATIC void wiz_cris_exit(void) {
MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state);
}
STATIC void wiz_cs_select(void) {
GPIO_clear_pin(wiznet5k_obj.cs->gpio, wiznet5k_obj.cs->pin_mask);
}
STATIC void wiz_cs_deselect(void) {
GPIO_set_pin(wiznet5k_obj.cs->gpio, wiznet5k_obj.cs->pin_mask);
}
STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi, buf, len, 5000);
(void)status;
}
STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi, (uint8_t*)buf, len, 5000);
(void)status;
}
/******************************************************************************/
// Miscellaneous helpers
// Check the return value from Wiz socket calls:
// - on error (<0) an exception is raised
// - SOCK_OK or SOCK_BUSY does nothing
// - anything positive does nothing
STATIC void check_sock_return_value(int8_t ret) {
// TODO convert Wiz errno's to POSIX ones
if (ret < 0) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "socket error %d", ret));
}
}
STATIC void parse_ip_addr(mp_obj_t addr_in, uint8_t *out_ip) {
const char *addr_str = mp_obj_str_get_str(addr_in);
const char *s = addr_str;
for (mp_uint_t i = 0;; i++) {
mp_uint_t val = 0;
for (; *s && *s != '.'; s++) {
val = val * 10 + *s - '0';
}
out_ip[i] = val;
if (i == 3 && *s == '\0') {
return;
} else if (i < 3 && *s == '.') {
s++;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid IP address"));
}
}
}
// Takes an address of the form ('192.168.0.1', 8080), returns the port and
// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
STATIC mp_uint_t parse_net_addr(mp_obj_t addr_in, uint8_t *out_ip) {
mp_obj_t *addr_items;
mp_obj_get_array_fixed_n(addr_in, 2, &addr_items);
parse_ip_addr(addr_items[0], out_ip);
return mp_obj_get_int(addr_items[1]);
}
// Takes an array with a raw IP address and returns something like '192.168.0.1'.
STATIC mp_obj_t format_ip_addr(uint8_t *ip) {
char ip_str[16];
mp_uint_t ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
return mp_obj_new_str(ip_str, ip_len, false);
}
// Takes an array with a raw IP address, and a port, and returns a net-address
// tuple such as ('192.168.0.1', 8080).
STATIC mp_obj_t format_net_addr(uint8_t *ip, mp_uint_t port) {
mp_obj_t tuple[2] = {
tuple[0] = format_ip_addr(ip),
tuple[1] = mp_obj_new_int(port),
};
return mp_obj_new_tuple(2, tuple);
}
/******************************************************************************/
// Micro Python bindings
STATIC void wiznet5k_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
print(env, "WIZnet5k()");
}
/// \classmethod \constructor()
/// Create and return a wiznet5k object.
STATIC mp_obj_t wiznet5k_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// init the wiznet5k object
wiznet5k_obj.base.type = &wiznet5k_type;
wiznet5k_obj.cris_state = 0;
wiznet5k_obj.cs = &pin_B12; // Y5
wiznet5k_obj.rst = &pin_B9; // Y4
wiznet5k_obj.spi = &SPIHandle2; // Y-skin
wiznet5k_obj.socket_used = 0;
/*!< SPI configuration */
SPIHandle2.Init.Mode = SPI_MODE_MASTER;
SPIHandle2.Init.Direction = SPI_DIRECTION_2LINES;
SPIHandle2.Init.DataSize = SPI_DATASIZE_8BIT;
SPIHandle2.Init.CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle
SPIHandle2.Init.CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle
SPIHandle2.Init.NSS = SPI_NSS_SOFT;
SPIHandle2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz
SPIHandle2.Init.FirstBit = SPI_FIRSTBIT_MSB;
SPIHandle2.Init.TIMode = SPI_TIMODE_DISABLED;
SPIHandle2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
SPIHandle2.Init.CRCPolynomial = 7; // unused
spi_init(wiznet5k_obj.spi);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = wiznet5k_obj.cs->pin_mask;
HAL_GPIO_Init(wiznet5k_obj.cs->gpio, &GPIO_InitStructure);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = wiznet5k_obj.rst->pin_mask;
HAL_GPIO_Init(wiznet5k_obj.rst->gpio, &GPIO_InitStructure);
GPIO_clear_pin(wiznet5k_obj.rst->gpio, wiznet5k_obj.rst->pin_mask);
HAL_Delay(1); // datasheet says 2us
GPIO_set_pin(wiznet5k_obj.rst->gpio, wiznet5k_obj.rst->pin_mask);
HAL_Delay(160); // datasheet says 150ms
reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit);
reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write);
uint8_t sn_size[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; // 2k buffer for each socket
ctlwizchip(CW_INIT_WIZCHIP, sn_size);
// TODO make this configurable!
wiz_NetInfo netinfo = {
.mac = {0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef},
.ip = {192, 168, 0, 18},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 0, 1},
.dns = {8, 8, 8, 8}, // Google public DNS
.dhcp = NETINFO_STATIC,
};
ctlnetwork(CN_SET_NETINFO, (void*)&netinfo);
// return wiznet5k object
return &wiznet5k_obj;
}
/// \method regs()
/// Dump WIZnet5k registers.
STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) {
//wiznet5k_obj_t *self = self_in;
printf("Wiz CREG:");
for (int i = 0; i < 0x50; ++i) {
if (i % 16 == 0) {
printf("\n %04x:", i);
}
printf(" %02x", WIZCHIP_READ(i));
}
for (int sn = 0; sn < 4; ++sn) {
printf("\nWiz SREG[%d]:", sn);
for (int i = 0; i < 0x30; ++i) {
if (i % 16 == 0) {
printf("\n %04x:", i);
}
printf(" %02x", WIZCHIP_READ(WIZCHIP_SREG_ADDR(sn, i)));
}
}
printf("\n");
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs);
/// \method ipaddr([(ip, subnet, gateway, dns)])
/// Get/set IP address, subnet mask, gateway and DNS.
STATIC mp_obj_t wiznet5k_ipaddr(mp_uint_t n_args, const mp_obj_t *args) {
wiz_NetInfo netinfo;
ctlnetwork(CN_GET_NETINFO, &netinfo);
if (n_args == 1) {
// get
mp_obj_t tuple[4] = {
format_ip_addr(netinfo.ip),
format_ip_addr(netinfo.sn),
format_ip_addr(netinfo.gw),
format_ip_addr(netinfo.dns),
};
return mp_obj_new_tuple(4, tuple);
} else {
// set
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[1], 4, &items);
parse_ip_addr(items[0], netinfo.ip);
parse_ip_addr(items[1], netinfo.sn);
parse_ip_addr(items[2], netinfo.gw);
parse_ip_addr(items[3], netinfo.dns);
ctlnetwork(CN_SET_NETINFO, &netinfo);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ipaddr_obj, 1, 2, wiznet5k_ipaddr);
STATIC const mp_arg_t wiznet5k_socket_args[] = {
{ MP_QSTR_family, MP_ARG_INT, {.u_int = 0} }, // ignored, only AF_INET supported
{ MP_QSTR_type, MP_ARG_INT, {.u_int = Sn_MR_TCP} }, // SOCK_STREAM or SOCK_DGRAM
{ MP_QSTR_fileno, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
#define PYB_WIZNET5K_SOCKET_NUM_ARGS MP_ARRAY_SIZE(wiznet5k_socket_args)
STATIC mp_obj_t wiznet5k_socket(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PYB_WIZNET5K_SOCKET_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_WIZNET5K_SOCKET_NUM_ARGS, wiznet5k_socket_args, vals);
if (vals[2].u_int < 0) {
// get first unused socket number
for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) {
if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) {
vals[2].u_int = sn;
break;
}
}
if (vals[2].u_int < 0) {
// too many open sockets
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EMFILE)));
}
}
return wiznet5k_socket_new(vals[2].u_int, vals[1].u_int);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wiznet5k_socket_obj, 1, wiznet5k_socket);
STATIC mp_obj_t wiznet5k_gethostbyname(mp_obj_t self_in, mp_obj_t name_in) {
uint8_t dns_ip[IPADDR_BUF_SIZE] = {8, 8, 8, 8};
const char *name = mp_obj_str_get_str(name_in);
uint8_t out_ip[IPADDR_BUF_SIZE];
uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE);
DNS_init(0, buf);
mp_int_t ret = DNS_run(dns_ip, (uint8_t*)name, out_ip);
m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
if (ret == 1) {
// success
return format_ip_addr(out_ip);
} else {
// failure
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "DNS error %d", ret));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_gethostbyname_obj, wiznet5k_gethostbyname);
STATIC const mp_map_elem_t wiznet5k_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_regs), (mp_obj_t)&wiznet5k_regs_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ipaddr), (mp_obj_t)&wiznet5k_ipaddr_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&wiznet5k_socket_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_gethostbyname), (mp_obj_t)&wiznet5k_gethostbyname_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(0) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(Sn_MR_TCP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(Sn_MR_UDP) },
};
STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
STATIC const mp_obj_type_t wiznet5k_type = {
{ &mp_type_type },
.name = MP_QSTR_WIZnet5k,
.print = wiznet5k_print,
.make_new = wiznet5k_make_new,
.locals_dict = (mp_obj_t)&wiznet5k_locals_dict,
};
/******************************************************************************/
// Micro Python bindings; WIZnet5x00 socket class
typedef struct _wiznet5k_socket_obj_t {
mp_obj_base_t base;
uint8_t sn;
uint8_t type;
} wiznet5k_socket_obj_t;
STATIC mp_obj_t wiznet5k_socket_new(uint8_t sn, mp_uint_t type) {
wiznet5k_socket_obj_t *s = m_new_obj(wiznet5k_socket_obj_t);
s->base.type = &wiznet5k_socket_type;
s->sn = sn;
s->type = type;
return s;
}
STATIC void wiznet5k_socket_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
wiznet5k_socket_obj_t *self = self_in;
print(env, "<WIZnet5k.socket sn=%u MR=0x%02x>", self->sn, getSn_MR(self->sn));
}
STATIC mp_obj_t wiznet5k_socket_close(mp_obj_t self_in) {
wiznet5k_socket_obj_t *self = self_in;
wiznet5k_obj.socket_used &= ~(1 << self->sn);
mp_int_t ret = close(self->sn);
check_sock_return_value(ret);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_socket_close_obj, wiznet5k_socket_close);
STATIC mp_obj_t wiznet5k_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
wiznet5k_socket_obj_t *self = self_in;
uint8_t ip[IPADDR_BUF_SIZE];
mp_uint_t port = parse_net_addr(addr_in, ip);
// open the socket in server mode
mp_int_t ret = socket(self->sn, self->type, port, 0);
check_sock_return_value(ret);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_bind_obj, wiznet5k_socket_bind);
STATIC mp_obj_t wiznet5k_socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
wiznet5k_socket_obj_t *self = self_in;
mp_int_t ret = listen(self->sn);
check_sock_return_value(ret);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_listen_obj, wiznet5k_socket_listen);
STATIC mp_obj_t wiznet5k_socket_accept(mp_obj_t self_in) {
//wiznet5k_socket_obj_t *self = self_in;
// TODO what to do here exactly?
mp_obj_t tuple[2] = {self_in, mp_const_none};
return mp_obj_new_tuple(2, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_socket_accept_obj, wiznet5k_socket_accept);
STATIC mp_obj_t wiznet5k_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
wiznet5k_socket_obj_t *self = self_in;
// first open the socket in client mode
mp_int_t ret = socket(self->sn, self->type, 0, 0);
check_sock_return_value(ret);
// now connect
uint8_t ip[IPADDR_BUF_SIZE];
mp_uint_t port = parse_net_addr(addr_in, ip);
ret = connect(self->sn, ip, port);
check_sock_return_value(ret);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_connect_obj, wiznet5k_socket_connect);
STATIC mp_obj_t wiznet5k_socket_disconnect(mp_obj_t self_in) {
wiznet5k_socket_obj_t *self = self_in;
mp_int_t ret = disconnect(self->sn);
check_sock_return_value(ret);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_socket_disconnect_obj, wiznet5k_socket_disconnect);
STATIC mp_obj_t wiznet5k_socket_send(mp_obj_t self_in, mp_obj_t data_in) {
wiznet5k_socket_obj_t *self = self_in;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
mp_int_t ret = send(self->sn, bufinfo.buf, bufinfo.len);
check_sock_return_value(ret);
return mp_obj_new_int(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_send_obj, wiznet5k_socket_send);
STATIC mp_obj_t wiznet5k_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
wiznet5k_socket_obj_t *self = self_in;
mp_int_t len = mp_obj_get_int(len_in);
uint8_t *buf = m_new(uint8_t, len);
mp_int_t ret = recv(self->sn, buf, len);
check_sock_return_value(ret);
mp_obj_t ret_buf = mp_obj_new_bytes(buf, ret);
m_del(uint8_t, buf, len);
return ret_buf;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_recv_obj, wiznet5k_socket_recv);
STATIC mp_obj_t wiznet5k_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
wiznet5k_socket_obj_t *self = self_in;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
uint8_t ip[IPADDR_BUF_SIZE];
mp_uint_t port = parse_net_addr(addr_in, ip);
mp_int_t ret = sendto(self->sn, bufinfo.buf, bufinfo.len, ip, port);
check_sock_return_value(ret);
return mp_obj_new_int(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(wiznet5k_socket_sendto_obj, wiznet5k_socket_sendto);
STATIC mp_obj_t wiznet5k_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
wiznet5k_socket_obj_t *self = self_in;
mp_int_t len = mp_obj_get_int(len_in);
uint8_t *buf = m_new(uint8_t, len);
uint8_t ip[4];
uint16_t port;
mp_int_t ret = recvfrom(self->sn, buf, len, ip, &port);
check_sock_return_value(ret);
mp_obj_t tuple[2] = {
mp_obj_new_bytes(buf, ret),
format_net_addr(ip, port),
};
return mp_obj_new_tuple(2, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_recvfrom_obj, wiznet5k_socket_recvfrom);
STATIC const mp_map_elem_t wiznet5k_socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&wiznet5k_socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&wiznet5k_socket_bind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&wiznet5k_socket_listen_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&wiznet5k_socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&wiznet5k_socket_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&wiznet5k_socket_disconnect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&wiznet5k_socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&wiznet5k_socket_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&wiznet5k_socket_sendto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&wiznet5k_socket_recvfrom_obj },
};
STATIC MP_DEFINE_CONST_DICT(wiznet5k_socket_locals_dict, wiznet5k_socket_locals_dict_table);
STATIC const mp_obj_type_t wiznet5k_socket_type = {
{ &mp_type_type },
.name = MP_QSTR_socket,
.print = wiznet5k_socket_print,
.locals_dict = (mp_obj_t)&wiznet5k_socket_locals_dict,
};
/******************************************************************************/
// Micro Python bindings; WIZnet5x00 module
STATIC const mp_map_elem_t mp_module_wiznet5k_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_wiznet5k) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WIZnet5k), (mp_obj_t)&wiznet5k_type },
};
STATIC const mp_obj_dict_t mp_module_wiznet5k_globals = {
.base = {&mp_type_dict},
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,