summaryrefslogtreecommitdiffstatshomepage
path: root/extmod
diff options
context:
space:
mode:
Diffstat (limited to 'extmod')
-rw-r--r--extmod/fsusermount.c2
-rw-r--r--extmod/machine_i2c.c8
-rw-r--r--extmod/machine_pulse.c67
-rw-r--r--extmod/machine_pulse.h37
-rw-r--r--extmod/misc.h1
-rw-r--r--extmod/modlwip.c132
-rw-r--r--extmod/modubinascii.c2
-rw-r--r--extmod/moduos_dupterm.c15
-rw-r--r--extmod/modussl.c36
-rw-r--r--extmod/modwebrepl.c12
-rw-r--r--extmod/modwebsocket.c18
-rw-r--r--extmod/vfs_fat.c165
-rw-r--r--extmod/vfs_fat_misc.c7
-rw-r--r--extmod/virtpin.c39
-rw-r--r--extmod/virtpin.h40
15 files changed, 469 insertions, 112 deletions
diff --git a/extmod/fsusermount.c b/extmod/fsusermount.c
index 8f789ca033..9ddc98f3dd 100644
--- a/extmod/fsusermount.c
+++ b/extmod/fsusermount.c
@@ -32,7 +32,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "lib/fatfs/ff.h"
-#include "fsusermount.h"
+#include "extmod/fsusermount.h"
fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs) {
static const mp_arg_t allowed_args[] = {
diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c
index e3bdb36925..ceddf0730e 100644
--- a/extmod/machine_i2c.c
+++ b/extmod/machine_i2c.c
@@ -48,7 +48,7 @@ STATIC void mp_hal_i2c_delay(machine_i2c_obj_t *self) {
}
STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
- mp_hal_pin_low(self->scl);
+ mp_hal_pin_od_low(self->scl);
}
STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
@@ -56,7 +56,7 @@ STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
}
STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
- mp_hal_pin_low(self->sda);
+ mp_hal_pin_od_low(self->sda);
}
STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) {
@@ -91,8 +91,8 @@ STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) {
if (self->us_delay == 0) {
self->us_delay = 1;
}
- mp_hal_pin_config_od(self->scl);
- mp_hal_pin_config_od(self->sda);
+ mp_hal_pin_open_drain(self->scl);
+ mp_hal_pin_open_drain(self->sda);
mp_hal_i2c_stop(self);
}
diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c
new file mode 100644
index 0000000000..8c8bff510c
--- /dev/null
+++ b/extmod/machine_pulse.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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 "py/runtime.h"
+#include "py/mperrno.h"
+#include "extmod/machine_pulse.h"
+
+#if MICROPY_PY_MACHINE_PULSE
+
+mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
+ mp_uint_t start = mp_hal_ticks_us();
+ while (mp_hal_pin_read(pin) != pulse_level) {
+ if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
+ return (mp_uint_t)-1;
+ }
+ }
+ start = mp_hal_ticks_us();
+ while (mp_hal_pin_read(pin) == pulse_level) {
+ if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
+ return (mp_uint_t)-1;
+ }
+ }
+ return mp_hal_ticks_us() - start;
+}
+
+STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {
+ mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]);
+ int level = 0;
+ if (mp_obj_is_true(args[1])) {
+ level = 1;
+ }
+ mp_uint_t timeout_us = 1000000;
+ if (n_args > 2) {
+ timeout_us = mp_obj_get_int(args[2]);
+ }
+ mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us);
+ if (us == (mp_uint_t)-1) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
+ }
+ return mp_obj_new_int(us);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_);
+
+#endif
diff --git a/extmod/machine_pulse.h b/extmod/machine_pulse.h
new file mode 100644
index 0000000000..3d5d81c073
--- /dev/null
+++ b/extmod/machine_pulse.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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.
+ */
+
+#ifndef __MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H__
+#define __MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H__
+
+#include "py/obj.h"
+#include "py/mphal.h"
+
+mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
+
+MP_DECLARE_CONST_FUN_OBJ(machine_time_pulse_us_obj);
+
+#endif // __MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H__
diff --git a/extmod/misc.h b/extmod/misc.h
index 39bfd5ecb5..634ea924d0 100644
--- a/extmod/misc.h
+++ b/extmod/misc.h
@@ -34,6 +34,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_uos_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
+void mp_uos_deactivate(const char *msg, mp_obj_t exc);
#else
#define mp_uos_dupterm_tx_strn(s, l)
#endif
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index 090e1005a8..cb7cc6596f 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -26,13 +26,13 @@
*/
#include <string.h>
-#include <errno.h>
#include <stdio.h>
#include "py/nlr.h"
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/stream.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "netutils.h"
@@ -172,45 +172,45 @@ STATIC const mp_obj_type_t lwip_slip_type = {
// investigate in more detail.
#if LWIP_VERSION < 0x01040100
static const int error_lookup_table[] = {
- 0, /* ERR_OK 0 No error, everything OK. */
- ENOMEM, /* ERR_MEM -1 Out of memory error. */
- ENOBUFS, /* ERR_BUF -2 Buffer error. */
- EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
- EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
- EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
- EINVAL, /* ERR_VAL -6 Illegal value. */
- EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
-
- ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
- ECONNRESET, /* ERR_RST -9 Connection reset. */
- ENOTCONN, /* ERR_CLSD -10 Connection closed. */
- ENOTCONN, /* ERR_CONN -11 Not connected. */
- EIO, /* ERR_ARG -12 Illegal argument. */
- EADDRINUSE, /* ERR_USE -13 Address in use. */
- -1, /* ERR_IF -14 Low-level netif error */
- EALREADY, /* ERR_ISCONN -15 Already connected. */
- EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
+ 0, /* ERR_OK 0 No error, everything OK. */
+ MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
+ MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
+ MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
+ MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
+ MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
+ MP_EINVAL, /* ERR_VAL -6 Illegal value. */
+ MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
+
+ MP_ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
+ MP_ECONNRESET, /* ERR_RST -9 Connection reset. */
+ MP_ENOTCONN, /* ERR_CLSD -10 Connection closed. */
+ MP_ENOTCONN, /* ERR_CONN -11 Not connected. */
+ MP_EIO, /* ERR_ARG -12 Illegal argument. */
+ MP_EADDRINUSE, /* ERR_USE -13 Address in use. */
+ -1, /* ERR_IF -14 Low-level netif error */
+ MP_EALREADY, /* ERR_ISCONN -15 Already connected. */
+ MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
};
#else
static const int error_lookup_table[] = {
- 0, /* ERR_OK 0 No error, everything OK. */
- ENOMEM, /* ERR_MEM -1 Out of memory error. */
- ENOBUFS, /* ERR_BUF -2 Buffer error. */
- EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
- EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
- EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
- EINVAL, /* ERR_VAL -6 Illegal value. */
- EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
-
- EADDRINUSE, /* ERR_USE -8 Address in use. */
- EALREADY, /* ERR_ISCONN -9 Already connected. */
- ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
- ECONNRESET, /* ERR_RST -11 Connection reset. */
- ENOTCONN, /* ERR_CLSD -12 Connection closed. */
- ENOTCONN, /* ERR_CONN -13 Not connected. */
- EIO, /* ERR_ARG -14 Illegal argument. */
- -1, /* ERR_IF -15 Low-level netif error */
- EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
+ 0, /* ERR_OK 0 No error, everything OK. */
+ MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
+ MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
+ MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
+ MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
+ MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
+ MP_EINVAL, /* ERR_VAL -6 Illegal value. */
+ MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
+
+ MP_EADDRINUSE, /* ERR_USE -8 Address in use. */
+ MP_EALREADY, /* ERR_ISCONN -9 Already connected. */
+ MP_ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
+ MP_ECONNRESET, /* ERR_RST -11 Connection reset. */
+ MP_ENOTCONN, /* ERR_CLSD -12 Connection closed. */
+ MP_ENOTCONN, /* ERR_CONN -13 Not connected. */
+ MP_EIO, /* ERR_ARG -14 Illegal argument. */
+ -1, /* ERR_IF -15 Low-level netif error */
+ MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
};
#endif
@@ -311,6 +311,17 @@ STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pb
return ERR_BUF;
}
+// "Poll" (idle) callback to be called ASAP after accept callback
+// to execute Python callback function, as it can't be executed
+// from accept callback itself.
+STATIC err_t _lwip_tcp_accept_finished(void *arg, struct tcp_pcb *pcb)
+{
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
+ tcp_poll(pcb, NULL, 0);
+ exec_user_callback(socket);
+ return ERR_OK;
+}
+
// Callback for incoming tcp connections.
STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
@@ -323,7 +334,12 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
return ERR_BUF;
} else {
socket->incoming.connection = newpcb;
- exec_user_callback(socket);
+ if (socket->callback != MP_OBJ_NULL) {
+ // Schedule accept callback to be called when lwIP is done
+ // with processing this incoming connection on its side and
+ // is idle.
+ tcp_poll(newpcb, _lwip_tcp_accept_finished, 1);
+ }
return ERR_OK;
}
}
@@ -363,7 +379,7 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
// FIXME: maybe PBUF_ROM?
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (p == NULL) {
- *_errno = ENOMEM;
+ *_errno = MP_ENOMEM;
return -1;
}
@@ -401,7 +417,7 @@ STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
if (socket->incoming.pbuf != NULL) break;
}
if (socket->incoming.pbuf == NULL) {
- *_errno = ETIMEDOUT;
+ *_errno = MP_ETIMEDOUT;
return -1;
}
} else {
@@ -444,7 +460,7 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
if (available == 0) {
// Non-blocking socket
if (socket->timeout == 0) {
- *_errno = EAGAIN;
+ *_errno = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@@ -457,7 +473,7 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
// Avoid sending too small packets, so wait until at least 16 bytes available
while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) {
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
- *_errno = ETIMEDOUT;
+ *_errno = MP_ETIMEDOUT;
return MP_STREAM_ERROR;
}
poll_sockets();
@@ -491,14 +507,14 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
if (socket->state == STATE_PEER_CLOSED) {
return 0;
}
- *_errno = EAGAIN;
+ *_errno = MP_EAGAIN;
return -1;
}
mp_uint_t start = mp_hal_ticks_ms();
while (socket->state == STATE_CONNECTED && socket->incoming.pbuf == NULL) {
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
- *_errno = ETIMEDOUT;
+ *_errno = MP_ETIMEDOUT;
return -1;
}
poll_sockets();
@@ -570,11 +586,11 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args
case MOD_NETWORK_SOCK_STREAM: socket->pcb.tcp = tcp_new(); break;
case MOD_NETWORK_SOCK_DGRAM: socket->pcb.udp = udp_new(); break;
//case MOD_NETWORK_SOCK_RAW: socket->pcb.raw = raw_new(); break;
- default: nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
+ default: nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINVAL)));
}
if (socket->pcb.tcp == NULL) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOMEM)));
}
switch (socket->type) {
@@ -670,15 +686,15 @@ STATIC mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
mp_int_t backlog = mp_obj_get_int(backlog_in);
if (socket->pcb.tcp == NULL) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
}
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
}
struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
if (new_pcb == NULL) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOMEM)));
}
socket->pcb.tcp = new_pcb;
tcp_accept(new_pcb, _lwip_tcp_accept);
@@ -691,15 +707,15 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
lwip_socket_obj_t *socket = self_in;
if (socket->pcb.tcp == NULL) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
}
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
}
// I need to do this because "tcp_accepted", later, is a macro.
struct tcp_pcb *listener = socket->pcb.tcp;
if (listener->state != LISTEN) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINVAL)));
}
// accept incoming connection
@@ -710,7 +726,7 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
if (socket->incoming.connection != NULL) break;
}
if (socket->incoming.connection == NULL) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
}
} else {
while (socket->incoming.connection == NULL) {
@@ -757,7 +773,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
lwip_socket_obj_t *socket = self_in;
if (socket->pcb.tcp == NULL) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
}
// get address
@@ -772,9 +788,9 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
case MOD_NETWORK_SOCK_STREAM: {
if (socket->state != STATE_NEW) {
if (socket->state == STATE_CONNECTED) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EALREADY)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EALREADY)));
} else {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINPROGRESS)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINPROGRESS)));
}
}
// Register our recieve callback.
@@ -794,7 +810,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
if (socket->state != STATE_CONNECTING) break;
}
if (socket->state == STATE_CONNECTING) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
}
} else {
while (socket->state == STATE_CONNECTING) {
@@ -982,7 +998,7 @@ STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
// most useful behavior is: check whether we will be able to send all of input
// data without EAGAIN, and if won't be, raise it without sending any.
if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EAGAIN)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EAGAIN)));
}
}
// TODO: In CPython3.5, socket timeout should apply to the
diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c
index 82f910b0e7..3cceb991f1 100644
--- a/extmod/modubinascii.c
+++ b/extmod/modubinascii.c
@@ -31,7 +31,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/binary.h"
-#include "modubinascii.h"
+#include "extmod/modubinascii.h"
mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
diff --git a/extmod/moduos_dupterm.c b/extmod/moduos_dupterm.c
index 41b8b3c81e..4c9f9e4940 100644
--- a/extmod/moduos_dupterm.c
+++ b/extmod/moduos_dupterm.c
@@ -31,9 +31,20 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/objtuple.h"
+#include "py/stream.h"
#if MICROPY_PY_OS_DUPTERM
+void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
+ mp_obj_t term = MP_STATE_PORT(term_obj);
+ MP_STATE_PORT(term_obj) = NULL;
+ mp_printf(&mp_plat_print, msg);
+ if (exc != MP_OBJ_NULL) {
+ mp_obj_print_exception(&mp_plat_print, exc);
+ }
+ mp_stream_close(term);
+}
+
void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
nlr_buf_t nlr;
@@ -44,9 +55,7 @@ void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
mp_call_method_n_kw(1, 0, write_m);
nlr_pop();
} else {
- MP_STATE_PORT(term_obj) = NULL;
- mp_printf(&mp_plat_print, "dupterm: Exception in write() method, deactivating: ");
- mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
+ mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
}
}
}
diff --git a/extmod/modussl.c b/extmod/modussl.c
index 51f4fead81..567033cf48 100644
--- a/extmod/modussl.c
+++ b/extmod/modussl.c
@@ -78,12 +78,12 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, bool server_side) {
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
- mp_obj_ssl_socket_t *self = self_in;
+ mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<_SSLSocket %p>", self->ssl_sock);
}
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
- mp_obj_ssl_socket_t *o = o_in;
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
while (o->bytes_left == 0) {
mp_int_t r = ssl_read(o->ssl_sock, &o->buf);
@@ -113,7 +113,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
}
STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
- mp_obj_ssl_socket_t *o = o_in;
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
mp_int_t r = ssl_write(o->ssl_sock, buf, size);
if (r < 0) {
*errcode = r;
@@ -123,7 +123,7 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
}
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
- mp_obj_ssl_socket_t *self = self_in;
+ mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
ssl_free(self->ssl_sock);
ssl_ctx_free(self->ssl_ctx);
@@ -133,13 +133,13 @@ STATIC mp_obj_t socket_close(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
-STATIC const mp_map_elem_t ussl_socket_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
+STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
};
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
@@ -157,10 +157,10 @@ STATIC const mp_obj_type_t ussl_socket_type = {
.getiter = NULL,
.iternext = NULL,
.stream_p = &ussl_socket_stream_p,
- .locals_dict = (mp_obj_t)&ussl_socket_locals_dict,
+ .locals_dict = (void*)&ussl_socket_locals_dict,
};
-STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// TODO: Implement more args
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
@@ -175,13 +175,13 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
- return socket_new(sock, args.server_side.u_bool);
+ return MP_OBJ_FROM_PTR(socket_new(sock, args.server_side.u_bool));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
-STATIC const mp_map_elem_t mp_module_ssl_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ussl) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_wrap_socket), (mp_obj_t)&mod_ssl_wrap_socket_obj },
+STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
+ { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
@@ -195,6 +195,8 @@ const mp_obj_module_t mp_module_ussl = {
// These functions might be split to stream_posix.c. They are referenced by
// axtls os_port.h .
+ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len);
+ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len);
int mp_stream_errno;
diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c
index c160abea2f..8ecab922aa 100644
--- a/extmod/modwebrepl.c
+++ b/extmod/modwebrepl.c
@@ -250,8 +250,8 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz);
int err;
- mp_uint_t res = mp_stream_writeall(self->cur_file, filebuf, buf_sz, &err);
- if(res == MP_STREAM_ERROR) {
+ mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err);
+ if (err != 0 || res != buf_sz) {
assert(0);
}
@@ -284,6 +284,13 @@ STATIC mp_uint_t webrepl_write(mp_obj_t self_in, const void *buf, mp_uint_t size
return stream_p->write(self->sock, buf, size, errcode);
}
+STATIC mp_obj_t webrepl_close(mp_obj_t self_in) {
+ mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(self_in);
+ // TODO: This is a place to do cleanup
+ return mp_stream_close(self->sock);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_close_obj, webrepl_close);
+
STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) {
mp_uint_t len;
const char *passwd = mp_obj_str_get_data(passwd_in, &len);
@@ -297,6 +304,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_set_password_obj, webrepl_set_password)
STATIC const mp_map_elem_t webrepl_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&webrepl_close_obj },
};
STATIC MP_DEFINE_CONST_DICT(webrepl_locals_dict, webrepl_locals_dict_table);
diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c
index 344933ded3..fc5e29a05e 100644
--- a/extmod/modwebsocket.c
+++ b/extmod/modwebsocket.c
@@ -240,9 +240,9 @@ STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si
mp_call_method_n_kw(1, 0, dest);
}
- mp_uint_t out_sz = mp_stream_writeall(self->sock, header, hdr_sz, errcode);
- if (out_sz != MP_STREAM_ERROR) {
- out_sz = mp_stream_writeall(self->sock, buf, size, errcode);
+ mp_uint_t out_sz = mp_stream_write_exactly(self->sock, header, hdr_sz, errcode);
+ if (*errcode == 0) {
+ out_sz = mp_stream_write_exactly(self->sock, buf, size, errcode);
}
if (self->opts & BLOCKING_WRITE) {
@@ -250,6 +250,9 @@ STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si
mp_call_method_n_kw(1, 0, dest);
}
+ if (*errcode != 0) {
+ return MP_STREAM_ERROR;
+ }
return out_sz;
}
@@ -269,10 +272,19 @@ STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t
}
}
+STATIC mp_obj_t websocket_close(mp_obj_t self_in) {
+ mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
+ // TODO: Send close signaling to the other side, otherwise it's
+ // abrupt close (connection abort).
+ return mp_stream_close(self->sock);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(websocket_close_obj, websocket_close);
+
STATIC const mp_map_elem_t websocket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&mp_stream_ioctl_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&websocket_close_obj },
};
STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index c52adfbe08..a4a81370f9 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -28,12 +28,14 @@
#include "py/mpconfig.h"
#if MICROPY_VFS_FAT
+#include <string.h>
#include "py/nlr.h"
#include "py/runtime.h"
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h"
#include "extmod/vfs_fat_file.h"
-#include "fsusermount.h"
+#include "extmod/fsusermount.h"
+#include "timeutils.h"
#define mp_obj_fat_vfs_t fs_user_mount_t
@@ -79,12 +81,11 @@ STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
// TODO check that path is actually a file before trying to unlink it
FRESULT res = f_unlink(path);
- switch (res) {
- case FR_OK:
- return mp_const_none;
- default:
- // TODO: standard errno's
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
+ if (res == FR_OK) {
+ return mp_const_none;
+ } else {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
+ MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove);
@@ -94,11 +95,11 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
const char *old_path = mp_obj_str_get_str(path_in);
const char *new_path = mp_obj_str_get_str(path_out);
FRESULT res = f_rename(old_path, new_path);
- switch (res) {
- case FR_OK:
- return mp_const_none;
- default:
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error renaming file '%s' to '%s'", old_path, new_path));
+ if (res == FR_OK) {
+ return mp_const_none;
+ } else {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
+ MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
@@ -108,25 +109,149 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
(void)vfs_in;
const char *path = mp_obj_str_get_str(path_o);
FRESULT res = f_mkdir(path);
- switch (res) {
- case FR_OK:
- return mp_const_none;
- case FR_EXIST:
- // TODO should be FileExistsError
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
- default:
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
+ if (res == FR_OK) {
+ return mp_const_none;
+ } else {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
+ MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
+/// Change current directory.
+STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
+ (void)vfs_in;
+ const char *path;
+ path = mp_obj_str_get_str(path_in);
+
+ FRESULT res = f_chdrive(path);
+
+ if (res == FR_OK) {
+ res = f_chdir(path);
+ }
+
+ if (res != FR_OK) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
+ MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir);
+
+/// Get the current directory.
+STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
+ (void)vfs_in;
+ char buf[MICROPY_ALLOC_PATH_MAX + 1];
+ FRESULT res = f_getcwd(buf, sizeof buf);
+
+ if (res != FR_OK) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
+ }
+
+ return mp_obj_new_str(buf, strlen(buf), false);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);
+
+// Checks for path equality, ignoring trailing slashes:
+// path_equal(/, /) -> true
+// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
+STATIC bool path_equal(const char *path, const char *path_canonical) {
+ while (*path_canonical != '\0' && *path == *path_canonical) {
+ ++path;
+ ++path_canonical;
+ }
+ if (*path_canonical != '\0') {
+ return false;
+ }
+ while (*path == '/') {
+ ++path;
+ }
+ return *path == '\0';
+}
+
+/// \function stat(path)
+/// Get the status of a file or directory.
+STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
+ (void)vfs_in;
+ const char *path = mp_obj_str_get_str(path_in);
+
+ FILINFO fno;
+#if _USE_LFN
+ fno.lfname = NULL;
+ fno.lfsize = 0;
+#endif
+ FRESULT res;
+
+ if (path_equal(path, "/")) {
+ // stat root directory
+ fno.fsize = 0;
+ fno.fdate = 0;
+ fno.ftime = 0;
+ fno.fattrib = AM_DIR;
+ } else {
+ res = FR_NO_PATH;
+ for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
+ fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
+ if (vfs != NULL && path_equal(path, vfs->str)) {
+ // stat mounted device directory
+ fno.fsize = 0;
+ fno.fdate = 0;
+ fno.ftime = 0;
+ fno.fattrib = AM_DIR;
+ res = FR_OK;
+ }
+ }
+ if (res == FR_NO_PATH) {
+ // stat normal file
+ res = f_stat(path, &fno);
+ }
+ if (res != FR_OK) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
+ MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
+ }
+ }
+
+ mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
+ mp_int_t mode = 0;
+ if (fno.fattrib & AM_DIR) {
+ mode |= 0x4000; // stat.S_IFDIR
+ } else {
+ mode |= 0x8000; // stat.S_IFREG
+ }
+ mp_int_t seconds = timeutils_seconds_since_2000(
+ 1980 + ((fno.fdate >> 9) & 0x7f),
+ (fno.fdate >> 5) & 0x0f,
+ fno.fdate & 0x1f,
+ (fno.ftime >> 11) & 0x1f,
+ (fno.ftime >> 5) & 0x3f,
+ 2 * (fno.ftime & 0x1f)
+ );
+ t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
+ t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev
+ t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink
+ t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
+ t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
+ t->items[6] = MP_OBJ_NEW_SMALL_INT(fno.fsize); // st_size
+ t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime
+ t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime
+ t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime
+
+ return MP_OBJ_FROM_PTR(t);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
+
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) },
};
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);
diff --git a/extmod/vfs_fat_misc.c b/extmod/vfs_fat_misc.c
index 145b624c2b..23fe4be88d 100644
--- a/extmod/vfs_fat_misc.c
+++ b/extmod/vfs_fat_misc.c
@@ -35,7 +35,7 @@
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h"
#include "extmod/vfs_fat_file.h"
-#include "fsusermount.h"
+#include "extmod/fsusermount.h"
#include "py/lexer.h"
#if _USE_LFN
@@ -54,8 +54,9 @@ mp_obj_t fat_vfs_listdir(const char *path, bool is_str_type) {
res = f_opendir(&dir, path); /* Open the directory */
if (res != FR_OK) {
- // TODO should be mp_type_FileNotFoundError
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
+ MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
+
}
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
diff --git a/extmod/virtpin.c b/extmod/virtpin.c
new file mode 100644
index 0000000000..a5817ab4d0
--- /dev/null
+++ b/extmod/virtpin.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * 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 "extmod/virtpin.h"
+
+int mp_virtual_pin_read(mp_obj_t pin) {
+ mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
+ mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->stream_p;
+ return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL);
+}
+
+void mp_virtual_pin_write(mp_obj_t pin, int value) {
+ mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
+ mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->stream_p;
+ pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL);
+}
diff --git a/extmod/virtpin.h b/extmod/virtpin.h
new file mode 100644
index 0000000000..3821f9dec5
--- /dev/null
+++ b/extmod/virtpin.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * 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 "py/obj.h"
+
+#define MP_PIN_READ (1)
+#define MP_PIN_WRITE (2)
+#define MP_PIN_INPUT (3)
+#define MP_PIN_OUTPUT (4)
+
+// Pin protocol
+typedef struct _mp_pin_p_t {
+ mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
+} mp_pin_p_t;
+
+int mp_virtual_pin_read(mp_obj_t pin);
+void mp_virtual_pin_write(mp_obj_t pin, int value);