DRESULT disk_ioctl ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { switch (pdrv) { case PD_FLASH: switch (cmd) { case CTRL_SYNC: storage_flush(); return RES_OK; case GET_BLOCK_SIZE: *((DWORD*)buff) = 1; // high-level sector erase size in units of the small (512) block size return RES_OK; } break; #if MICROPY_HW_HAS_SDCARD case PD_SDCARD: switch (cmd) { case CTRL_SYNC: return RES_OK; case GET_BLOCK_SIZE: *((DWORD*)buff) = 1; // high-level sector erase size in units of the small (512) block size return RES_OK; } break; #endif case PD_USER: if (MP_STATE_PORT(fs_user_mount) == NULL) { // nothing mounted return RES_ERROR; } switch (cmd) { case CTRL_SYNC: if (MP_STATE_PORT(fs_user_mount)->sync[0] != MP_OBJ_NULL) { mp_call_method_n_kw(0, 0, MP_STATE_PORT(fs_user_mount)->sync); } return RES_OK; case GET_BLOCK_SIZE: *((DWORD*)buff) = 1; // high-level sector erase size in units of the small (512) bl return RES_OK; case GET_SECTOR_COUNT: { mp_obj_t ret = mp_call_method_n_kw(0, 0, MP_STATE_PORT(fs_user_mount)->count); *((DWORD*)buff) = mp_obj_get_int(ret); return RES_OK; } } break; } return RES_PARERR; }
static int call_dupterm_read(void) { if (MP_STATE_PORT(term_obj) == NULL) { return -1; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t read_m[3]; mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m); read_m[2] = MP_OBJ_NEW_SMALL_INT(1); mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); if (res == mp_const_none) { return -2; } mp_buffer_info_t bufinfo; mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); if (bufinfo.len == 0) { mp_uos_deactivate("dupterm: EOF received, deactivating\n", MP_OBJ_NULL); return -1; } nlr_pop(); return *(byte*)bufinfo.buf; } else { mp_uos_deactivate("dupterm: Exception in read() method, deactivating: ", nlr.ret_val); } return -1; }
// returns MP_OBJ_NULL if not found mp_obj_t mp_module_get(qstr module_name) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; // lookup module mp_map_elem_t *el = mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); if (el == NULL) { // module not found, look for builtin module names el = mp_map_lookup((mp_map_t*)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); if (el == NULL) { return MP_OBJ_NULL; } if (MICROPY_MODULE_BUILTIN_INIT) { // look for __init__ and call it if it exists mp_obj_t dest[2]; mp_load_method_maybe(el->value, MP_QSTR___init__, dest); if (dest[0] != MP_OBJ_NULL) { mp_call_method_n_kw(0, 0, dest); // register module so __init__ is not called again mp_module_register(module_name, el->value); } } } // module found, return it return el->value; }
DRESULT disk_write ( bdev_t pdrv, /* Physical drive nmuber (0..) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to write (1..128) */ ) { fs_user_mount_t *vfs = disk_get_device(pdrv); if (vfs == NULL) { return RES_PARERR; } if (vfs->writeblocks[0] == MP_OBJ_NULL) { // read-only block device return RES_WRPRT; } if (vfs->flags & FSUSER_NATIVE) { mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2]; if (f(buff, sector, count) != 0) { return RES_ERROR; } } else { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), (void*)buff}; vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); vfs->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); mp_call_method_n_kw(2, 0, vfs->writeblocks); // TODO handle error return } return RES_OK; }
static int call_dupterm_read(void) { if (MP_STATE_PORT(term_obj) == NULL) { return -1; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t read_m[3]; mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m); read_m[2] = MP_OBJ_NEW_SMALL_INT(1); mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); if (res == mp_const_none) { return -2; } mp_buffer_info_t bufinfo; mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); if (bufinfo.len == 0) { mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); MP_STATE_PORT(term_obj) = NULL; return -1; } nlr_pop(); return *(byte*)bufinfo.buf; } else { // Temporarily disable dupterm to avoid infinite recursion mp_obj_t save_term = MP_STATE_PORT(term_obj); MP_STATE_PORT(term_obj) = NULL; mp_printf(&mp_plat_print, "dupterm: "); mp_obj_print_exception(&mp_plat_print, nlr.ret_val); MP_STATE_PORT(term_obj) = save_term; } return -1; }
DRESULT disk_ioctl ( bdev_t pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { fs_user_mount_t *vfs = disk_get_device(pdrv); if (vfs == NULL) { return RES_PARERR; } // First part: call the relevant method of the underlying block device mp_obj_t ret = mp_const_none; if (vfs->flags & FSUSER_HAVE_IOCTL) { // new protocol with ioctl static const uint8_t op_map[8] = { [CTRL_SYNC] = BP_IOCTL_SYNC, [GET_SECTOR_COUNT] = BP_IOCTL_SEC_COUNT, [GET_SECTOR_SIZE] = BP_IOCTL_SEC_SIZE, [IOCTL_INIT] = BP_IOCTL_INIT, }; uint8_t bp_op = op_map[cmd & 7]; if (bp_op != 0) { vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op); vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); } } else {
STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in); mp_obj_t sock = o->sock; mp_obj_t dest[3]; mp_load_method(sock, MP_QSTR_setblocking, dest); dest[2] = flag_in; return mp_call_method_n_kw(1, 0, dest); }
STATIC mp_obj_t socket_close(mp_obj_t 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); mp_obj_t dest[2]; mp_load_method(self->sock, MP_QSTR_close, dest); return mp_call_method_n_kw(0, 0, dest); }
mp_obj_t vfs_proxy_call(qstr method_name, mp_uint_t n_args, const mp_obj_t *args) { if (MP_STATE_PORT(fs_user_mount)[0] == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENODEV))); } mp_obj_t meth[n_args + 2]; mp_load_method(MP_STATE_PORT(fs_user_mount)[0], method_name, meth); if (args != NULL) { memcpy(meth + 2, args, n_args * sizeof(*args)); } return mp_call_method_n_kw(n_args, 0, meth); }
STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_websocket_t *self = self_in; assert(size < 0x10000); byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)}; int hdr_sz; if (size < 126) { header[1] = size; hdr_sz = 2; } else { header[1] = 126; header[2] = size >> 8; header[3] = size & 0xff; hdr_sz = 4; } mp_obj_t dest[3]; if (self->opts & BLOCKING_WRITE) { mp_load_method(self->sock, MP_QSTR_setblocking, dest); dest[2] = mp_const_true; mp_call_method_n_kw(1, 0, dest); } 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) { dest[2] = mp_const_false; mp_call_method_n_kw(1, 0, dest); } if (*errcode != 0) { return MP_STREAM_ERROR; } return out_sz; }
STATIC void gc_sweep(void) { mp_uint_t block; #if MICROPY_PY_GC_COLLECT_RETVAL gc_collected = 0; #endif // free unmarked heads and their tails int free_tail = 0; for (block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { switch (ATB_GET_KIND(block)) { case AT_HEAD: #if MICROPY_ENABLE_FINALISER if (FTB_GET(block)) { mp_obj_t obj = (mp_obj_t)PTR_FROM_BLOCK(block); if (((mp_obj_base_t*)obj)->type != MP_OBJ_NULL) { // if the object has a type then see if it has a __del__ method mp_obj_t dest[2]; mp_load_method_maybe(obj, MP_QSTR___del__, dest); if (dest[0] != MP_OBJ_NULL) { // load_method returned a method mp_call_method_n_kw(0, 0, dest); } } // clear finaliser flag FTB_CLEAR(block); } #endif free_tail = 1; #if MICROPY_PY_GC_COLLECT_RETVAL gc_collected++; #endif // fall through to free the head // no break - disable eclipse static analyzer warning - intentional fall through case AT_TAIL: if (free_tail) { DEBUG_printf("gc_sweep(%p)\n",PTR_FROM_BLOCK(block)); ATB_ANY_TO_FREE(block); } break; case AT_MARK: ATB_MARK_TO_HEAD(block); free_tail = 0; break; } } }
STATIC mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); // check if __reversed__ exists, and if so delegate to it mp_obj_t dest[2]; mp_load_method_maybe(args[0], MP_QSTR___reversed__, dest); if (dest[0] != MP_OBJ_NULL) { return mp_call_method_n_kw(0, 0, dest); } mp_obj_reversed_t *o = m_new_obj(mp_obj_reversed_t); o->base.type = type; o->seq = args[0]; o->cur_index = mp_obj_get_int(mp_obj_len(args[0])); // start at the end of the sequence return MP_OBJ_FROM_PTR(o); }
STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { assert(n_args <= PROXY_MAX_ARGS); if (vfs == MP_VFS_NONE) { // mount point not found mp_raise_OSError(MP_ENODEV); } if (vfs == MP_VFS_ROOT) { // can't do operation on root dir mp_raise_OSError(MP_EPERM); } mp_obj_t meth[2 + PROXY_MAX_ARGS]; mp_load_method(vfs->obj, meth_name, meth); if (args != NULL) { memcpy(meth + 2, args, n_args * sizeof(*args)); } return mp_call_method_n_kw(n_args, 0, meth); }
STATIC void gc_sweep(void) { #if MICROPY_PY_GC_COLLECT_RETVAL MP_STATE_MEM(gc_collected) = 0; #endif // free unmarked heads and their tails int free_tail = 0; for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { switch (ATB_GET_KIND(block)) { case AT_HEAD: #if MICROPY_ENABLE_FINALISER if (FTB_GET(block)) { mp_obj_base_t *obj = (mp_obj_base_t*)PTR_FROM_BLOCK(block); if (obj->type != NULL) { // if the object has a type then see if it has a __del__ method mp_obj_t dest[2]; mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest); if (dest[0] != MP_OBJ_NULL) { // load_method returned a method mp_call_method_n_kw(0, 0, dest); } } // clear finaliser flag FTB_CLEAR(block); } #endif free_tail = 1; DEBUG_printf("gc_sweep(%x)\n", PTR_FROM_BLOCK(block)); #if MICROPY_PY_GC_COLLECT_RETVAL MP_STATE_MEM(gc_collected)++; #endif // fall through to free the head case AT_TAIL: if (free_tail) { ATB_ANY_TO_FREE(block); } break; case AT_MARK: ATB_MARK_TO_HEAD(block); free_tail = 0; break; } } }
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; if (nlr_push(&nlr) == 0) { mp_obj_t write_m[3]; mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m); write_m[2] = mp_obj_new_bytearray_by_ref(len, (char*)str); mp_call_method_n_kw(1, 0, write_m); nlr_pop(); } else { // Temporarily disable dupterm to avoid infinite recursion mp_obj_t save_term = MP_STATE_PORT(term_obj); MP_STATE_PORT(term_obj) = NULL; mp_printf(&mp_plat_print, "dupterm: "); mp_obj_print_exception(&mp_plat_print, nlr.ret_val); MP_STATE_PORT(term_obj) = save_term; } } }
DRESULT disk_write ( BYTE pdrv, /* Physical drive nmuber (0..) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to write (1..128) */ ) { switch (pdrv) { case PD_FLASH: for (int i = 0; i < count; i++) { if (!storage_write_block(buff + i * FLASH_BLOCK_SIZE, sector + i)) { return RES_ERROR; } } return RES_OK; #if MICROPY_HW_HAS_SDCARD case PD_SDCARD: if (sdcard_write_blocks(buff, sector, count) != 0) { return RES_ERROR; } return RES_OK; #endif case PD_USER: if (MP_STATE_PORT(fs_user_mount) == NULL) { // nothing mounted return RES_ERROR; } if (MP_STATE_PORT(fs_user_mount)->writeblocks[0] == MP_OBJ_NULL) { // read-only block device return RES_ERROR; } MP_STATE_PORT(fs_user_mount)->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); MP_STATE_PORT(fs_user_mount)->writeblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, (void*)buff); mp_call_method_n_kw(2, 0, MP_STATE_PORT(fs_user_mount)->writeblocks); return RES_OK; } return RES_PARERR; }
mp_int_t mp_obj_hash(mp_obj_t o_in) { if (o_in == mp_const_false) { return 0; // needs to hash to same as the integer 0, since False==0 } else if (o_in == mp_const_true) { return 1; // needs to hash to same as the integer 1, since True==1 } else if (MP_OBJ_IS_SMALL_INT(o_in)) { return MP_OBJ_SMALL_INT_VALUE(o_in); } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_int)) { return mp_obj_int_hash(o_in); } else if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) { return mp_obj_str_get_hash(o_in); } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_NoneType)) { return (mp_int_t)o_in; } else if (MP_OBJ_IS_FUN(o_in)) { return (mp_int_t)o_in; } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_tuple)) { return mp_obj_tuple_hash(o_in); } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_type)) { return (mp_int_t)o_in; } else if (MP_OBJ_IS_OBJ(o_in)) { // if a valid __hash__ method exists, use it mp_obj_t hash_method[2]; mp_load_method_maybe(o_in, MP_QSTR___hash__, hash_method); if (hash_method[0] != MP_OBJ_NULL) { mp_obj_t hash_val = mp_call_method_n_kw(0, 0, hash_method); if (MP_OBJ_IS_INT(hash_val)) { return mp_obj_int_get_truncated(hash_val); } } } // TODO hash class and instances - in CPython by default user created classes' __hash__ resolves to their id if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unhashable type")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unhashable type: '%s'", mp_obj_get_type_str(o_in))); } }
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; if (nlr_push(&nlr) == 0) { mp_obj_t write_m[3]; mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m); mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj)); void *org_items = arr->items; arr->items = (void*)str; arr->len = len; write_m[2] = MP_STATE_PORT(dupterm_arr_obj); mp_call_method_n_kw(1, 0, write_m); arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj)); arr->items = org_items; arr->len = 1; nlr_pop(); } else { mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val); } } }
STATIC void gc_sweep(void) { // free unmarked heads and their tails int free_tail = 0; for (machine_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { switch (ATB_GET_KIND(block)) { case AT_HEAD: #if MICROPY_ENABLE_FINALISER if (FTB_GET(block)) { mp_obj_t obj = (mp_obj_t)PTR_FROM_BLOCK(block); if (((mp_obj_base_t*)obj)->type != MP_OBJ_NULL) { // if the object has a type then see if it has a __del__ method mp_obj_t dest[2]; mp_load_method_maybe(obj, MP_QSTR___del__, dest); if (dest[0] != MP_OBJ_NULL) { // load_method returned a method mp_call_method_n_kw(0, 0, dest); } } // clear finaliser flag FTB_CLEAR(block); } #endif free_tail = 1; // fall through to free the head case AT_TAIL: if (free_tail) { ATB_ANY_TO_FREE(block); } break; case AT_MARK: ATB_MARK_TO_HEAD(block); free_tail = 0; break; } } }
mp_obj_t mp_stream_close(mp_obj_t stream) { // TODO: Still consider using ioctl for close mp_obj_t dest[2]; mp_load_method(stream, MP_QSTR_close, dest); return mp_call_method_n_kw(0, 0, dest); }
static inline void close_meth(mp_obj_t stream) { mp_obj_t dest[2]; mp_load_method(stream, MP_QSTR_close, dest); mp_call_method_n_kw(0, 0, dest); }