summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/bc.h12
-rw-r--r--py/objgenerator.c35
-rw-r--r--py/vm.c43
-rw-r--r--stmhal/Makefile24
-rw-r--r--stmhal/boards/PYBv10/mpconfigboard.h33
-rw-r--r--stmhal/boards/PYBv10/pins.csv45
-rw-r--r--stmhal/boards/PYBv10/stm32f4xx_hal_conf.h393
-rw-r--r--stmhal/main.c29
-rw-r--r--stmhal/osmodule.c178
-rw-r--r--stmhal/osmodule.h1
-rw-r--r--stmhal/pybmodule.c17
-rw-r--r--stmhal/qstrdefsport.h17
-rw-r--r--stmhal/rng.c25
-rw-r--r--stmhal/rng.h4
-rw-r--r--stmhal/servo.c142
-rw-r--r--stmhal/servo.h5
-rw-r--r--stmhal/stm32f4xx_hal_msp.c2
-rw-r--r--stmhal/timemodule.c44
-rw-r--r--stmhal/timemodule.h1
-rw-r--r--stmhal/usb.c21
-rw-r--r--stmhal/usb.h3
-rw-r--r--stmhal/usbd_cdc_interface.c156
-rw-r--r--stmhal/usbd_cdc_interface.h1
-rw-r--r--stmhal/usbd_conf.c8
-rw-r--r--stmhal/usbd_conf.h10
-rw-r--r--stmhal/usbd_desc_cdc_msc.c (renamed from stmhal/usbd_desc_vcp.c)0
-rw-r--r--stmhal/usbd_desc_msc.c227
-rw-r--r--stmhal/usbd_msc_storage.c2
-rw-r--r--stmhal/usbdev/class/cdc_msc/inc/usbd_cdc_msc.h132
-rw-r--r--stmhal/usbdev/class/cdc_msc/inc/usbd_msc_bot.h151
-rw-r--r--stmhal/usbdev/class/cdc_msc/inc/usbd_msc_data.h104
-rw-r--r--stmhal/usbdev/class/cdc_msc/inc/usbd_msc_scsi.h193
-rw-r--r--stmhal/usbdev/class/cdc_msc/src/usbd_cdc_msc.c578
-rw-r--r--stmhal/usbdev/class/cdc_msc/src/usbd_msc.c609
-rw-r--r--stmhal/usbdev/class/cdc_msc/src/usbd_msc_bot.c407
-rw-r--r--stmhal/usbdev/class/cdc_msc/src/usbd_msc_data.c134
-rw-r--r--stmhal/usbdev/class/cdc_msc/src/usbd_msc_scsi.c770
-rw-r--r--stmhal/usbdev/core/inc/usbd_conf_template.h163
-rw-r--r--stmhal/usbdev/core/src/usbd_conf_template.c258
-rw-r--r--tests/basics/generator-exc.py53
40 files changed, 4217 insertions, 813 deletions
diff --git a/py/bc.h b/py/bc.h
index aac35954d7..0709897750 100644
--- a/py/bc.h
+++ b/py/bc.h
@@ -4,6 +4,16 @@ typedef enum {
MP_VM_RETURN_EXCEPTION,
} mp_vm_return_kind_t;
+// Exception stack entry
+typedef struct _mp_exc_stack {
+ const byte *handler;
+ // bit 0 is saved currently_in_except_block value
+ machine_uint_t val_sp;
+ // We might only have 2 interesting cases here: SETUP_EXCEPT & SETUP_FINALLY,
+ // consider storing it in bit 1 of val_sp. TODO: SETUP_WITH?
+ byte opcode;
+} mp_exc_stack;
+
mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, uint n_state, mp_obj_t *ret);
-mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out);
+mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out, mp_exc_stack *exc_stack, mp_exc_stack **exc_sp_in_out, volatile mp_obj_t inject_exc);
void mp_byte_code_print(const byte *code, int len);
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 8c4bb595f1..2db04ad742 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -56,8 +56,10 @@ typedef struct _mp_obj_gen_instance_t {
const byte *code_info;
const byte *ip;
mp_obj_t *sp;
+ mp_exc_stack *exc_sp;
uint n_state;
- mp_obj_t state[];
+ mp_obj_t state[0]; // Variable-length
+ mp_exc_stack exc_state[0]; // Variable-length
} mp_obj_gen_instance_t;
void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -68,7 +70,7 @@ mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
return self_in;
}
-STATIC mp_obj_t gen_next_send(mp_obj_t self_in, mp_obj_t send_value) {
+STATIC mp_obj_t gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value) {
mp_obj_gen_instance_t *self = self_in;
if (self->ip == 0) {
return mp_const_stop_iteration;
@@ -80,7 +82,9 @@ STATIC mp_obj_t gen_next_send(mp_obj_t self_in, mp_obj_t send_value) {
} else {
*self->sp = send_value;
}
- mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(self->code_info, &self->ip, &self->state[self->n_state - 1], &self->sp);
+ mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(self->code_info, &self->ip,
+ &self->state[self->n_state - 1], &self->sp, (mp_exc_stack*)(self->state + self->n_state),
+ &self->exc_sp, throw_value);
switch (vm_return_kind) {
case MP_VM_RETURN_NORMAL:
// Explicitly mark generator as completed. If we don't do this,
@@ -100,19 +104,21 @@ STATIC mp_obj_t gen_next_send(mp_obj_t self_in, mp_obj_t send_value) {
return *self->sp;
case MP_VM_RETURN_EXCEPTION:
+ self->ip = 0;
+ nlr_jump(self->state[self->n_state - 1]);
+
default:
- // TODO
assert(0);
return mp_const_none;
}
}
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
- return gen_next_send(self_in, mp_const_none);
+ return gen_resume(self_in, mp_const_none, MP_OBJ_NULL);
}
STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) {
- mp_obj_t ret = gen_next_send(self_in, send_value);
+ mp_obj_t ret = gen_resume(self_in, send_value, MP_OBJ_NULL);
if (ret == mp_const_stop_iteration) {
nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
} else {
@@ -122,8 +128,21 @@ STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) {
STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send);
+STATIC mp_obj_t gen_instance_throw(uint n_args, const mp_obj_t *args) {
+ mp_obj_t ret = gen_resume(args[0], mp_const_none, n_args == 2 ? args[1] : args[2]);
+ if (ret == mp_const_stop_iteration) {
+ nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
+ } else {
+ return ret;
+ }
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_instance_throw);
+
+
STATIC const mp_method_t gen_type_methods[] = {
{ "send", &gen_instance_send_obj },
+ { "throw", &gen_instance_throw_obj },
{ NULL, NULL }, // end-of-list sentinel
};
@@ -137,11 +156,13 @@ const mp_obj_type_t gen_instance_type = {
};
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {
- mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, mp_obj_t, n_state);
+ // TODO: 4 is hardcoded number from vm.c, calc exc stack size instead.
+ mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, n_state * sizeof(mp_obj_t) + 4 * sizeof(mp_exc_stack));
o->base.type = &gen_instance_type;
o->code_info = bytecode;
o->ip = bytecode;
o->sp = &o->state[0] - 1; // sp points to top of stack, which starts off 1 below the state
+ o->exc_sp = (mp_exc_stack*)(o->state + n_state) - 1;
o->n_state = n_state;
// copy args to end of state array, in reverse (that's how mp_execute_byte_code_2 needs it)
diff --git a/py/vm.c b/py/vm.c
index 7b78b5fefb..7f4efeea0f 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -17,16 +17,6 @@
// top element.
// Exception stack also grows up, top element is also pointed at.
-// Exception stack entry
-typedef struct _mp_exc_stack {
- const byte *handler;
- // bit 0 is saved currently_in_except_block value
- machine_uint_t val_sp;
- // We might only have 2 interesting cases here: SETUP_EXCEPT & SETUP_FINALLY,
- // consider storing it in bit 1 of val_sp. TODO: SETUP_WITH?
- byte opcode;
-} mp_exc_stack;
-
// Exception stack unwind reasons (WHY_* in CPython-speak)
// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
// left to do encoded in the JUMP number
@@ -89,8 +79,10 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args,
}
}
+ mp_exc_stack exc_stack[4];
+ mp_exc_stack *exc_sp = &exc_stack[0] - 1;
// execute the byte code
- mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp);
+ mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp, MP_OBJ_NULL);
switch (vm_return_kind) {
case MP_VM_RETURN_NORMAL:
@@ -113,7 +105,10 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args,
// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
-mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out) {
+mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out,
+ mp_obj_t *fastn, mp_obj_t **sp_in_out,
+ mp_exc_stack *exc_stack, mp_exc_stack **exc_sp_in_out,
+ volatile mp_obj_t inject_exc) {
// careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
const byte *ip = *ip_in_out;
@@ -123,14 +118,21 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
mp_obj_t obj1, obj2;
nlr_buf_t nlr;
- volatile machine_uint_t currently_in_except_block = 0; // 0 or 1, to detect nested exceptions
- mp_exc_stack exc_stack[4];
- mp_exc_stack *volatile exc_sp = &exc_stack[0] - 1; // stack grows up, exc_sp points to top of stack
+ volatile machine_uint_t currently_in_except_block = (int)*exc_sp_in_out & 1; // 0 or 1, to detect nested exceptions
+ mp_exc_stack *volatile exc_sp = (void*)((int)*exc_sp_in_out & ~1); // stack grows up, exc_sp points to top of stack
const byte *volatile save_ip = ip; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop)
// outer exception handling loop
for (;;) {
if (nlr_push(&nlr) == 0) {
+ // If we have exception to inject, now that we finish setting up
+ // execution context, raise it. This works as if RAISE_VARARGS
+ // bytecode was executed.
+ if (inject_exc != MP_OBJ_NULL) {
+ mp_obj_t t = inject_exc;
+ inject_exc = MP_OBJ_NULL;
+ nlr_jump(rt_make_raise_obj(t));
+ }
// loop to execute byte code
for (;;) {
dispatch_loop:
@@ -434,7 +436,7 @@ unwind_jump:
// matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
case MP_BC_POP_BLOCK:
// we are exiting an exception handler, so pop the last one of the exception-stack
- assert(exc_sp >= &exc_stack[0]);
+ assert(exc_sp >= exc_stack);
currently_in_except_block = (exc_sp->val_sp & 1); // restore previous state
exc_sp--; // pop back to previous exception handler
break;
@@ -443,7 +445,7 @@ unwind_jump:
case MP_BC_POP_EXCEPT:
// TODO need to work out how blocks work etc
// pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
- assert(exc_sp >= &exc_stack[0]);
+ assert(exc_sp >= exc_stack);
assert(currently_in_except_block);
//sp = (mp_obj_t*)(*exc_sp--);
//exc_sp--; // discard ip
@@ -592,7 +594,7 @@ unwind_return:
}
nlr_pop();
*sp_in_out = sp;
- assert(exc_sp == &exc_stack[0] - 1);
+ assert(exc_sp == exc_stack - 1);
return MP_VM_RETURN_NORMAL;
case MP_BC_RAISE_VARARGS:
@@ -605,6 +607,7 @@ unwind_return:
nlr_pop();
*ip_in_out = ip;
*sp_in_out = sp;
+ *exc_sp_in_out = (void*)((int)exc_sp | currently_in_except_block);
return MP_VM_RETURN_YIELD;
case MP_BC_IMPORT_NAME:
@@ -654,7 +657,7 @@ unwind_return:
while (currently_in_except_block) {
// nested exception
- assert(exc_sp >= &exc_stack[0]);
+ assert(exc_sp >= exc_stack);
// TODO make a proper message for nested exception
// at the moment we are just raising the very last exception (the one that caused the nested exception)
@@ -664,7 +667,7 @@ unwind_return:
exc_sp--; // pop back to previous exception handler
}
- if (exc_sp >= &exc_stack[0]) {
+ if (exc_sp >= exc_stack) {
// set flag to indicate that we are now handling an exception
currently_in_except_block = 1;
diff --git a/stmhal/Makefile b/stmhal/Makefile
index 86791607a9..938871aefb 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -21,7 +21,7 @@ INC += -I$(PY_SRC)
INC += -I$(CMSIS_DIR)/inc
INC += -I$(CMSIS_DIR)/devinc
INC += -I$(HAL_DIR)/inc
-INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc/inc -I$(USBDEV_DIR)/class/msc/inc
+INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc_msc/inc
#INC += -I$(USBHOST_DIR)
INC += -I$(FATFS_DIR)/src
#INC += -I$(CC3K_DIR)
@@ -29,7 +29,7 @@ INC += -I$(FATFS_DIR)/src
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 $(CFLAGS_CORTEX_M4) $(COPT)
-BOARD ?= PYBOARD4
+BOARD ?= PYBv10
ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
endif
@@ -56,9 +56,8 @@ SRC_C = \
stm32f4xx_it.c \
stm32f4xx_hal_msp.c \
usbd_conf.c \
- usbd_desc_vcp.c \
+ usbd_desc_cdc_msc.c \
usbd_cdc_interface.c \
- usbd_desc_msc.c \
usbd_msc_storage.c \
pendsv.c \
systick.c \
@@ -74,11 +73,14 @@ SRC_C = \
gccollect.c \
pyexec.c \
pybmodule.c \
+ osmodule.c \
+ timemodule.c \
import.c \
lexerfatfs.c \
gpio.c \
exti.c \
usrsw.c \
+ rng.c \
rtc.c \
flash.c \
storage.c \
@@ -87,8 +89,8 @@ SRC_C = \
diskio.c \
lcd.c \
accel.c \
+ servo.c \
-# servo.c \
# timer.c \
# audio.c \
# i2c.c \
@@ -110,6 +112,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/src/,\
stm32f4xx_hal_pcd.c \
stm32f4xx_hal_rcc.c \
stm32f4xx_hal_rcc_ex.c \
+ stm32f4xx_hal_rng.c \
stm32f4xx_hal_rtc.c \
stm32f4xx_hal_rtc_ex.c \
stm32f4xx_hal_sd.c \
@@ -124,13 +127,14 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\
core/src/usbd_core.c \
core/src/usbd_ctlreq.c \
core/src/usbd_ioreq.c \
- class/cdc/src/usbd_cdc.c \
- class/msc/src/usbd_msc.c \
- class/msc/src/usbd_msc_bot.c \
- class/msc/src/usbd_msc_scsi.c \
- class/msc/src/usbd_msc_data.c \
+ class/cdc_msc/src/usbd_cdc_msc.c \
+ class/cdc_msc/src/usbd_msc_bot.c \
+ class/cdc_msc/src/usbd_msc_scsi.c \
+ class/cdc_msc/src/usbd_msc_data.c \
)
+# class/cdc/src/usbd_cdc.c \
+ class/msc/src/usbd_msc.c \
# usbd_core.c \
usbd_ioreq.c \
usbd_req.c \
diff --git a/stmhal/boards/PYBv10/mpconfigboard.h b/stmhal/boards/PYBv10/mpconfigboard.h
new file mode 100644
index 0000000000..b7b0259440
--- /dev/null
+++ b/stmhal/boards/PYBv10/mpconfigboard.h
@@ -0,0 +1,33 @@
+#define PYBOARD4
+
+#define MICROPY_HW_BOARD_NAME "PYBv1.0"
+
+#define MICROPY_HW_HAS_SWITCH (1)
+#define MICROPY_HW_HAS_SDCARD (1)
+#define MICROPY_HW_HAS_MMA7660 (1)
+#define MICROPY_HW_HAS_LIS3DSH (0)
+#define MICROPY_HW_HAS_LCD (1)
+#define MICROPY_HW_HAS_WLAN (0)
+#define MICROPY_HW_ENABLE_RNG (1)
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_TIMER (1)
+#define MICROPY_HW_ENABLE_SERVO (1)
+#define MICROPY_HW_ENABLE_AUDIO (1)
+
+// USRSW has no pullup or pulldown, and pressing the switch makes the input go low
+#define USRSW_PIN (pin_B3)
+#define USRSW_PULL (GPIO_PULLUP)
+#define USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
+#define USRSW_PRESSED (0)
+
+/* LED */
+#define PYB_LED1 (pin_A13) // red
+#define PYB_LED2 (pin_A14) // green
+#define PYB_LED3 (pin_A15) // yellow
+#define PYB_LED4 (pin_B4) // blue
+
+#define PYB_OTYPE (GPIO_MODE_OUTPUT_PP)
+
+#define PYB_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask)
+#define PYB_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
+
diff --git a/stmhal/boards/PYBv10/pins.csv b/stmhal/boards/PYBv10/pins.csv
new file mode 100644
index 0000000000..2ca7fef184
--- /dev/null
+++ b/stmhal/boards/PYBv10/pins.csv
@@ -0,0 +1,45 @@
+X1,PA0
+X2,PA1
+X3,PA2
+X4,PA3
+X5,PA4
+X6,PA5
+X7,PA6
+X8,PA7
+X9,PB6
+X10,PB7
+X11,PC4
+X12,PC5
+X13,Reset
+X14,GND
+X15,3.3V
+X16,VIN
+X17,PB3
+X18,PC13
+X19,PC0
+X20,PC1
+X21,PC2
+X22,PC3
+X23,A3.3V
+X24,AGND
+Y1,PC6
+Y2,PC7
+Y3,PB8
+Y4,PB9
+Y5,PB12
+Y6,PB13
+Y7,PB14
+Y8,PB15
+Y9,PB10
+Y10,PB11
+Y11,PB0
+Y12,PB1
+Y13,Reset
+Y14,GND
+Y15,3.3V
+Y16,VIN
+LED_BLUE,PB4
+LED_RED,PA13
+LED_GREEN,PA14
+LED_YELLOW,PA15
+SW,PB3
diff --git a/stmhal/boards/PYBv10/stm32f4xx_hal_conf.h b/stmhal/boards/PYBv10/stm32f4xx_hal_conf.h
new file mode 100644
index 0000000000..315c24dc67
--- /dev/null
+++ b/stmhal/boards/PYBv10/stm32f4xx_hal_conf.h
@@ -0,0 +1,393 @@
+/**
+ ******************************************************************************
+ * @file stm32f4xx_hal_conf.h
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 26-February-2014
+ * @brief HAL configuration file.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_HAL_CONF_H
+#define __STM32F4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+#define STM32F405xx
+#define USE_USB_FS
+
+/* ########################## Module Selection ############################## */
+/**
+ * @brief This is the list of modules to be used in the HAL driver
+ */
+#define HAL_MODULE_ENABLED
+#define HAL_ADC_MODULE_ENABLED
+#define HAL_CAN_MODULE_ENABLED
+#define HAL_CRC_MODULE_ENABLED
+#define HAL_CRYP_MODULE_ENABLED
+#define HAL_DAC_MODULE_ENABLED
+#define HAL_DCMI_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+/* #define HAL_DMA2D_MODULE_ENABLED */
+#define HAL_ETH_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_NAND_MODULE_ENABLED
+#define HAL_NOR_MODULE_ENABLED
+#define HAL_PCCARD_MODULE_ENABLED
+#define HAL_SRAM_MODULE_ENABLED
+/* #define HAL_SDRAM_MODULE_ENABLED */
+#define HAL_HASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_I2S_MODULE_ENABLED
+#define HAL_IWDG_MODULE_ENABLED
+#define HAL_LTDC_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_RNG_MODULE_ENABLED
+#define HAL_RTC_MODULE_ENABLED
+/* #define HAL_SAI_MODULE_ENABLED */
+#define HAL_SD_MODULE_ENABLED
+#define HAL_SPI_MODULE_ENABLED
+#define HAL_TIM_MODULE_ENABLED
+#define HAL_UART_MODULE_ENABLED
+#define HAL_USART_MODULE_ENABLED
+#define HAL_IRDA_MODULE_ENABLED
+#define HAL_SMARTCARD_MODULE_ENABLED
+#define HAL_WWDG_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_PCD_MODULE_ENABLED
+#define HAL_HCD_MODULE_ENABLED
+
+
+/* ########################## HSE/HSI Values adaptation ##################### */
+/**
+ * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSE is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief Internal High Speed oscillator (HSI) value.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSI is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @brief External clock source for I2S peripheral
+ * This value is used by the I2S HAL module to compute the I2S clock source
+ * frequency, this source is inserted directly through I2S_CKIN pad.
+ */
+#if !defined (EXTERNAL_CLOCK_VALUE)
+ #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* EXTERNAL_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+ === you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+ * @brief This is the HAL system configuration section
+ */
+#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
+#define USE_RTOS 0
+#define PREFETCH_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define DATA_CACHE_ENABLE 1
+
+/* ########################## Assert Selection ############################## */
+/**
+ * @brief Uncomment the line below to expanse the "assert_param" macro in the
+ * HAL drivers code
+ */
+/* #define USE_FULL_ASSERT 1 */
+
+/* ################## Ethernet peripheral configuration ##################### */
+
+/* Section 1 : Ethernet peripheral configuration */
+
+/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
+#define MAC_ADDR0 2
+#define MAC_ADDR1 0
+#define MAC_ADDR2 0
+#define MAC_ADDR3 0
+#define MAC_ADDR4 0
+#define MAC_ADDR5 0
+
+/* Definition of the Ethernet driver buffers size and count */
+#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
+#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
+#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
+#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
+
+/* Section 2: PHY configuration section */
+
+/* DP83848 PHY Address*/
+#define DP83848_PHY_ADDRESS 0x01
+/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
+#define PHY_RESET_DELAY ((uint32_t)0x000000FF)
+/* PHY Configuration delay */
+#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF)
+
+#define PHY_READ_TO ((uint32_t)0x0000FFFF)
+#define PHY_WRITE_TO ((uint32_t)0x0000FFFF)
+
+/* Section 3: Common PHY Registers */
+
+#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */
+#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */
+
+#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */
+#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */
+#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */
+#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */
+#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */
+#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */
+#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */
+#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */
+
+#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */
+#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */
+#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */
+
+/* Section 4: Extended PHY Registers */
+
+#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */
+#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */
+#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */
+
+#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */
+#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */
+#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */
+
+#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */
+#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */
+
+#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */
+#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */
+
+/* Includes ------------------------------------------------------------------*/
+/**
+ * @brief Include module's header file
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "stm32f4xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "stm32f4xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+ #include "stm32f4xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+ #include "stm32f4xx_hal_can.h"
+#endif /* HAL_CAN_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+ #include "stm32f4xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+ #include "stm32f4xx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DMA2D_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma2d.h"
+#endif /* HAL_DMA2D_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+ #include "stm32f4xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_DCMI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dcmi.h"
+#endif /* HAL_DCMI_MODULE_ENABLED */
+
+#ifdef HAL_ETH_MODULE_ENABLED
+ #include "stm32f4xx_hal_eth.h"
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sram.h"
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+ #include "stm32f4xx_hal_nor.h"
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+ #include "stm32f4xx_hal_nand.h"
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+#ifdef HAL_PCCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pccard.h"
+#endif /* HAL_PCCARD_MODULE_ENABLED */
+
+#ifdef HAL_SDRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sdram.h"
+#endif /* HAL_SDRAM_MODULE_ENABLED */
+
+#ifdef HAL_HASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_hash.h"
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2s.h"
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LTDC_MODULE_ENABLED
+ #include "stm32f4xx_hal_ltdc.h"
+#endif /* HAL_LTDC_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32f4xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32f4xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32f4xx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SD_MODULE_ENABLED
+ #include "stm32f4xx_hal_sd.h"
+#endif /* HAL_SD_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32f4xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32f4xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32f4xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_hcd.h"
+#endif /* HAL_HCD_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr: If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval None
+ */
+ #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_HAL_CONF_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/main.c b/stmhal/main.c
index d92ccdd5b1..6511891a1b 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -10,7 +10,6 @@
#include "pendsv.h"
#include "mpconfig.h"
#include "qstr.h"
-#include "nlr.h"
#include "misc.h"
#include "lexer.h"
#include "parse.h"
@@ -23,19 +22,22 @@
#include "gccollect.h"
#include "pyexec.h"
#include "pybmodule.h"
+#include "osmodule.h"
+#include "timemodule.h"
#include "usart.h"
#include "led.h"
#include "exti.h"
#include "usrsw.h"
#include "usb.h"
+#include "rng.h"
#include "rtc.h"
#include "storage.h"
#include "sdcard.h"
#include "ff.h"
#include "lcd.h"
#include "accel.h"
-#if 0
#include "servo.h"
+#if 0
#include "timer.h"
#include "pybwlan.h"
#include "pin.h"
@@ -247,23 +249,24 @@ soft_reset:
lcd_init();
#endif
-#if 0
+#if MICROPY_HW_ENABLE_RNG
+ // RNG
+ rng_init();
+#endif
+
#if MICROPY_HW_ENABLE_SERVO
// servo
servo_init();
#endif
+#if 0
#if MICROPY_HW_ENABLE_TIMER
// timer
timer_init();
#endif
-
-#if MICROPY_HW_ENABLE_RNG
- // RNG
- RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
- RNG_Cmd(ENABLE);
#endif
+#if 0
pin_map_init();
#endif
@@ -274,6 +277,11 @@ soft_reset:
// probably shouldn't do this, so we are compatible with CPython
rt_store_name(MP_QSTR_pyb, (mp_obj_t)&pyb_module);
+ // pre-import the os and time modules
+ // TODO don't do this! (need a way of registering builtin modules...)
+ rt_store_name(MP_QSTR_os, (mp_obj_t)&os_module);
+ rt_store_name(MP_QSTR_time, (mp_obj_t)&time_module);
+
// check if user switch held (initiates reset of filesystem)
bool reset_filesystem = false;
#if MICROPY_HW_HAS_SWITCH
@@ -336,7 +344,6 @@ soft_reset:
fno.lfname = NULL;
fno.lfsize = 0;
#endif
- led_debug(0, 500);
FRESULT res = f_stat("0:/boot.py", &fno);
if (res == FR_OK) {
if (fno.fattrib & AM_DIR) {
@@ -400,7 +407,7 @@ soft_reset:
pyb_usb_host_init();
#elif defined(USE_DEVICE_MODE)
// USB device
- pyb_usb_dev_init(USBD_DEVICE_MSC, usbd_medium_kind);
+ pyb_usb_dev_init(USBD_DEVICE_CDC_MSC, usbd_medium_kind);
#endif
#if MICROPY_HW_HAS_MMA7660
@@ -474,10 +481,8 @@ soft_reset:
pyexec_repl();
-#if 0
printf("PYB: sync filesystems\n");
storage_flush();
-#endif
printf("PYB: soft reboot\n");
diff --git a/stmhal/osmodule.c b/stmhal/osmodule.c
new file mode 100644
index 0000000000..7f32fe6749
--- /dev/null
+++ b/stmhal/osmodule.c
@@ -0,0 +1,178 @@
+#include <string.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "map.h"
+#include "systick.h"
+#include "rng.h"
+#include "storage.h"
+#include "ff.h"
+#include "osmodule.h"
+
+#if _USE_LFN
+static char lfn[_MAX_LFN + 1]; /* Buffer to store the LFN */
+#endif
+
+STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) {
+ const mp_obj_type_t *local_str_type = &str_type;
+ const char *path;
+ if (n_args == 1) {
+ if (mp_obj_get_type(args[0]) == &bytes_type) {
+ local_str_type = &bytes_type;
+ }
+ path = mp_obj_str_get_str(args[0]);
+ } else {
+ path = "0:";
+ }
+
+ FRESULT res;
+ FILINFO fno;
+ DIR dir;
+#if _USE_LFN
+ fno.lfname = lfn;
+ fno.lfsize = sizeof lfn;
+#endif
+
+ res = f_opendir(&dir, path); /* Open the directory */
+ if (res != FR_OK) {
+ // TODO should be mp_type_FileNotFoundError
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
+ }
+
+ mp_obj_t dir_list = mp_obj_new_list(0, NULL);
+
+ uint path_len = strlen(path);
+ if (path[path_len - 1] == '/') {
+ path_len--;
+ }
+
+ for (;;) {
+ res = f_readdir(&dir, &fno); /* Read a directory item */
+ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
+ if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
+ if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
+
+#if _USE_LFN
+ char *fn = *fno.lfname ? fno.lfname : fno.fname;
+#else
+ char *fn = fno.fname;
+#endif
+
+ if (fno.fattrib & AM_DIR) { /* It is a directory */
+ } else { /* It is a file. */
+ }
+
+ // make a string object for this entry
+ byte *data;
+ uint fn_len = strlen(fn);
+ mp_obj_t entry_o = mp_obj_str_builder_start(local_str_type, path_len + 1 + fn_len, &data);
+ memcpy(data, path, path_len);
+ data[path_len] = '/';
+ memcpy(data + path_len + 1, fn, fn_len);
+
+ // add the entry to the list
+ mp_obj_list_append(dir_list, mp_obj_str_builder_end(entry_o));
+ }
+
+ f_closedir(&dir);
+
+ return dir_list;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir);
+
+STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
+ 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_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
+ default:
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
+ }
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
+
+STATIC mp_obj_t os_remove(mp_obj_t path_o) {
+ const char *path = mp_obj_str_get_str(path_o);
+ // 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:
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
+ }
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
+
+STATIC mp_obj_t os_rmdir(mp_obj_t path_o) {
+ const char *path = mp_obj_str_get_str(path_o);
+ // TODO check that path is actually a directory before trying to unlink it
+ FRESULT res = f_unlink(path);
+ switch (res) {
+ case FR_OK:
+ return mp_const_none;
+ default:
+ nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path));
+ }
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir);
+
+STATIC mp_obj_t os_sync(void) {
+ storage_flush();
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
+
+STATIC mp_obj_t os_urandom(mp_obj_t num) {
+ machine_int_t n = mp_obj_get_int(num);
+ byte *data;
+ mp_obj_t o = mp_obj_str_builder_start(&bytes_type, n, &data);
+ for (int i = 0; i < n; i++) {
+ data[i] = rng_get();
+ }
+ return mp_obj_str_builder_end(o);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
+
+STATIC const mp_map_elem_t os_module_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_os) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&os_rmdir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&os_remove_obj }, // unlink aliases to remove
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&os_sync_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_urandom), (mp_obj_t)&os_urandom_obj },
+};
+
+STATIC const mp_map_t os_module_globals = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(os_module_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(os_module_globals_table) / sizeof(mp_map_elem_t),
+ .table = (mp_map_elem_t*)os_module_globals_table,
+};
+
+const mp_obj_module_t os_module = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_os,
+ .globals = (mp_map_t*)&os_module_globals,
+};
diff --git a/stmhal/osmodule.h b/stmhal/osmodule.h
new file mode 100644
index 0000000000..e3c13f756e
--- /dev/null
+++ b/stmhal/osmodule.h
@@ -0,0 +1 @@
+extern const mp_obj_module_t os_module;
diff --git a/stmhal/pybmodule.c b/stmhal/pybmodule.c
index 3db23dc6de..09cdf83b8a 100644
--- a/stmhal/pybmodule.c
+++ b/stmhal/pybmodule.c
@@ -17,13 +17,14 @@
#include "pin.h"
#include "exti.h"
#include "usrsw.h"
+#include "rng.h"
#include "rtc.h"
#include "usart.h"
#include "storage.h"
#include "sdcard.h"
#include "accel.h"
-#if 0
#include "servo.h"
+#if 0
#include "usb.h"
#include "i2c.h"
#include "adc.h"
@@ -128,16 +129,6 @@ STATIC mp_obj_t pyb_udelay(mp_obj_t usec) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
-STATIC mp_obj_t pyb_rng_get(void) {
-#if 0
- return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
-#else
- return mp_obj_new_int(0);
-#endif
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);
-
#if 0
STATIC void SYSCLKConfig_STOP(void) {
/* After wake-up from STOP reconfigure the system clock */
@@ -232,7 +223,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj },
#if MICROPY_HW_ENABLE_RNG
- { MP_OBJ_NEW_QSTR(MP_QSTR_rand), (mp_obj_t)&pyb_rng_get_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },
#endif
#if MICROPY_HW_ENABLE_RTC
@@ -240,13 +231,11 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_rtc_info), (mp_obj_t)&pyb_rtc_info_obj },
#endif
-#if 0
#if MICROPY_HW_ENABLE_SERVO
{ MP_OBJ_NEW_QSTR(MP_QSTR_pwm), (mp_obj_t)&pyb_pwm_set_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_servo), (mp_obj_t)&pyb_servo_set_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Servo), (mp_obj_t)&pyb_Servo_obj },
#endif
-#endif
#if MICROPY_HW_HAS_SWITCH
{ MP_OBJ_NEW_QSTR(MP_QSTR_switch), (mp_obj_t)&pyb_switch_obj },
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index 13532892a7..9961102a35 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -22,7 +22,7 @@ Q(accel_read)
Q(accel_mode)
Q(hid)
Q(time)
-Q(rand)
+Q(rng)
Q(Led)
Q(LCD)
Q(Servo)
@@ -55,3 +55,18 @@ Q(PULL_UP)
Q(PULL_DOWN)
Q(PUSH_PULL)
Q(OPEN_DRAIN)
+
+// for os module
+Q(os)
+Q(/)
+Q(listdir)
+Q(mkdir)
+Q(remove)
+Q(rmdir)
+Q(unlink)
+Q(sep)
+Q(urandom)
+
+// for time module
+Q(time)
+Q(sleep)
diff --git a/stmhal/rng.c b/stmhal/rng.c
new file mode 100644
index 0000000000..f0d14fe975
--- /dev/null
+++ b/stmhal/rng.c
@@ -0,0 +1,25 @@
+#include "stm32f4xx_hal.h"
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "rng.h"
+
+STATIC RNG_HandleTypeDef RngHandle;
+
+void rng_init(void) {
+ __RNG_CLK_ENABLE();
+ RngHandle.Instance = RNG;
+ HAL_RNG_Init(&RngHandle);
+}
+
+uint32_t rng_get(void) {
+ return HAL_RNG_GetRandomNumber(&RngHandle);
+}
+
+STATIC mp_obj_t pyb_rng_get(void) {
+ return mp_obj_new_int(HAL_RNG_GetRandomNumber(&RngHandle) >> 2);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);
diff --git a/stmhal/rng.h b/stmhal/rng.h
new file mode 100644
index 0000000000..5442d453c2
--- /dev/null
+++ b/stmhal/rng.h
@@ -0,0 +1,4 @@
+void rng_init(void);
+uint32_t rng_get(void);
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_rng_get_obj);
diff --git a/stmhal/servo.c b/stmhal/servo.c
new file mode 100644
index 0000000000..1be18b8a4e
--- /dev/null
+++ b/stmhal/servo.c
@@ -0,0 +1,142 @@
+#include <stdio.h>
+
+#include "stm32f4xx_hal.h"
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "servo.h"
+
+// this servo driver uses hardware PWM to drive servos on PA0, PA1, PA2, PA3 = X1, X2, X3, X4
+// TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively
+// they are both 32-bit counters with 16-bit prescaler
+// we use TIM2
+
+STATIC TIM_HandleTypeDef servo_TimHandle;
+
+void servo_init(void) {
+ // TIM2 clock enable
+ __TIM2_CLK_ENABLE();
+
+ // PWM clock configuration
+ servo_TimHandle.Instance = TIM2;
+ servo_TimHandle.Init.Period = 2000; // timer cycles at 50Hz
+ servo_TimHandle.Init.Prescaler = ((SystemCoreClock / 2) / 100000) - 1; // timer runs at 100kHz
+ servo_TimHandle.Init.ClockDivision = 0;
+ servo_TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
+ HAL_TIM_PWM_Init(&servo_TimHandle);
+}
+
+STATIC void servo_init_channel(int channel_in) {
+ uint32_t pin;
+ uint32_t channel;
+ switch (channel_in) {
+ case 1: pin = GPIO_PIN_0; channel = TIM_CHANNEL_1; break;
+ case 2: pin = GPIO_PIN_1; channel = TIM_CHANNEL_2; break;
+ case 3: pin = GPIO_PIN_2; channel = TIM_CHANNEL_3; break;
+ case 4: pin = GPIO_PIN_3; channel = TIM_CHANNEL_4; break;
+ default: return;
+ }
+
+ // GPIO configuration
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Pin = pin;
+ GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Alternate = GPIO_AF1_TIM2;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ // PWM mode configuration
+ TIM_OC_InitTypeDef oc_init;
+ oc_init.OCMode = TIM_OCMODE_PWM1;
+ oc_init.Pulse = 150; // units of 10us
+ oc_init.OCPolarity = TIM_OCPOLARITY_HIGH;
+ oc_init.OCFastMode = TIM_OCFAST_DISABLE;
+ HAL_TIM_PWM_ConfigChannel(&servo_TimHandle, &oc_init, channel);
+
+ // start PWM
+ HAL_TIM_PWM_Start(&servo_TimHandle, channel);
+}
+
+/******************************************************************************/
+// Micro Python bindings
+
+STATIC mp_obj_t pyb_servo_set(mp_obj_t port, mp_obj_t value) {
+ int p = mp_obj_get_int(port);
+ int v = mp_obj_get_int(value);
+ if (v < 50) { v = 50; }
+ if (v > 250) { v = 250; }
+ switch (p) {
+ case 1: TIM2->CCR1 = v; break;
+ case 2: TIM2->CCR2 = v; break;
+ case 3: TIM2->CCR3 = v; break;
+ case 4: TIM2->CCR4 = v; break;
+ }
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_2(pyb_servo_set_obj, pyb_servo_set);
+
+STATIC mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse) {
+ int pe = mp_obj_get_int(period);
+ int pu = mp_obj_get_int(pulse);
+ TIM2->ARR = pe;
+ TIM2->CCR3 = pu;
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_2(pyb_pwm_set_obj, pyb_pwm_set);
+
+typedef struct _pyb_servo_obj_t {
+ mp_obj_base_t base;
+ uint servo_id;
+} pyb_servo_obj_t;
+
+STATIC void servo_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pyb_servo_obj_t *self = self_in;
+ print(env, "<Servo %lu>", self->servo_id);
+}
+
+STATIC mp_obj_t servo_obj_angle(mp_obj_t self_in, mp_obj_t angle) {
+ pyb_servo_obj_t *self = self_in;
+#if MICROPY_ENABLE_FLOAT
+ machine_int_t v = 152 + 85.0 * mp_obj_get_float(angle) / 90.0;
+#else
+ machine_int_t v = 152 + 85 * mp_obj_get_int(angle) / 90;
+#endif
+ if (v < 65) { v = 65; }
+ if (v > 210) { v = 210; }
+ switch (self->servo_id) {
+ case 1: TIM2->CCR1 = v; break;
+ case 2: TIM2->CCR2 = v; break;
+ case 3: TIM2->CCR3 = v; break;
+ case 4: TIM2->CCR4 = v; break;
+ }
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(servo_obj_angle_obj, servo_obj_angle);
+
+STATIC const mp_method_t servo_methods[] = {
+ { "angle", &servo_obj_angle_obj },
+ { NULL, NULL },
+};
+
+STATIC const mp_obj_type_t servo_obj_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Servo,
+ .print = servo_obj_print,
+ .methods = servo_methods,
+};
+
+STATIC mp_obj_t pyb_Servo(mp_obj_t servo_id) {
+ pyb_servo_obj_t *o = m_new_obj(pyb_servo_obj_t);
+ o->base.type = &servo_obj_type;
+ o->servo_id = mp_obj_get_int(servo_id);
+ servo_init_channel(o->servo_id);
+ return o;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_Servo_obj, pyb_Servo);
diff --git a/stmhal/servo.h b/stmhal/servo.h
new file mode 100644
index 0000000000..bb3edd97a2
--- /dev/null
+++ b/stmhal/servo.h
@@ -0,0 +1,5 @@
+void servo_init(void);
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_servo_set_obj);
+MP_DECLARE_CONST_FUN_OBJ(pyb_pwm_set_obj);
+MP_DECLARE_CONST_FUN_OBJ(pyb_Servo_obj);
diff --git a/stmhal/stm32f4xx_hal_msp.c b/stmhal/stm32f4xx_hal_msp.c
index f5611e1082..816b1427e9 100644
--- a/stmhal/stm32f4xx_hal_msp.c
+++ b/stmhal/stm32f4xx_hal_msp.c
@@ -47,7 +47,7 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
-#include "usbd_cdc.h"
+#include "usbd_cdc_msc.h"
#include "usbd_cdc_interface.h"
/** @addtogroup STM32F4xx_HAL_Driver
diff --git a/stmhal/timemodule.c b/stmhal/timemodule.c
new file mode 100644
index 0000000000..b2dac6a54c
--- /dev/null
+++ b/stmhal/timemodule.c
@@ -0,0 +1,44 @@
+#include <stm32f4xx_hal.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "map.h"
+#include "timemodule.h"
+
+STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
+#if MICROPY_ENABLE_FLOAT
+ if (MP_OBJ_IS_INT(seconds_o)) {
+#endif
+ HAL_Delay(1000 * mp_obj_get_int(seconds_o));
+#if MICROPY_ENABLE_FLOAT
+ } else {
+ HAL_Delay((uint32_t)(1000 * mp_obj_get_float(seconds_o)));
+ }
+#endif
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
+
+STATIC const mp_map_elem_t time_module_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_time) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
+};
+
+STATIC const mp_map_t time_module_globals = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(time_module_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(time_module_globals_table) / sizeof(mp_map_elem_t),
+ .table = (mp_map_elem_t*)time_module_globals_table,
+};
+
+const mp_obj_module_t time_module = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_time,
+ .globals = (mp_map_t*)&time_module_globals,
+};
diff --git a/stmhal/timemodule.h b/stmhal/timemodule.h
new file mode 100644
index 0000000000..70e35b1fde
--- /dev/null
+++ b/stmhal/timemodule.h
@@ -0,0 +1 @@
+extern const mp_obj_module_t time_module;
diff --git a/stmhal/usb.c b/stmhal/usb.c
index c14a5ad688..aa006b8b8f 100644
--- a/stmhal/usb.c
+++ b/stmhal/usb.c
@@ -2,9 +2,8 @@
#include "usbd_core.h"
#include "usbd_desc.h"
-#include "usbd_cdc.h"
+#include "usbd_cdc_msc.h"
#include "usbd_cdc_interface.h"
-#include "usbd_msc.h"
#include "usbd_msc_storage.h"
#include "misc.h"
@@ -18,7 +17,6 @@ USBD_HandleTypeDef hUSBDDevice;
#endif
static int dev_is_enabled = 0;
-uint32_t APP_dev_is_connected = 0; /* used by usbd_cdc_vcp */
mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind) {
@@ -26,21 +24,10 @@ void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t
if (!dev_is_enabled) {
// only init USB once in the device's power-lifetime
switch (device_kind) {
- case USBD_DEVICE_CDC:
- // XXX USBD_CDC_Init (called by one of these functions below) uses malloc,
- // so the memory is invalid after a soft reset (which resets the GC).
+ case USBD_DEVICE_CDC_MSC:
USBD_Init(&hUSBDDevice, &VCP_Desc, 0);
- USBD_RegisterClass(&hUSBDDevice, &USBD_CDC);
+ USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC);
USBD_CDC_RegisterInterface(&hUSBDDevice, (USBD_CDC_ItfTypeDef*)&USBD_CDC_fops);
- USBD_Start(&hUSBDDevice);
- //USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
- break;
-
- case USBD_DEVICE_MSC:
- // XXX USBD_CDC_Init (called by one of these functions below) uses malloc,
- // so the memory is invalid after a soft reset (which resets the GC).
- USBD_Init(&hUSBDDevice, &MSC_Desc, 0);
- USBD_RegisterClass(&hUSBDDevice, &USBD_MSC);
if (medium_kind == USBD_STORAGE_MEDIUM_FLASH) {
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops);
} else {
@@ -67,7 +54,7 @@ bool usb_vcp_is_enabled(void) {
}
bool usb_vcp_is_connected(void) {
- return APP_dev_is_connected;
+ return USBD_CDC_IsConnected();
}
void usb_vcp_set_interrupt_char(int c) {
diff --git a/stmhal/usb.h b/stmhal/usb.h
index bb6283c89a..e30b1364f9 100644
--- a/stmhal/usb.h
+++ b/stmhal/usb.h
@@ -5,8 +5,7 @@
#define VCP_CHAR_CTRL_D (4)
typedef enum {
- USBD_DEVICE_CDC,
- USBD_DEVICE_MSC,
+ USBD_DEVICE_CDC_MSC,
USBD_DEVICE_HID,
} usbd_device_kind_t;
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index e0f387eb7e..5116ce860e 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -28,11 +28,22 @@
/* Includes ------------------------------------------------------------------*/
#include <stdbool.h>
#include "stm32f4xx_hal.h"
-#include "usbd_cdc.h"
+#include "usbd_cdc_msc.h"
#include "usbd_cdc_interface.h"
#include "pendsv.h"
#include "usb.h"
+// CDC control commands
+#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
+#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
+#define CDC_SET_COMM_FEATURE 0x02
+#define CDC_GET_COMM_FEATURE 0x03
+#define CDC_CLEAR_COMM_FEATURE 0x04
+#define CDC_SET_LINE_CODING 0x20
+#define CDC_GET_LINE_CODING 0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+#define CDC_SEND_BREAK 0x23
+
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define APP_RX_DATA_SIZE 1024 // I think this must be at least CDC_DATA_FS_OUT_PACKET_SIZE (was 2048)
@@ -41,6 +52,8 @@
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
+static uint8_t dev_is_connected = 0; // indicates if we are connected
+
static uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; // received data from USB OUT endpoint is stored in this buffer
static uint16_t UserRxBufCur = 0; // points to next available character in UserRxBuffer
static uint16_t UserRxBufLen = 0; // counts number of valid characters in UserRxBuffer
@@ -163,76 +176,73 @@ static int8_t CDC_Itf_DeInit(void)
* @param Len: Number of data to be sent (in bytes)
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
*/
-static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)
-{
- switch (cmd)
- {
- case CDC_SEND_ENCAPSULATED_COMMAND:
- /* Add your code here */
- break;
-
- case CDC_GET_ENCAPSULATED_RESPONSE:
- /* Add your code here */
- break;
-
- case CDC_SET_COMM_FEATURE:
- /* Add your code here */
- break;
-
- case CDC_GET_COMM_FEATURE:
- /* Add your code here */
- break;
-
- case CDC_CLEAR_COMM_FEATURE:
- /* Add your code here */
- break;
-
- case CDC_SET_LINE_CODING:
- #if 0
- LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\
- (pbuf[2] << 16) | (pbuf[3] << 24));
- LineCoding.format = pbuf[4];
- LineCoding.paritytype = pbuf[5];
- LineCoding.datatype = pbuf[6];
-
- /* Set the new configuration */
- #endif
- break;
-
- case CDC_GET_LINE_CODING:
- #if 0
- pbuf[0] = (uint8_t)(LineCoding.bitrate);
- pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8);
- pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16);
- pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24);
- pbuf[4] = LineCoding.format;
- pbuf[5] = LineCoding.paritytype;
- pbuf[6] = LineCoding.datatype;
- #endif
-
- /* Add your code here */
- pbuf[0] = (uint8_t)(115200);
- pbuf[1] = (uint8_t)(115200 >> 8);
- pbuf[2] = (uint8_t)(115200 >> 16);
- pbuf[3] = (uint8_t)(115200 >> 24);
- pbuf[4] = 0; // stop bits (1)
- pbuf[5] = 0; // parity (none)
- pbuf[6] = 8; // number of bits (8)
- break;
-
- case CDC_SET_CONTROL_LINE_STATE:
- /* Add your code here */
- break;
-
- case CDC_SEND_BREAK:
- /* Add your code here */
- break;
-
- default:
- break;
- }
-
- return (USBD_OK);
+static int8_t CDC_Itf_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length) {
+ switch (cmd) {
+ case CDC_SEND_ENCAPSULATED_COMMAND:
+ /* Add your code here */
+ break;
+
+ case CDC_GET_ENCAPSULATED_RESPONSE:
+ /* Add your code here */
+ break;
+
+ case CDC_SET_COMM_FEATURE:
+ /* Add your code here */
+ break;
+
+ case CDC_GET_COMM_FEATURE:
+ /* Add your code here */
+ break;
+
+ case CDC_CLEAR_COMM_FEATURE:
+ /* Add your code here */
+ break;
+
+ case CDC_SET_LINE_CODING:
+ #if 0
+ LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\
+ (pbuf[2] << 16) | (pbuf[3] << 24));
+ LineCoding.format = pbuf[4];
+ LineCoding.paritytype = pbuf[5];
+ LineCoding.datatype = pbuf[6];
+ /* Set the new configuration */
+ #endif
+ break;
+
+ case CDC_GET_LINE_CODING:
+ #if 0
+ pbuf[0] = (uint8_t)(LineCoding.bitrate);
+ pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8);
+ pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16);
+ pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24);
+ pbuf[4] = LineCoding.format;
+ pbuf[5] = LineCoding.paritytype;
+ pbuf[6] = LineCoding.datatype;
+ #endif
+
+ /* Add your code here */
+ pbuf[0] = (uint8_t)(115200);
+ pbuf[1] = (uint8_t)(115200 >> 8);
+ pbuf[2] = (uint8_t)(115200 >> 16);
+ pbuf[3] = (uint8_t)(115200 >> 24);
+ pbuf[4] = 0; // stop bits (1)
+ pbuf[5] = 0; // parity (none)
+ pbuf[6] = 8; // number of bits (8)
+ break;
+
+ case CDC_SET_CONTROL_LINE_STATE:
+ dev_is_connected = length & 1; // wValue is passed in Len (bit of a hack)
+ break;
+
+ case CDC_SEND_BREAK:
+ /* Add your code here */
+ break;
+
+ default:
+ break;
+ }
+
+ return USBD_OK;
}
/**
@@ -328,6 +338,10 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
return (USBD_OK);
}
+int USBD_CDC_IsConnected(void) {
+ return dev_is_connected;
+}
+
void USBD_CDC_SetInterrupt(int chr, void *data) {
user_interrupt_char = chr;
user_interrupt_data = data;
diff --git a/stmhal/usbd_cdc_interface.h b/stmhal/usbd_cdc_interface.h
index b50cbf4c29..bcb6333a6a 100644
--- a/stmhal/usbd_cdc_interface.h
+++ b/stmhal/usbd_cdc_interface.h
@@ -49,6 +49,7 @@
extern const USBD_CDC_ItfTypeDef USBD_CDC_fops;
+int USBD_CDC_IsConnected(void);
void USBD_CDC_SetInterrupt(int chr, void *data);
void USBD_CDC_Tx(const char *str, uint32_t len);
int USBD_CDC_RxNum(void);
diff --git a/stmhal/usbd_conf.c b/stmhal/usbd_conf.c
index 4a4414afe2..9df3b673c3 100644
--- a/stmhal/usbd_conf.c
+++ b/stmhal/usbd_conf.c
@@ -342,10 +342,12 @@ USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
pdev->pData = &hpcd;
/*Initialize LL Driver */
HAL_PCD_Init(&hpcd);
-
+
HAL_PCD_SetRxFiFo(&hpcd, 0x80);
- HAL_PCD_SetTxFiFo(&hpcd, 0, 0x40);
- HAL_PCD_SetTxFiFo(&hpcd, 1, 0x80);
+ HAL_PCD_SetTxFiFo(&hpcd, 0, 0x20);
+ HAL_PCD_SetTxFiFo(&hpcd, 1, 0x40);
+ HAL_PCD_SetTxFiFo(&hpcd, 2, 0x20);
+ HAL_PCD_SetTxFiFo(&hpcd, 3, 0x40);
#endif
diff --git a/stmhal/usbd_conf.h b/stmhal/usbd_conf.h
index cc3ad73f98..d37cd4a8ba 100644
--- a/stmhal/usbd_conf.h
+++ b/stmhal/usbd_conf.h
@@ -36,7 +36,6 @@
#include <string.h>
#include "mpconfig.h"
-#include "gc.h" // for gc_alloc and gc_free
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
@@ -47,17 +46,18 @@
#define USBD_SUPPORT_USER_STRING 0
#define USBD_SELF_POWERED 0
#define USBD_DEBUG_LEVEL 0
-
-// for MSC device
-#define MSC_MEDIA_PACKET 8192
/* Exported macro ------------------------------------------------------------*/
/* Memory management macros */
+/*
+these should not be used because the GC is reset on a soft reset but the usb is not
+#include "gc.h"
#define USBD_malloc gc_alloc
#define USBD_free gc_free
#define USBD_memset memset
#define USBD_memcpy memcpy
-
+*/
+
/* DEBUG macros */
#if (USBD_DEBUG_LEVEL > 0)
#define USBD_UsrLog(...) printf(__VA_ARGS__);\
diff --git a/stmhal/usbd_desc_vcp.c b/stmhal/usbd_desc_cdc_msc.c
index edcb4b3431..edcb4b3431 100644
--- a/stmhal/usbd_desc_vcp.c
+++ b/stmhal/usbd_desc_cdc_msc.c
diff --git a/stmhal/usbd_desc_msc.c b/stmhal/usbd_desc_msc.c
deleted file mode 100644
index 7d0911e82c..0000000000
--- a/stmhal/usbd_desc_msc.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/**
- ******************************************************************************
- * @file USB_Device/MSC_Standalone/Src/usbd_desc.c
- * @author MCD Application Team
- * @version V1.0.1
- * @date 26-February-2014
- * @brief This file provides the USBD descriptors and string formating method.
- ******************************************************************************
- * @attention
- *
- * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
- *
- * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.st.com/software_license_agreement_liberty_v2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************
- */
-
-/* Includes ------------------------------------------------------------------*/
-#include "usbd_core.h"
-#include "usbd_desc.h"
-#include "usbd_conf.h"
-
-/* Private typedef -----------------------------------------------------------*/
-/* Private define ------------------------------------------------------------*/
-#define USBD_VID 0x0483
-#define USBD_PID 0x5720
-#define USBD_LANGID_STRING 0x409
-#define USBD_MANUFACTURER_STRING "STMicroelectronics"
-#define USBD_PRODUCT_HS_STRING "Mass Storage in HS Mode"
-#define USBD_SERIALNUMBER_HS_STRING "00000000001A"
-#define USBD_PRODUCT_FS_STRING "Mass Storage in FS Mode"
-#define USBD_SERIALNUMBER_FS_STRING "00000000001B"
-#define USBD_CONFIGURATION_HS_STRING "MSC Config"
-#define USBD_INTERFACE_HS_STRING "MSC Interface"
-#define USBD_CONFIGURATION_FS_STRING "MSC Config"
-#define USBD_INTERFACE_FS_STRING "MSC Interface"
-
-/* Private macro -------------------------------------------------------------*/
-/* Private function prototypes -----------------------------------------------*/
-uint8_t *USBD_MSC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
-uint8_t *USBD_MSC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
-uint8_t *USBD_MSC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
-uint8_t *USBD_MSC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
-uint8_t *USBD_MSC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
-uint8_t *USBD_MSC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
-uint8_t *USBD_MSC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
-#ifdef USB_SUPPORT_USER_STRING_DESC
-uint8_t *USBD_MSC_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
-#endif /* USB_SUPPORT_USER_STRING_DESC */
-
-/* Private variables ---------------------------------------------------------*/
-USBD_DescriptorsTypeDef MSC_Desc = {
- USBD_MSC_DeviceDescriptor,
- USBD_MSC_LangIDStrDescriptor,
- USBD_MSC_ManufacturerStrDescriptor,
- USBD_MSC_ProductStrDescriptor,
- USBD_MSC_SerialStrDescriptor,
- USBD_MSC_ConfigStrDescriptor,
- USBD_MSC_InterfaceStrDescriptor,
-};
-
-/* USB Standard Device Descriptor */
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma data_alignment=4
-#endif
-__ALIGN_BEGIN static uint8_t USBD_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
- 0x12, /* bLength */
- USB_DESC_TYPE_DEVICE, /* bDescriptorType */
- 0x00, /* bcdUSB */
- 0x02,
- 0x00, /* bDeviceClass */
- 0x00, /* bDeviceSubClass */
- 0x00, /* bDeviceProtocol */
- USB_MAX_EP0_SIZE, /* bMaxPacketSize */
- LOBYTE(USBD_VID), /* idVendor */
- HIBYTE(USBD_VID), /* idVendor */
- LOBYTE(USBD_PID), /* idVendor */
- HIBYTE(USBD_PID), /* idVendor */
- 0x00, /* bcdDevice rel. 2.00 */
- 0x02,
- USBD_IDX_MFC_STR, /* Index of manufacturer string */
- USBD_IDX_PRODUCT_STR, /* Index of product string */
- USBD_IDX_SERIAL_STR, /* Index of serial number string */
- USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
-}; /* USB_DeviceDescriptor */
-
-/* USB Standard Device Descriptor */
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma data_alignment=4
-#endif
-__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
- USB_LEN_LANGID_STR_DESC,
- USB_DESC_TYPE_STRING,
- LOBYTE(USBD_LANGID_STRING),
- HIBYTE(USBD_LANGID_STRING),
-};
-
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma data_alignment=4
-#endif
-__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
-
-/* Private functions ---------------------------------------------------------*/
-
-/**
- * @brief Returns the device descriptor.
- * @param speed: Current device speed
- * @param length: Pointer to data length variable
- * @retval Pointer to descriptor buffer
- */
-uint8_t *USBD_MSC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
-{
- *length = sizeof(USBD_DeviceDesc);
- return USBD_DeviceDesc;
-}
-
-/**
- * @brief Returns the LangID string descriptor.
- * @param speed: Current device speed
- * @param length: Pointer to data length variable
- * @retval Pointer to descriptor buffer
- */
-uint8_t *USBD_MSC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
-{
- *length = sizeof(USBD_LangIDDesc);
- return USBD_LangIDDesc;
-}
-
-/**
- * @brief Returns the product string descriptor.
- * @param speed: Current device speed
- * @param length: Pointer to data length variable
- * @retval Pointer to descriptor buffer
- */
-uint8_t *USBD_MSC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
-{
- if(speed == 0)
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_PRODUCT_HS_STRING, USBD_StrDesc, length);
- }
- else
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);
- }
- return USBD_StrDesc;
-}
-
-/**
- * @brief Returns the manufacturer string descriptor.
- * @param speed: Current device speed
- * @param length: Pointer to data length variable
- * @retval Pointer to descriptor buffer
- */
-uint8_t *USBD_MSC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
-{
- USBD_GetString((uint8_t *)(uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
- return USBD_StrDesc;
-}
-
-/**
- * @brief Returns the serial number string descriptor.
- * @param speed: Current device speed
- * @param length: Pointer to data length variable
- * @retval Pointer to descriptor buffer
- */
-uint8_t *USBD_MSC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
-{
- if(speed == USBD_SPEED_HIGH)
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length);
- }
- else
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length);
- }
- return USBD_StrDesc;
-}
-
-/**
- * @brief Returns the configuration string descriptor.
- * @param speed: Current device speed
- * @param length: Pointer to data length variable
- * @retval Pointer to descriptor buffer
- */
-uint8_t *USBD_MSC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
-{
- if(speed == USBD_SPEED_HIGH)
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length);
- }
- else
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length);
- }
- return USBD_StrDesc;
-}
-
-/**
- * @brief Returns the interface string descriptor.
- * @param speed: Current device speed
- * @param length: Pointer to data length variable
- * @retval Pointer to descriptor buffer
- */
-uint8_t *USBD_MSC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
-{
- if(speed == 0)
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_INTERFACE_HS_STRING, USBD_StrDesc, length);
- }
- else
- {
- USBD_GetString((uint8_t *)(uint8_t *)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
- }
- return USBD_StrDesc;
-}
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbd_msc_storage.c b/stmhal/usbd_msc_storage.c
index e5c75e27c7..ce6d3a5608 100644
--- a/stmhal/usbd_msc_storage.c
+++ b/stmhal/usbd_msc_storage.c
@@ -27,7 +27,7 @@
******************************************************************************
*/
-#include "usbd_msc.h"
+#include "usbd_cdc_msc.h"
#include "usbd_msc_storage.h"
#include "misc.h"
diff --git a/stmhal/usbdev/class/cdc_msc/inc/usbd_cdc_msc.h b/stmhal/usbdev/class/cdc_msc/inc/usbd_cdc_msc.h
new file mode 100644
index 0000000000..5299f31e96
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/inc/usbd_cdc_msc.h
@@ -0,0 +1,132 @@
+#ifndef _USB_CDC_MSC_CORE_H_
+#define _USB_CDC_MSC_CORE_H_
+
+#include "usbd_msc_bot.h"
+#include "usbd_msc_scsi.h"
+#include "usbd_ioreq.h"
+
+// CDC and MSC packet sizes
+#define CDC_DATA_FS_MAX_PACKET_SIZE (64) // endpoint IN & OUT packet size
+#define MSC_MEDIA_PACKET (2048) // was 8192; how low can it go whilst still working?
+
+#if 0
+// CDC
+#define USB_CDC_MSC_CONFIG_DESC_SIZ (75)
+#define NUM_INTERFACES (2)
+#define USE_CDC (1)
+#define USE_MSC (0)
+#define CDC_IN_EP 0x81 /* EP1 for data IN */
+#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
+#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
+#define MSC_IN_EP (0x83)
+#define MSC_OUT_EP (0x03)
+#elif 0
+// MSC
+#define USB_CDC_MSC_CONFIG_DESC_SIZ (32)
+#define NUM_INTERFACES (1)
+#define USE_CDC (0)
+#define USE_MSC (1)
+#define CDC_IN_EP 0x81 /* EP1 for data IN */
+#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
+#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
+#define MSC_IFACE_NUM (0)
+#define MSC_IN_EP (0x81)
+#define MSC_OUT_EP (0x01)
+#elif 1
+// CDC + MSC
+#define USB_CDC_MSC_CONFIG_DESC_SIZ (98)
+#define NUM_INTERFACES (3)
+#define USE_CDC (1)
+#define USE_MSC (1)
+#define CDC_IFACE_NUM (0)
+#define CDC_IN_EP 0x81 /* EP1 for data IN */
+#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
+#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
+#define MSC_IFACE_NUM (2)
+#define MSC_IN_EP (0x83)
+#define MSC_OUT_EP (0x03)
+#else
+// MSC + CDC
+#define USB_CDC_MSC_CONFIG_DESC_SIZ (98)
+#define NUM_INTERFACES (3)
+#define USE_CDC (1)
+#define USE_MSC (1)
+#define CDC_IFACE_NUM (1)
+#define CDC_IN_EP 0x83 /* EP1 for data IN */
+#define CDC_OUT_EP 0x03 /* EP1 for data OUT */
+#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
+#define MSC_IFACE_NUM (0)
+#define MSC_IN_EP (0x81)
+#define MSC_OUT_EP (0x01)
+#endif
+
+typedef struct {
+ uint32_t bitrate;
+ uint8_t format;
+ uint8_t paritytype;
+ uint8_t datatype;
+} USBD_CDC_LineCodingTypeDef;
+
+typedef struct _USBD_CDC_Itf {
+ int8_t (* Init) (void);
+ int8_t (* DeInit) (void);
+ int8_t (* Control) (uint8_t, uint8_t * , uint16_t);
+ int8_t (* Receive) (uint8_t *, uint32_t *);
+} USBD_CDC_ItfTypeDef;
+
+typedef struct {
+ uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */
+ uint8_t CmdOpCode;
+ uint8_t CmdLength;
+ uint8_t *RxBuffer;
+ uint8_t *TxBuffer;
+ uint32_t RxLength;
+ uint32_t TxLength;
+
+ __IO uint32_t TxState;
+ __IO uint32_t RxState;
+} USBD_CDC_HandleTypeDef;
+
+typedef struct _USBD_STORAGE {
+ int8_t (* Init) (uint8_t lun);
+ int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size);
+ int8_t (* IsReady) (uint8_t lun);
+ int8_t (* IsWriteProtected) (uint8_t lun);
+ int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
+ int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
+ int8_t (* GetMaxLun)(void);
+ int8_t *pInquiry;
+} USBD_StorageTypeDef;
+
+typedef struct {
+ uint32_t max_lun;
+ uint32_t interface;
+ uint8_t bot_state;
+ uint8_t bot_status;
+ uint16_t bot_data_length;
+ uint8_t bot_data[MSC_MEDIA_PACKET];
+ USBD_MSC_BOT_CBWTypeDef cbw;
+ USBD_MSC_BOT_CSWTypeDef csw;
+
+ USBD_SCSI_SenseTypeDef scsi_sense [SENSE_LIST_DEEPTH];
+ uint8_t scsi_sense_head;
+ uint8_t scsi_sense_tail;
+
+ uint16_t scsi_blk_size;
+ uint32_t scsi_blk_nbr;
+
+ uint32_t scsi_blk_addr;
+ uint32_t scsi_blk_len;
+} USBD_MSC_BOT_HandleTypeDef;
+
+extern USBD_ClassTypeDef USBD_CDC_MSC;
+
+uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops);
+uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length);
+uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff);
+uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev);
+uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev);
+
+uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops);
+
+#endif // _USB_CDC_MSC_CORE_H_
diff --git a/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_bot.h b/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_bot.h
new file mode 100644
index 0000000000..41f8ab5a53
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_bot.h
@@ -0,0 +1,151 @@
+/**
+ ******************************************************************************
+ * @file usbd_msc_bot.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header for the usbd_msc_bot.c file
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+
+#include "usbd_core.h"
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_MSC_BOT_H
+#define __USBD_MSC_BOT_H
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup MSC_BOT
+ * @brief This file is the Header file for usbd_bot.c
+ * @{
+ */
+
+
+/** @defgroup USBD_CORE_Exported_Defines
+ * @{
+ */
+#define USBD_BOT_IDLE 0 /* Idle state */
+#define USBD_BOT_DATA_OUT 1 /* Data Out state */
+#define USBD_BOT_DATA_IN 2 /* Data In state */
+#define USBD_BOT_LAST_DATA_IN 3 /* Last Data In Last */
+#define USBD_BOT_SEND_DATA 4 /* Send Immediate data */
+#define USBD_BOT_NO_DATA 5 /* No data Stage */
+
+#define USBD_BOT_CBW_SIGNATURE 0x43425355
+#define USBD_BOT_CSW_SIGNATURE 0x53425355
+#define USBD_BOT_CBW_LENGTH 31
+#define USBD_BOT_CSW_LENGTH 13
+#define USBD_BOT_MAX_DATA 256
+
+/* CSW Status Definitions */
+#define USBD_CSW_CMD_PASSED 0x00
+#define USBD_CSW_CMD_FAILED 0x01
+#define USBD_CSW_PHASE_ERROR 0x02
+
+/* BOT Status */
+#define USBD_BOT_STATUS_NORMAL 0
+#define USBD_BOT_STATUS_RECOVERY 1
+#define USBD_BOT_STATUS_ERROR 2
+
+
+#define USBD_DIR_IN 0
+#define USBD_DIR_OUT 1
+#define USBD_BOTH_DIR 2
+
+/**
+ * @}
+ */
+
+/** @defgroup MSC_CORE_Private_TypesDefinitions
+ * @{
+ */
+
+typedef struct
+{
+ uint32_t dSignature;
+ uint32_t dTag;
+ uint32_t dDataLength;
+ uint8_t bmFlags;
+ uint8_t bLUN;
+ uint8_t bCBLength;
+ uint8_t CB[16];
+ uint8_t ReservedForAlign;
+}
+USBD_MSC_BOT_CBWTypeDef;
+
+
+typedef struct
+{
+ uint32_t dSignature;
+ uint32_t dTag;
+ uint32_t dDataResidue;
+ uint8_t bStatus;
+ uint8_t ReservedForAlign[3];
+}
+USBD_MSC_BOT_CSWTypeDef;
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Exported_Types
+ * @{
+ */
+
+/**
+ * @}
+ */
+/** @defgroup USBD_CORE_Exported_FunctionsPrototypes
+ * @{
+ */
+void MSC_BOT_Init (USBD_HandleTypeDef *pdev);
+void MSC_BOT_Reset (USBD_HandleTypeDef *pdev);
+void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev);
+void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+
+void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+
+void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev,
+ uint8_t CSW_Status);
+
+void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+/**
+ * @}
+ */
+
+#endif /* __USBD_MSC_BOT_H */
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_data.h b/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_data.h
new file mode 100644
index 0000000000..f468267f43
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_data.h
@@ -0,0 +1,104 @@
+/**
+ ******************************************************************************
+ * @file usbd_msc_data.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header for the usbd_msc_data.c file
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+
+#ifndef _USBD_MSC_DATA_H_
+#define _USBD_MSC_DATA_H_
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USB_INFO
+ * @brief general defines for the usb device library file
+ * @{
+ */
+
+/** @defgroup USB_INFO_Exported_Defines
+ * @{
+ */
+#define MODE_SENSE6_LEN 8
+#define MODE_SENSE10_LEN 8
+#define LENGTH_INQUIRY_PAGE00 7
+#define LENGTH_FORMAT_CAPACITIES 20
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_INFO_Exported_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_INFO_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_INFO_Exported_Variables
+ * @{
+ */
+extern const uint8_t MSC_Page00_Inquiry_Data[];
+extern const uint8_t MSC_Mode_Sense6_data[];
+extern const uint8_t MSC_Mode_Sense10_data[] ;
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_INFO_Exported_FunctionsPrototype
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+#endif /* _USBD_MSC_DATA_H_ */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_scsi.h b/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_scsi.h
new file mode 100644
index 0000000000..dea247bca8
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/inc/usbd_msc_scsi.h
@@ -0,0 +1,193 @@
+/**
+ ******************************************************************************
+ * @file usbd_msc_scsi.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header for the usbd_msc_scsi.c file
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_MSC_SCSI_H
+#define __USBD_MSC_SCSI_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_def.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_SCSI
+ * @brief header file for the storage disk file
+ * @{
+ */
+
+/** @defgroup USBD_SCSI_Exported_Defines
+ * @{
+ */
+
+#define SENSE_LIST_DEEPTH 4
+
+/* SCSI Commands */
+#define SCSI_FORMAT_UNIT 0x04
+#define SCSI_INQUIRY 0x12
+#define SCSI_MODE_SELECT6 0x15
+#define SCSI_MODE_SELECT10 0x55
+#define SCSI_MODE_SENSE6 0x1A
+#define SCSI_MODE_SENSE10 0x5A
+#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E
+#define SCSI_READ6 0x08
+#define SCSI_READ10 0x28
+#define SCSI_READ12 0xA8
+#define SCSI_READ16 0x88
+
+#define SCSI_READ_CAPACITY10 0x25
+#define SCSI_READ_CAPACITY16 0x9E
+
+#define SCSI_REQUEST_SENSE 0x03
+#define SCSI_START_STOP_UNIT 0x1B
+#define SCSI_TEST_UNIT_READY 0x00
+#define SCSI_WRITE6 0x0A
+#define SCSI_WRITE10 0x2A
+#define SCSI_WRITE12 0xAA
+#define SCSI_WRITE16 0x8A
+
+#define SCSI_VERIFY10 0x2F
+#define SCSI_VERIFY12 0xAF
+#define SCSI_VERIFY16 0x8F
+
+#define SCSI_SEND_DIAGNOSTIC 0x1D
+#define SCSI_READ_FORMAT_CAPACITIES 0x23
+
+#define NO_SENSE 0
+#define RECOVERED_ERROR 1
+#define NOT_READY 2
+#define MEDIUM_ERROR 3
+#define HARDWARE_ERROR 4
+#define ILLEGAL_REQUEST 5
+#define UNIT_ATTENTION 6
+#define DATA_PROTECT 7
+#define BLANK_CHECK 8
+#define VENDOR_SPECIFIC 9
+#define COPY_ABORTED 10
+#define ABORTED_COMMAND 11
+#define VOLUME_OVERFLOW 13
+#define MISCOMPARE 14
+
+
+#define INVALID_CDB 0x20
+#define INVALID_FIELED_IN_COMMAND 0x24
+#define PARAMETER_LIST_LENGTH_ERROR 0x1A
+#define INVALID_FIELD_IN_PARAMETER_LIST 0x26
+#define ADDRESS_OUT_OF_RANGE 0x21
+#define MEDIUM_NOT_PRESENT 0x3A
+#define MEDIUM_HAVE_CHANGED 0x28
+#define WRITE_PROTECTED 0x27
+#define UNRECOVERED_READ_ERROR 0x11
+#define WRITE_FAULT 0x03
+
+#define READ_FORMAT_CAPACITY_DATA_LEN 0x0C
+#define READ_CAPACITY10_DATA_LEN 0x08
+#define MODE_SENSE10_DATA_LEN 0x08
+#define MODE_SENSE6_DATA_LEN 0x04
+#define REQUEST_SENSE_DATA_LEN 0x12
+#define STANDARD_INQUIRY_DATA_LEN 0x24
+#define BLKVFY 0x04
+
+extern uint8_t Page00_Inquiry_Data[];
+extern uint8_t Standard_Inquiry_Data[];
+extern uint8_t Standard_Inquiry_Data2[];
+extern uint8_t Mode_Sense6_data[];
+extern uint8_t Mode_Sense10_data[];
+extern uint8_t Scsi_Sense_Data[];
+extern uint8_t ReadCapacity10_Data[];
+extern uint8_t ReadFormatCapacity_Data [];
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_SCSI_Exported_TypesDefinitions
+ * @{
+ */
+
+typedef struct _SENSE_ITEM {
+ char Skey;
+ union {
+ struct _ASCs {
+ char ASC;
+ char ASCQ;
+ }b;
+ unsigned int ASC;
+ char *pData;
+ } w;
+} USBD_SCSI_SenseTypeDef;
+/**
+ * @}
+ */
+
+/** @defgroup USBD_SCSI_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_SCSI_Exported_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+/** @defgroup USBD_SCSI_Exported_FunctionsPrototype
+ * @{
+ */
+int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
+ uint8_t lun,
+ uint8_t *cmd);
+
+void SCSI_SenseCode(USBD_HandleTypeDef *pdev,
+ uint8_t lun,
+ uint8_t sKey,
+ uint8_t ASC);
+
+/**
+ * @}
+ */
+
+#endif /* __USBD_MSC_SCSI_H */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbdev/class/cdc_msc/src/usbd_cdc_msc.c b/stmhal/usbdev/class/cdc_msc/src/usbd_cdc_msc.c
new file mode 100644
index 0000000000..07e801e9bd
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/src/usbd_cdc_msc.c
@@ -0,0 +1,578 @@
+#include "usbd_ioreq.h"
+#include "usbd_cdc_msc.h"
+
+#define USB_DESC_TYPE_ASSOCIATION (0x0b)
+
+#define CDC_CMD_PACKET_SIZE 8 // Control Endpoint Packet size
+#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
+#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE
+
+#define BOT_GET_MAX_LUN 0xFE
+#define BOT_RESET 0xFF
+#define USB_MSC_CONFIG_DESC_SIZ 32
+
+#define MSC_MAX_FS_PACKET 0x40
+
+static USBD_CDC_ItfTypeDef *CDC_fops;
+static USBD_StorageTypeDef *MSC_fops;
+
+static USBD_CDC_HandleTypeDef CDC_ClassData;
+static USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData;
+
+// I don't think we can make these descriptors constant because they are
+// modified (perhaps unnecessarily) by the USB driver.
+
+// USB Standard Device Descriptor
+__ALIGN_BEGIN static uint8_t USBD_CDC_MSC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = {
+ USB_LEN_DEV_QUALIFIER_DESC,
+ USB_DESC_TYPE_DEVICE_QUALIFIER,
+ 0x00,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x40, // same for CDC and MSC (latter being MSC_MAX_FS_PACKET)
+ 0x01,
+ 0x00,
+};
+
+// USB CDC MSC device Configuration Descriptor
+__ALIGN_BEGIN static uint8_t USBD_CDC_MSC_CfgFSDesc[USB_CDC_MSC_CONFIG_DESC_SIZ] __ALIGN_END = {
+ //--------------------------------------------------------------------------
+ // Configuration Descriptor
+ 0x09, // bLength: Configuration Descriptor size
+ USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration
+ LOBYTE(USB_CDC_MSC_CONFIG_DESC_SIZ), // wTotalLength: no of returned bytes
+ HIBYTE(USB_CDC_MSC_CONFIG_DESC_SIZ),
+ NUM_INTERFACES, // bNumInterfaces: 3 interfaces
+ 0x01, // bConfigurationValue: Configuration value
+ 0x00, // iConfiguration: Index of string descriptor describing the configuration
+ 0x80, // bmAttributes: bus powered; 0xc0 for self powered
+ 0xfa, // bMaxPower: in units of 2mA
+
+#if USE_CDC
+ //==========================================================================
+ // Interface Association for CDC VCP
+ 0x08, // bLength: 8 bytes
+ USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD
+ CDC_IFACE_NUM, // bFirstInterface: first interface for this association
+ 0x02, // bInterfaceCount: nummber of interfaces for this association
+ 0x00, // bFunctionClass: ?
+ 0x00, // bFunctionSubClass: ?
+ 0x00, // bFunctionProtocol: ?
+ 0x00, // iFunction: index of string for this function
+
+ //--------------------------------------------------------------------------
+ // Interface Descriptor
+ 0x09, // bLength: Interface Descriptor size
+ USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface
+ CDC_IFACE_NUM, // bInterfaceNumber: Number of Interface
+ 0x00, // bAlternateSetting: Alternate setting
+ 0x01, // bNumEndpoints: One endpoints used
+ 0x02, // bInterfaceClass: Communication Interface Class
+ 0x02, // bInterfaceSubClass: Abstract Control Model
+ 0x01, // bInterfaceProtocol: Common AT commands
+ 0x00, // iInterface:
+
+ // Header Functional Descriptor
+ 0x05, // bLength: Endpoint Descriptor size
+ 0x24, // bDescriptorType: CS_INTERFACE
+ 0x00, // bDescriptorSubtype: Header Func Desc
+ 0x10, // bcdCDC: spec release number
+ 0x01, // ?
+
+ // Call Management Functional Descriptor
+ 0x05, // bFunctionLength
+ 0x24, // bDescriptorType: CS_INTERFACE
+ 0x01, // bDescriptorSubtype: Call Management Func Desc
+ 0x00, // bmCapabilities: D0+D1
+ CDC_IFACE_NUM + 1, // bDataInterface: 1
+
+ // ACM Functional Descriptor
+ 0x04, // bFunctionLength
+ 0x24, // bDescriptorType: CS_INTERFACE
+ 0x02, // bDescriptorSubtype: Abstract Control Management desc
+ 0x02, // bmCapabilities
+
+ // Union Functional Descriptor
+ 0x05, // bFunctionLength
+ 0x24, // bDescriptorType: CS_INTERFACE
+ 0x06, // bDescriptorSubtype: Union func desc
+ CDC_IFACE_NUM + 0, // bMasterInterface: Communication class interface
+ CDC_IFACE_NUM + 1, // bSlaveInterface0: Data Class Interface
+
+ // Endpoint 2 Descriptor
+ 0x07, // bLength: Endpoint Descriptor size
+ USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint
+ CDC_CMD_EP, // bEndpointAddress
+ 0x03, // bmAttributes: Interrupt
+ LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize:
+ HIBYTE(CDC_CMD_PACKET_SIZE),
+ 0x20, // bInterval: polling interval in frames of 1ms
+
+ //--------------------------------------------------------------------------
+ // Data class interface descriptor
+ 0x09, // bLength: Endpoint Descriptor size
+ USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface
+ CDC_IFACE_NUM + 1, // bInterfaceNumber: Number of Interface
+ 0x00, // bAlternateSetting: Alternate setting
+ 0x02, // bNumEndpoints: Two endpoints used
+ 0x0A, // bInterfaceClass: CDC
+ 0x00, // bInterfaceSubClass: ?
+ 0x00, // bInterfaceProtocol: ?
+ 0x00, // iInterface:
+
+ // Endpoint OUT Descriptor
+ 0x07, // bLength: Endpoint Descriptor size
+ USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint
+ CDC_OUT_EP, // bEndpointAddress
+ 0x02, // bmAttributes: Bulk
+ LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
+ HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
+ 0x00, // bInterval: ignore for Bulk transfer
+
+ // Endpoint IN Descriptor
+ 0x07, // bLength: Endpoint Descriptor size
+ USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint
+ CDC_IN_EP, // bEndpointAddress
+ 0x02, // bmAttributes: Bulk
+ LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
+ HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
+ 0x00, // bInterval: ignore for Bulk transfer
+#endif
+
+#if USE_MSC
+ //==========================================================================
+ // MSC only has 1 interface so doesn't need an IAD
+
+ //--------------------------------------------------------------------------
+ // Interface Descriptor
+ 0x09, // bLength: Interface Descriptor size
+ USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface descriptor
+ MSC_IFACE_NUM, // bInterfaceNumber: Number of Interface
+ 0x00, // bAlternateSetting: Alternate setting
+ 0x02, // bNumEndpoints
+ 0x08, // bInterfaceClass: MSC Class
+ 0x06, // bInterfaceSubClass : SCSI transparent
+ 0x50, // nInterfaceProtocol
+ 0x00, // iInterface:
+
+ // Endpoint IN descriptor
+ 0x07, // bLength: Endpoint descriptor length
+ USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type
+ MSC_IN_EP, // bEndpointAddress: IN, address 3
+ 0x02, // bmAttributes: Bulk endpoint type
+ LOBYTE(MSC_MAX_FS_PACKET), // wMaxPacketSize
+ HIBYTE(MSC_MAX_FS_PACKET),
+ 0x00, // bInterval: ignore for Bulk transfer
+
+ // Endpoint OUT descriptor
+ 0x07, // bLength: Endpoint descriptor length
+ USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type
+ MSC_OUT_EP, // bEndpointAddress: OUT, address 3
+ 0x02, // bmAttributes: Bulk endpoint type
+ LOBYTE(MSC_MAX_FS_PACKET), // wMaxPacketSize
+ HIBYTE(MSC_MAX_FS_PACKET),
+ 0x00, // bInterval: ignore for Bulk transfer
+#endif
+};
+
+static uint8_t USBD_CDC_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
+ if (pdev->dev_speed == USBD_SPEED_HIGH) {
+ // can't handle high speed
+ return 1;
+ }
+
+#if USE_CDC
+ //----------------------------------
+ // CDC VCP component
+
+ // Open EP IN
+ USBD_LL_OpenEP(pdev,
+ CDC_IN_EP,
+ USBD_EP_TYPE_BULK,
+ CDC_DATA_FS_IN_PACKET_SIZE);
+
+ // Open EP OUT
+ USBD_LL_OpenEP(pdev,
+ CDC_OUT_EP,
+ USBD_EP_TYPE_BULK,
+ CDC_DATA_FS_OUT_PACKET_SIZE);
+
+ // Open Command IN EP
+ USBD_LL_OpenEP(pdev,
+ CDC_CMD_EP,
+ USBD_EP_TYPE_INTR,
+ CDC_CMD_PACKET_SIZE);
+
+ // Init physical Interface components
+ CDC_fops->Init();
+
+ // Init Xfer states
+ CDC_ClassData.TxState =0;
+ CDC_ClassData.RxState =0;
+
+ // Prepare Out endpoint to receive next packet
+ USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, CDC_ClassData.RxBuffer, CDC_DATA_FS_OUT_PACKET_SIZE);
+#endif
+
+#if USE_MSC
+ //----------------------------------
+ // MSC component
+
+ // Open EP OUT
+ USBD_LL_OpenEP(pdev,
+ MSC_OUT_EP,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+
+ // Open EP IN
+ USBD_LL_OpenEP(pdev,
+ MSC_IN_EP,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+
+ // MSC uses the pClassData pointer because SCSI and BOT reference it
+ pdev->pClassData = &MSC_BOT_ClassData;
+
+ // Init the BOT layer
+ MSC_BOT_Init(pdev);
+#endif
+
+ return 0;
+}
+
+static uint8_t USBD_CDC_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
+#if USD_CDC
+ //----------------------------------
+ // CDC VCP component
+
+ // close endpoints
+ USBD_LL_CloseEP(pdev, CDC_IN_EP);
+ USBD_LL_CloseEP(pdev, CDC_OUT_EP);
+ USBD_LL_CloseEP(pdev, CDC_CMD_EP);
+
+ // DeInit physical Interface components
+ CDC_fops->DeInit();
+#endif
+
+#if USE_MSC
+ //----------------------------------
+ // MSC component
+
+ // close endpoints
+ USBD_LL_CloseEP(pdev, MSC_OUT_EP);
+ USBD_LL_CloseEP(pdev, MSC_IN_EP);
+
+ // DeInit the BOT layer
+ MSC_BOT_DeInit(pdev);
+
+ // clear the pointer
+ pdev->pClassData = NULL;
+#endif
+
+ return 0;
+}
+
+static uint8_t USBD_CDC_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) {
+
+ /*
+ printf("SU: %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex);
+ This is what we get when MSC is IFACE=0 and CDC is IFACE=1,2:
+ SU: 21 22 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE
+ SU: 21 20 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_LINE_CODING
+ SU: a1 fe 0 0 -- 0x80 | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; BOT_GET_MAX_LUN; 0; 0
+ SU: 21 22 3 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE
+ */
+
+ switch (req->bmRequest & USB_REQ_TYPE_MASK) {
+
+ // Class request
+ case USB_REQ_TYPE_CLASS:
+ // req->wIndex is the recipient interface number
+ if (0) {
+#if USE_CDC
+ } else if (req->wIndex == CDC_IFACE_NUM) {
+ // CDC component
+ if (req->wLength) {
+ if (req->bmRequest & 0x80) {
+ // device-to-host request
+ CDC_fops->Control(req->bRequest, (uint8_t*)CDC_ClassData.data, req->wLength);
+ USBD_CtlSendData(pdev, (uint8_t*)CDC_ClassData.data, req->wLength);
+ } else {
+ // host-to-device request
+ CDC_ClassData.CmdOpCode = req->bRequest;
+ CDC_ClassData.CmdLength = req->wLength;
+ USBD_CtlPrepareRx(pdev, (uint8_t*)CDC_ClassData.data, req->wLength);
+ }
+ } else {
+ // Not a Data request
+ // Transfer the command to the interface layer
+ return CDC_fops->Control(req->bRequest, NULL, req->wValue);
+ }
+ break;
+#endif
+#if USE_MSC
+ } else if (req->wIndex == MSC_IFACE_NUM) {
+ // MSC component
+ switch (req->bRequest) {
+ case BOT_GET_MAX_LUN :
+
+ if((req->wValue == 0) &&
+ (req->wLength == 1) &&
+ ((req->bmRequest & 0x80) == 0x80))
+ {
+ MSC_BOT_ClassData.max_lun = MSC_fops->GetMaxLun();
+ USBD_CtlSendData (pdev, (uint8_t *)&MSC_BOT_ClassData.max_lun, 1);
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+
+ case BOT_RESET :
+ if((req->wValue == 0) &&
+ (req->wLength == 0) &&
+ ((req->bmRequest & 0x80) != 0x80))
+ {
+ MSC_BOT_Reset(pdev);
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+ }
+#endif
+ break;
+
+ /* Interface & Endpoint request */
+ case USB_REQ_TYPE_STANDARD:
+#if USE_MSC
+ // MSC only
+ switch (req->bRequest) {
+ case USB_REQ_GET_INTERFACE :
+ USBD_CtlSendData(pdev, (uint8_t *)&MSC_BOT_ClassData.interface, 1);
+ break;
+
+ case USB_REQ_SET_INTERFACE :
+ MSC_BOT_ClassData.interface = (uint8_t)(req->wValue);
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ /* Flush the FIFO and Clear the stall status */
+ USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
+
+ /* Re-activate the EP */
+ USBD_LL_CloseEP (pdev , (uint8_t)req->wIndex);
+ if((((uint8_t)req->wIndex) & 0x80) == 0x80) {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev, MSC_IN_EP, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
+ } else {
+ /* Open EP OUT */
+ USBD_LL_OpenEP(pdev, MSC_OUT_EP, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
+ }
+ /* Handle BOT error */
+ MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
+ break;
+ }
+#endif
+ break;
+ }
+ return USBD_OK;
+}
+
+static uint8_t USBD_CDC_MSC_EP0_RxReady(USBD_HandleTypeDef *pdev) {
+ if((CDC_fops != NULL) && (CDC_ClassData.CmdOpCode != 0xFF)) {
+ CDC_fops->Control(CDC_ClassData.CmdOpCode,
+ (uint8_t *)CDC_ClassData.data,
+ CDC_ClassData.CmdLength);
+ CDC_ClassData.CmdOpCode = 0xFF;
+
+ }
+ return USBD_OK;
+}
+
+static uint8_t USBD_CDC_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) {
+ switch (epnum) {
+#if USE_CDC
+ case (CDC_IN_EP & 0x7f):
+ case (CDC_CMD_EP & 0x7f):
+ CDC_ClassData.TxState = 0;
+ return USBD_OK;
+#endif
+
+ case (MSC_IN_EP & 0x7f):
+ MSC_BOT_DataIn(pdev, epnum);
+ return USBD_OK;
+ }
+
+ return USBD_OK;
+}
+
+static uint8_t USBD_CDC_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) {
+ switch (epnum) {
+#if USE_CDC
+ case (CDC_OUT_EP & 0x7f):
+ /* Get the received data length */
+ CDC_ClassData.RxLength = USBD_LL_GetRxDataSize (pdev, epnum);
+
+ /* USB data will be immediately processed, this allow next USB traffic being
+ NAKed till the end of the application Xfer */
+ CDC_fops->Receive(CDC_ClassData.RxBuffer, &CDC_ClassData.RxLength);
+
+ return USBD_OK;
+#endif
+
+ case (MSC_OUT_EP & 0x7f):
+ MSC_BOT_DataOut(pdev, epnum);
+ return USBD_OK;
+ }
+
+ return USBD_OK;
+}
+
+static uint8_t *USBD_CDC_MSC_GetFSCfgDesc(uint16_t *length) {
+ *length = sizeof(USBD_CDC_MSC_CfgFSDesc);
+ return USBD_CDC_MSC_CfgFSDesc;
+}
+
+static uint8_t *USBD_CDC_MSC_GetHSCfgDesc(uint16_t *length) {
+ *length = 0;
+ return USBD_CDC_MSC_CfgFSDesc; // need to return something because the USB driver writes bytes to the result
+}
+
+static uint8_t *USBD_CDC_MSC_GetOtherSpeedCfgDesc (uint16_t *length) {
+ *length = 0;
+ return USBD_CDC_MSC_CfgFSDesc; // need to return something because the USB driver writes bytes to the result
+}
+
+uint8_t *USBD_CDC_MSC_GetDeviceQualifierDescriptor (uint16_t *length) {
+ *length = sizeof(USBD_CDC_MSC_DeviceQualifierDesc);
+ return USBD_CDC_MSC_DeviceQualifierDesc;
+}
+
+uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops) {
+ if (fops == NULL) {
+ return USBD_FAIL;
+ } else {
+ CDC_fops = fops;
+ return USBD_OK;
+ }
+}
+
+/**
+ * @brief USBD_CDC_SetTxBuffer
+ * @param pdev: device instance
+ * @param pbuff: Tx Buffer
+ * @retval status
+ */
+uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuff,
+ uint16_t length)
+{
+ CDC_ClassData.TxBuffer = pbuff;
+ CDC_ClassData.TxLength = length;
+
+ return USBD_OK;
+}
+
+
+/**
+ * @brief USBD_CDC_SetRxBuffer
+ * @param pdev: device instance
+ * @param pbuff: Rx Buffer
+ * @retval status
+ */
+uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuff)
+{
+ CDC_ClassData.RxBuffer = pbuff;
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_CDC_DataOut
+ * Data received on non-control Out endpoint
+ * @param pdev: device instance
+ * @param epnum: endpoint number
+ * @retval status
+ */
+uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) {
+ if(CDC_ClassData.TxState == 0) {
+
+ /* Transmit next packet */
+ USBD_LL_Transmit(pdev,
+ CDC_IN_EP,
+ CDC_ClassData.TxBuffer,
+ CDC_ClassData.TxLength);
+
+ /* Tx Transfer in progress */
+ CDC_ClassData.TxState = 1;
+ return USBD_OK;
+ }
+ else
+ {
+ return USBD_BUSY;
+ }
+}
+
+
+/**
+ * @brief USBD_CDC_ReceivePacket
+ * prepare OUT Endpoint for reception
+ * @param pdev: device instance
+ * @retval status
+ */
+uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) {
+ // Suspend or Resume USB Out process
+ if (pdev->dev_speed == USBD_SPEED_HIGH) {
+ return USBD_FAIL;
+ }
+
+ // Prepare Out endpoint to receive next packet */
+ USBD_LL_PrepareReceive(pdev,
+ CDC_OUT_EP,
+ CDC_ClassData.RxBuffer,
+ CDC_DATA_FS_OUT_PACKET_SIZE);
+
+ return USBD_OK;
+}
+
+uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops) {
+ if (fops == NULL) {
+ return USBD_FAIL;
+ } else {
+ MSC_fops = fops;
+ pdev->pUserData = fops; // MSC uses pUserData because SCSI and BOT reference it
+ return USBD_OK;
+ }
+}
+
+// CDC + MSC interface class callbacks structure
+USBD_ClassTypeDef USBD_CDC_MSC = {
+ USBD_CDC_MSC_Init,
+ USBD_CDC_MSC_DeInit,
+ USBD_CDC_MSC_Setup,
+ NULL, // EP0_TxSent
+ USBD_CDC_MSC_EP0_RxReady,
+ USBD_CDC_MSC_DataIn,
+ USBD_CDC_MSC_DataOut,
+ NULL, // SOF
+ NULL,
+ NULL,
+ USBD_CDC_MSC_GetHSCfgDesc,
+ USBD_CDC_MSC_GetFSCfgDesc,
+ USBD_CDC_MSC_GetOtherSpeedCfgDesc,
+ USBD_CDC_MSC_GetDeviceQualifierDescriptor,
+};
diff --git a/stmhal/usbdev/class/cdc_msc/src/usbd_msc.c b/stmhal/usbdev/class/cdc_msc/src/usbd_msc.c
new file mode 100644
index 0000000000..7817c98b1c
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/src/usbd_msc.c
@@ -0,0 +1,609 @@
+/**
+ ******************************************************************************
+ * @file usbd_msc_core.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the MSC core functions.
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * MSC Class Description
+ * ===================================================================
+ * This module manages the MSC class V1.0 following the "Universal
+ * Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0
+ * Sep. 31, 1999".
+ * This driver implements the following aspects of the specification:
+ * - Bulk-Only Transport protocol
+ * - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc.h"
+
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_CORE
+ * @brief Mass storage core module
+ * @{
+ */
+
+/** @defgroup MSC_CORE_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_FunctionPrototypes
+ * @{
+ */
+uint8_t USBD_MSC_Init (USBD_HandleTypeDef *pdev,
+ uint8_t cfgidx);
+
+uint8_t USBD_MSC_DeInit (USBD_HandleTypeDef *pdev,
+ uint8_t cfgidx);
+
+uint8_t USBD_MSC_Setup (USBD_HandleTypeDef *pdev,
+ USBD_SetupReqTypedef *req);
+
+uint8_t USBD_MSC_DataIn (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+
+
+uint8_t USBD_MSC_DataOut (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+
+uint8_t *USBD_MSC_GetHSCfgDesc (uint16_t *length);
+
+uint8_t *USBD_MSC_GetFSCfgDesc (uint16_t *length);
+
+uint8_t *USBD_MSC_GetOtherSpeedCfgDesc (uint16_t *length);
+
+uint8_t *USBD_MSC_GetDeviceQualifierDescriptor (uint16_t *length);
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Variables
+ * @{
+ */
+
+
+USBD_ClassTypeDef USBD_MSC =
+{
+ USBD_MSC_Init,
+ USBD_MSC_DeInit,
+ USBD_MSC_Setup,
+ NULL, /*EP0_TxSent*/
+ NULL, /*EP0_RxReady*/
+ USBD_MSC_DataIn,
+ USBD_MSC_DataOut,
+ NULL, /*SOF */
+ NULL,
+ NULL,
+ USBD_MSC_GetHSCfgDesc,
+ USBD_MSC_GetFSCfgDesc,
+ USBD_MSC_GetOtherSpeedCfgDesc,
+ USBD_MSC_GetDeviceQualifierDescriptor,
+};
+
+/* USB Mass storage device Configuration Descriptor */
+/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
+__ALIGN_BEGIN uint8_t USBD_MSC_CfgHSDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END =
+{
+
+ 0x09, /* bLength: Configuation Descriptor size */
+ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
+ USB_MSC_CONFIG_DESC_SIZ,
+
+ 0x00,
+ 0x01, /* bNumInterfaces: 1 interface */
+ 0x01, /* bConfigurationValue: */
+ 0x04, /* iConfiguration: */
+ 0xC0, /* bmAttributes: */
+ 0x32, /* MaxPower 100 mA */
+
+ /******************** Mass Storage interface ********************/
+ 0x09, /* bLength: Interface Descriptor size */
+ 0x04, /* bDescriptorType: */
+ 0x00, /* bInterfaceNumber: Number of Interface */
+ 0x00, /* bAlternateSetting: Alternate setting */
+ 0x02, /* bNumEndpoints*/
+ 0x08, /* bInterfaceClass: MSC Class */
+ 0x06, /* bInterfaceSubClass : SCSI transparent*/
+ 0x50, /* nInterfaceProtocol */
+ 0x05, /* iInterface: */
+ /******************** Mass Storage Endpoints ********************/
+ 0x07, /*Endpoint descriptor length = 7*/
+ 0x05, /*Endpoint descriptor type */
+ MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */
+ 0x02, /*Bulk endpoint type */
+ LOBYTE(MSC_MAX_HS_PACKET),
+ HIBYTE(MSC_MAX_HS_PACKET),
+ 0x00, /*Polling interval in milliseconds */
+
+ 0x07, /*Endpoint descriptor length = 7 */
+ 0x05, /*Endpoint descriptor type */
+ MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */
+ 0x02, /*Bulk endpoint type */
+ LOBYTE(MSC_MAX_HS_PACKET),
+ HIBYTE(MSC_MAX_HS_PACKET),
+ 0x00 /*Polling interval in milliseconds*/
+};
+
+/* USB Mass storage device Configuration Descriptor */
+/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
+uint8_t USBD_MSC_CfgFSDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END =
+{
+
+ 0x09, /* bLength: Configuation Descriptor size */
+ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
+ USB_MSC_CONFIG_DESC_SIZ,
+
+ 0x00,
+ 0x01, /* bNumInterfaces: 1 interface */
+ 0x01, /* bConfigurationValue: */
+ 0x04, /* iConfiguration: */
+ 0xC0, /* bmAttributes: */
+ 0x32, /* MaxPower 100 mA */
+
+ /******************** Mass Storage interface ********************/
+ 0x09, /* bLength: Interface Descriptor size */
+ 0x04, /* bDescriptorType: */
+ 0x00, /* bInterfaceNumber: Number of Interface */
+ 0x00, /* bAlternateSetting: Alternate setting */
+ 0x02, /* bNumEndpoints*/
+ 0x08, /* bInterfaceClass: MSC Class */
+ 0x06, /* bInterfaceSubClass : SCSI transparent*/
+ 0x50, /* nInterfaceProtocol */
+ 0x05, /* iInterface: */
+ /******************** Mass Storage Endpoints ********************/
+ 0x07, /*Endpoint descriptor length = 7*/
+ 0x05, /*Endpoint descriptor type */
+ MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */
+ 0x02, /*Bulk endpoint type */
+ LOBYTE(MSC_MAX_FS_PACKET),
+ HIBYTE(MSC_MAX_FS_PACKET),
+ 0x00, /*Polling interval in milliseconds */
+
+ 0x07, /*Endpoint descriptor length = 7 */
+ 0x05, /*Endpoint descriptor type */
+ MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */
+ 0x02, /*Bulk endpoint type */
+ LOBYTE(MSC_MAX_FS_PACKET),
+ HIBYTE(MSC_MAX_FS_PACKET),
+ 0x00 /*Polling interval in milliseconds*/
+};
+
+__ALIGN_BEGIN uint8_t USBD_MSC_OtherSpeedCfgDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END =
+{
+
+ 0x09, /* bLength: Configuation Descriptor size */
+ USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION,
+ USB_MSC_CONFIG_DESC_SIZ,
+
+ 0x00,
+ 0x01, /* bNumInterfaces: 1 interface */
+ 0x01, /* bConfigurationValue: */
+ 0x04, /* iConfiguration: */
+ 0xC0, /* bmAttributes: */
+ 0x32, /* MaxPower 100 mA */
+
+ /******************** Mass Storage interface ********************/
+ 0x09, /* bLength: Interface Descriptor size */
+ 0x04, /* bDescriptorType: */
+ 0x00, /* bInterfaceNumber: Number of Interface */
+ 0x00, /* bAlternateSetting: Alternate setting */
+ 0x02, /* bNumEndpoints*/
+ 0x08, /* bInterfaceClass: MSC Class */
+ 0x06, /* bInterfaceSubClass : SCSI transparent command set*/
+ 0x50, /* nInterfaceProtocol */
+ 0x05, /* iInterface: */
+ /******************** Mass Storage Endpoints ********************/
+ 0x07, /*Endpoint descriptor length = 7*/
+ 0x05, /*Endpoint descriptor type */
+ MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */
+ 0x02, /*Bulk endpoint type */
+ 0x40,
+ 0x00,
+ 0x00, /*Polling interval in milliseconds */
+
+ 0x07, /*Endpoint descriptor length = 7 */
+ 0x05, /*Endpoint descriptor type */
+ MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */
+ 0x02, /*Bulk endpoint type */
+ 0x40,
+ 0x00,
+ 0x00 /*Polling interval in milliseconds*/
+};
+
+/* USB Standard Device Descriptor */
+__ALIGN_BEGIN uint8_t USBD_MSC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
+{
+ USB_LEN_DEV_QUALIFIER_DESC,
+ USB_DESC_TYPE_DEVICE_QUALIFIER,
+ 0x00,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x00,
+ MSC_MAX_FS_PACKET,
+ 0x01,
+ 0x00,
+};
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief USBD_MSC_Init
+ * Initialize the mass storage configuration
+ * @param pdev: device instance
+ * @param cfgidx: configuration index
+ * @retval status
+ */
+uint8_t USBD_MSC_Init (USBD_HandleTypeDef *pdev,
+ uint8_t cfgidx)
+{
+ int16_t ret = 0;
+
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ /* Open EP OUT */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+ }
+ else
+ {
+ /* Open EP OUT */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+ }
+ pdev->pClassData = USBD_malloc(sizeof (USBD_MSC_BOT_HandleTypeDef));
+
+ if(pdev->pClassData == NULL)
+ {
+ ret = 1;
+ }
+ else
+ {
+ /* Init the BOT layer */
+ MSC_BOT_Init(pdev);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_MSC_DeInit
+ * DeInitilaize the mass storage configuration
+ * @param pdev: device instance
+ * @param cfgidx: configuration index
+ * @retval status
+ */
+uint8_t USBD_MSC_DeInit (USBD_HandleTypeDef *pdev,
+ uint8_t cfgidx)
+{
+ /* Close MSC EPs */
+ USBD_LL_CloseEP(pdev,
+ MSC_EPOUT_ADDR);
+
+ /* Open EP IN */
+ USBD_LL_CloseEP(pdev,
+ MSC_EPIN_ADDR);
+
+
+ /* D-Init the BOT layer */
+ MSC_BOT_DeInit(pdev);
+
+ /* Free MSC Class Resources */
+ if(pdev->pClassData != NULL)
+ {
+ USBD_free(pdev->pClassData);
+ pdev->pClassData = NULL;
+ }
+ return 0;
+}
+/**
+* @brief USBD_MSC_Setup
+* Handle the MSC specific requests
+* @param pdev: device instance
+* @param req: USB request
+* @retval status
+*/
+uint8_t USBD_MSC_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ switch (req->bmRequest & USB_REQ_TYPE_MASK)
+ {
+
+ /* Class request */
+ case USB_REQ_TYPE_CLASS :
+ switch (req->bRequest)
+ {
+ case BOT_GET_MAX_LUN :
+
+ if((req->wValue == 0) &&
+ (req->wLength == 1) &&
+ ((req->bmRequest & 0x80) == 0x80))
+ {
+ hmsc->max_lun = ((USBD_StorageTypeDef *)pdev->pUserData)->GetMaxLun();
+ USBD_CtlSendData (pdev,
+ (uint8_t *)&hmsc->max_lun,
+ 1);
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+
+ case BOT_RESET :
+ if((req->wValue == 0) &&
+ (req->wLength == 0) &&
+ ((req->bmRequest & 0x80) != 0x80))
+ {
+ MSC_BOT_Reset(pdev);
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+ /* Interface & Endpoint request */
+ case USB_REQ_TYPE_STANDARD:
+ switch (req->bRequest)
+ {
+ case USB_REQ_GET_INTERFACE :
+ USBD_CtlSendData (pdev,
+ (uint8_t *)&hmsc->interface,
+ 1);
+ break;
+
+ case USB_REQ_SET_INTERFACE :
+ hmsc->interface = (uint8_t)(req->wValue);
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+
+ /* Flush the FIFO and Clear the stall status */
+ USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
+
+ /* Re-activate the EP */
+ USBD_LL_CloseEP (pdev , (uint8_t)req->wIndex);
+ if((((uint8_t)req->wIndex) & 0x80) == 0x80)
+ {
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+ }
+ else
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+ }
+ }
+ else
+ {
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+ }
+ else
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+ }
+ }
+
+ /* Handle BOT error */
+ MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
+ break;
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+* @brief USBD_MSC_DataIn
+* handle data IN Stage
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval status
+*/
+uint8_t USBD_MSC_DataIn (USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ MSC_BOT_DataIn(pdev , epnum);
+ return 0;
+}
+
+/**
+* @brief USBD_MSC_DataOut
+* handle data OUT Stage
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval status
+*/
+uint8_t USBD_MSC_DataOut (USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ MSC_BOT_DataOut(pdev , epnum);
+ return 0;
+}
+
+/**
+* @brief USBD_MSC_GetHSCfgDesc
+* return configuration descriptor
+* @param length : pointer data length
+* @retval pointer to descriptor buffer
+*/
+uint8_t *USBD_MSC_GetHSCfgDesc (uint16_t *length)
+{
+ *length = sizeof (USBD_MSC_CfgHSDesc);
+ return USBD_MSC_CfgHSDesc;
+}
+
+/**
+* @brief USBD_MSC_GetFSCfgDesc
+* return configuration descriptor
+* @param length : pointer data length
+* @retval pointer to descriptor buffer
+*/
+uint8_t *USBD_MSC_GetFSCfgDesc (uint16_t *length)
+{
+ *length = sizeof (USBD_MSC_CfgFSDesc);
+ return USBD_MSC_CfgFSDesc;
+}
+
+/**
+* @brief USBD_MSC_GetOtherSpeedCfgDesc
+* return other speed configuration descriptor
+* @param length : pointer data length
+* @retval pointer to descriptor buffer
+*/
+uint8_t *USBD_MSC_GetOtherSpeedCfgDesc (uint16_t *length)
+{
+ *length = sizeof (USBD_MSC_OtherSpeedCfgDesc);
+ return USBD_MSC_OtherSpeedCfgDesc;
+}
+/**
+* @brief DeviceQualifierDescriptor
+* return Device Qualifier descriptor
+* @param length : pointer data length
+* @retval pointer to descriptor buffer
+*/
+uint8_t *USBD_MSC_GetDeviceQualifierDescriptor (uint16_t *length)
+{
+ *length = sizeof (USBD_MSC_DeviceQualifierDesc);
+ return USBD_MSC_DeviceQualifierDesc;
+}
+
+/**
+* @brief USBD_MSC_RegisterStorage
+* @param fops: storage callback
+* @retval status
+*/
+uint8_t USBD_MSC_RegisterStorage (USBD_HandleTypeDef *pdev,
+ USBD_StorageTypeDef *fops)
+{
+ if(fops != NULL)
+ {
+ pdev->pUserData= fops;
+ }
+ return 0;
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc/src/usbd_msc_bot.c b/stmhal/usbdev/class/cdc_msc/src/usbd_msc_bot.c
new file mode 100644
index 0000000000..69c34a5838
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/src/usbd_msc_bot.c
@@ -0,0 +1,407 @@
+/**
+ ******************************************************************************
+ * @file usbd_msc_bot.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the BOT protocol core functions.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc_bot.h"
+#include "usbd_msc_scsi.h"
+#include "usbd_cdc_msc.h"
+#include "usbd_ioreq.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_BOT
+ * @brief BOT protocol module
+ * @{
+ */
+
+/** @defgroup MSC_BOT_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_FunctionPrototypes
+ * @{
+ */
+static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev);
+
+static void MSC_BOT_SendData (USBD_HandleTypeDef *pdev,
+ uint8_t* pbuf,
+ uint16_t len);
+
+static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev);
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Functions
+ * @{
+ */
+
+
+
+/**
+* @brief MSC_BOT_Init
+* Initialize the BOT Process
+* @param pdev: device instance
+* @retval None
+*/
+void MSC_BOT_Init (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->bot_state = USBD_BOT_IDLE;
+ hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
+
+ hmsc->scsi_sense_tail = 0;
+ hmsc->scsi_sense_head = 0;
+
+ ((USBD_StorageTypeDef *)pdev->pUserData)->Init(0);
+
+ USBD_LL_FlushEP(pdev, MSC_OUT_EP);
+ USBD_LL_FlushEP(pdev, MSC_IN_EP);
+
+ /* Prapare EP to Receive First BOT Cmd */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (uint8_t *)&hmsc->cbw,
+ USBD_BOT_CBW_LENGTH);
+}
+
+/**
+* @brief MSC_BOT_Reset
+* Reset the BOT Machine
+* @param pdev: device instance
+* @retval None
+*/
+void MSC_BOT_Reset (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->bot_state = USBD_BOT_IDLE;
+ hmsc->bot_status = USBD_BOT_STATUS_RECOVERY;
+
+ /* Prapare EP to Receive First BOT Cmd */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (uint8_t *)&hmsc->cbw,
+ USBD_BOT_CBW_LENGTH);
+}
+
+/**
+* @brief MSC_BOT_DeInit
+* Uninitialize the BOT Machine
+* @param pdev: device instance
+* @retval None
+*/
+void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ hmsc->bot_state = USBD_BOT_IDLE;
+}
+
+/**
+* @brief MSC_BOT_DataIn
+* Handle BOT IN data stage
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval None
+*/
+void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ switch (hmsc->bot_state)
+ {
+ case USBD_BOT_DATA_IN:
+ if(SCSI_ProcessCmd(pdev,
+ hmsc->cbw.bLUN,
+ &hmsc->cbw.CB[0]) < 0)
+ {
+ MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
+ }
+ break;
+
+ case USBD_BOT_SEND_DATA:
+ case USBD_BOT_LAST_DATA_IN:
+ MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
+
+ break;
+
+ default:
+ break;
+ }
+}
+/**
+* @brief MSC_BOT_DataOut
+* Proccess MSC OUT data
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval None
+*/
+void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ switch (hmsc->bot_state)
+ {
+ case USBD_BOT_IDLE:
+ MSC_BOT_CBW_Decode(pdev);
+ break;
+
+ case USBD_BOT_DATA_OUT:
+
+ if(SCSI_ProcessCmd(pdev,
+ hmsc->cbw.bLUN,
+ &hmsc->cbw.CB[0]) < 0)
+ {
+ MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+* @brief MSC_BOT_CBW_Decode
+* Decode the CBW command and set the BOT state machine accordingtly
+* @param pdev: device instance
+* @retval None
+*/
+static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->csw.dTag = hmsc->cbw.dTag;
+ hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
+
+ if ((USBD_LL_GetRxDataSize (pdev ,MSC_OUT_EP) != USBD_BOT_CBW_LENGTH) ||
+ (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE)||
+ (hmsc->cbw.bLUN > 1) ||
+ (hmsc->cbw.bCBLength < 1) ||
+ (hmsc->cbw.bCBLength > 16))
+ {
+
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+
+ hmsc->bot_status = USBD_BOT_STATUS_ERROR;
+ MSC_BOT_Abort(pdev);
+
+ }
+ else
+ {
+ if(SCSI_ProcessCmd(pdev,
+ hmsc->cbw.bLUN,
+ &hmsc->cbw.CB[0]) < 0)
+ {
+ if(hmsc->bot_state == USBD_BOT_NO_DATA)
+ {
+ MSC_BOT_SendCSW (pdev,
+ USBD_CSW_CMD_FAILED);
+ }
+ else
+ {
+ MSC_BOT_Abort(pdev);
+ }
+ }
+ /*Burst xfer handled internally*/
+ else if ((hmsc->bot_state != USBD_BOT_DATA_IN) &&
+ (hmsc->bot_state != USBD_BOT_DATA_OUT) &&
+ (hmsc->bot_state != USBD_BOT_LAST_DATA_IN))
+ {
+ if (hmsc->bot_data_length > 0)
+ {
+ MSC_BOT_SendData(pdev,
+ hmsc->bot_data,
+ hmsc->bot_data_length);
+ }
+ else if (hmsc->bot_data_length == 0)
+ {
+ MSC_BOT_SendCSW (pdev,
+ USBD_CSW_CMD_PASSED);
+ }
+ }
+ }
+}
+
+/**
+* @brief MSC_BOT_SendData
+* Send the requested data
+* @param pdev: device instance
+* @param buf: pointer to data buffer
+* @param len: Data Length
+* @retval None
+*/
+static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
+ uint8_t* buf,
+ uint16_t len)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ len = MIN (hmsc->cbw.dDataLength, len);
+ hmsc->csw.dDataResidue -= len;
+ hmsc->csw.bStatus = USBD_CSW_CMD_PASSED;
+ hmsc->bot_state = USBD_BOT_SEND_DATA;
+
+ USBD_LL_Transmit (pdev, MSC_IN_EP, buf, len);
+}
+
+/**
+* @brief MSC_BOT_SendCSW
+* Send the Command Status Wrapper
+* @param pdev: device instance
+* @param status : CSW status
+* @retval None
+*/
+void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev,
+ uint8_t CSW_Status)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE;
+ hmsc->csw.bStatus = CSW_Status;
+ hmsc->bot_state = USBD_BOT_IDLE;
+
+ USBD_LL_Transmit (pdev,
+ MSC_IN_EP,
+ (uint8_t *)&hmsc->csw,
+ USBD_BOT_CSW_LENGTH);
+
+ /* Prapare EP to Receive next Cmd */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (uint8_t *)&hmsc->cbw,
+ USBD_BOT_CBW_LENGTH);
+
+}
+
+/**
+* @brief MSC_BOT_Abort
+* Abort the current transfer
+* @param pdev: device instance
+* @retval status
+*/
+
+static void MSC_BOT_Abort (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if ((hmsc->cbw.bmFlags == 0) &&
+ (hmsc->cbw.dDataLength != 0) &&
+ (hmsc->bot_status == USBD_BOT_STATUS_NORMAL) )
+ {
+ USBD_LL_StallEP(pdev, MSC_OUT_EP );
+ }
+ USBD_LL_StallEP(pdev, MSC_IN_EP);
+
+ if(hmsc->bot_status == USBD_BOT_STATUS_ERROR)
+ {
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (uint8_t *)&hmsc->cbw,
+ USBD_BOT_CBW_LENGTH);
+ }
+}
+
+/**
+* @brief MSC_BOT_CplClrFeature
+* Complete the clear feature request
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval None
+*/
+
+void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if(hmsc->bot_status == USBD_BOT_STATUS_ERROR )/* Bad CBW Signature */
+ {
+ USBD_LL_StallEP(pdev, MSC_IN_EP);
+ hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
+ }
+ else if(((epnum & 0x80) == 0x80) && ( hmsc->bot_status != USBD_BOT_STATUS_RECOVERY))
+ {
+ MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
+ }
+
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc/src/usbd_msc_data.c b/stmhal/usbdev/class/cdc_msc/src/usbd_msc_data.c
new file mode 100644
index 0000000000..4d72bd5fce
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/src/usbd_msc_data.c
@@ -0,0 +1,134 @@
+/**
+ ******************************************************************************
+ * @file usbd_msc_data.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the vital inquiry pages and sense data.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc_data.h"
+
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_DATA
+ * @brief Mass storage info/data module
+ * @{
+ */
+
+/** @defgroup MSC_DATA_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Variables
+ * @{
+ */
+
+
+/* USB Mass storage Page 0 Inquiry Data */
+const uint8_t MSC_Page00_Inquiry_Data[] = {//7
+ 0x00,
+ 0x00,
+ 0x00,
+ (LENGTH_INQUIRY_PAGE00 - 4),
+ 0x00,
+ 0x80,
+ 0x83
+};
+/* USB Mass storage sense 6 Data */
+const uint8_t MSC_Mode_Sense6_data[] = {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+/* USB Mass storage sense 10 Data */
+const uint8_t MSC_Mode_Sense10_data[] = {
+ 0x00,
+ 0x06,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_FunctionPrototypes
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Functions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc/src/usbd_msc_scsi.c b/stmhal/usbdev/class/cdc_msc/src/usbd_msc_scsi.c
new file mode 100644
index 0000000000..dd3de90feb
--- /dev/null
+++ b/stmhal/usbdev/class/cdc_msc/src/usbd_msc_scsi.c
@@ -0,0 +1,770 @@
+/**
+ ******************************************************************************
+ * @file usbd_msc_scsi.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the USBD SCSI layer functions.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc_bot.h"
+#include "usbd_msc_scsi.h"
+#include "usbd_msc_data.h"
+#include "usbd_cdc_msc.h"
+
+
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_SCSI
+ * @brief Mass storage SCSI layer module
+ * @{
+ */
+
+/** @defgroup MSC_SCSI_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_FunctionPrototypes
+ * @{
+ */
+static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
+static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
+static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev,
+ uint8_t lun ,
+ uint32_t blk_offset ,
+ uint16_t blk_nbr);
+static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev,
+ uint8_t lun);
+
+static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev,
+ uint8_t lun);
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Functions
+ * @{
+ */
+
+
+/**
+* @brief SCSI_ProcessCmd
+* Process SCSI commands
+* @param pdev: device instance
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
+ uint8_t lun,
+ uint8_t *params)
+{
+
+ switch (params[0])
+ {
+ case SCSI_TEST_UNIT_READY:
+ return SCSI_TestUnitReady(pdev, lun, params);
+
+ case SCSI_REQUEST_SENSE:
+ return SCSI_RequestSense (pdev, lun, params);
+ case SCSI_INQUIRY:
+ return SCSI_Inquiry(pdev, lun, params);
+
+ case SCSI_START_STOP_UNIT:
+ return SCSI_StartStopUnit(pdev, lun, params);
+
+ case SCSI_ALLOW_MEDIUM_REMOVAL:
+ return SCSI_StartStopUnit(pdev, lun, params);
+
+ case SCSI_MODE_SENSE6:
+ return SCSI_ModeSense6 (pdev, lun, params);
+
+ case SCSI_MODE_SENSE10:
+ return SCSI_ModeSense10 (pdev, lun, params);
+
+ case SCSI_READ_FORMAT_CAPACITIES:
+ return SCSI_ReadFormatCapacity(pdev, lun, params);
+
+ case SCSI_READ_CAPACITY10:
+ return SCSI_ReadCapacity10(pdev, lun, params);
+
+ case SCSI_READ10:
+ return SCSI_Read10(pdev, lun, params);
+
+ case SCSI_WRITE10:
+ return SCSI_Write10(pdev, lun, params);
+
+ case SCSI_VERIFY10:
+ return SCSI_Verify10(pdev, lun, params);
+
+ default:
+ SCSI_SenseCode(pdev,
+ lun,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+}
+
+
+/**
+* @brief SCSI_TestUnitReady
+* Process SCSI Test Unit Ready Command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ /* case 9 : Hi > D0 */
+ if (hmsc->cbw.dDataLength != 0)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+
+ hmsc->bot_state = USBD_BOT_NO_DATA;
+ return -1;
+ }
+ hmsc->bot_data_length = 0;
+ return 0;
+}
+
+/**
+* @brief SCSI_Inquiry
+* Process Inquiry command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ uint8_t* pPage;
+ uint16_t len;
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if (params[1] & 0x01)/*Evpd is set*/
+ {
+ pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
+ len = LENGTH_INQUIRY_PAGE00;
+ }
+ else
+ {
+
+ pPage = (uint8_t *)&((USBD_StorageTypeDef *)pdev->pUserData)->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN];
+ len = pPage[4] + 5;
+
+ if (params[4] <= len)
+ {
+ len = params[4];
+ }
+ }
+ hmsc->bot_data_length = len;
+
+ while (len)
+ {
+ len--;
+ hmsc->bot_data[len] = pPage[len];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_ReadCapacity10
+* Process Read Capacity 10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0)
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+ else
+ {
+
+ hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24);
+ hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16);
+ hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 8);
+ hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1);
+
+ hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24);
+ hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16);
+ hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8);
+ hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size);
+
+ hmsc->bot_data_length = 8;
+ return 0;
+ }
+}
+/**
+* @brief SCSI_ReadFormatCapacity
+* Process Read Format Capacity command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ uint16_t blk_size;
+ uint32_t blk_nbr;
+ uint16_t i;
+
+ for(i=0 ; i < 12 ; i++)
+ {
+ hmsc->bot_data[i] = 0;
+ }
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blk_nbr, &blk_size) != 0)
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+ else
+ {
+ hmsc->bot_data[3] = 0x08;
+ hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24);
+ hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16);
+ hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >> 8);
+ hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1);
+
+ hmsc->bot_data[8] = 0x02;
+ hmsc->bot_data[9] = (uint8_t)(blk_size >> 16);
+ hmsc->bot_data[10] = (uint8_t)(blk_size >> 8);
+ hmsc->bot_data[11] = (uint8_t)(blk_size);
+
+ hmsc->bot_data_length = 12;
+ return 0;
+ }
+}
+/**
+* @brief SCSI_ModeSense6
+* Process Mode Sense6 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ uint16_t len = 8 ;
+ hmsc->bot_data_length = len;
+
+ while (len)
+ {
+ len--;
+ hmsc->bot_data[len] = MSC_Mode_Sense6_data[len];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_ModeSense10
+* Process Mode Sense10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ uint16_t len = 8;
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->bot_data_length = len;
+
+ while (len)
+ {
+ len--;
+ hmsc->bot_data[len] = MSC_Mode_Sense10_data[len];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_RequestSense
+* Process Request Sense command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+
+static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ uint8_t i;
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
+ {
+ hmsc->bot_data[i] = 0;
+ }
+
+ hmsc->bot_data[0] = 0x70;
+ hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6;
+
+ if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) {
+
+ hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;
+ hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;
+ hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;
+ hmsc->scsi_sense_head++;
+
+ if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
+ {
+ hmsc->scsi_sense_head = 0;
+ }
+ }
+ hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;
+
+ if (params[4] <= REQUEST_SENSE_DATA_LEN)
+ {
+ hmsc->bot_data_length = params[4];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_SenseCode
+* Load the last error code in the error list
+* @param lun: Logical unit number
+* @param sKey: Sense Key
+* @param ASC: Additional Sense Key
+* @retval none
+
+*/
+void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;
+ hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8;
+ hmsc->scsi_sense_tail++;
+ if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH)
+ {
+ hmsc->scsi_sense_tail = 0;
+ }
+}
+/**
+* @brief SCSI_StartStopUnit
+* Process Start Stop Unit command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ hmsc->bot_data_length = 0;
+ return 0;
+}
+
+/**
+* @brief SCSI_Read10
+* Process Read10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
+ {
+
+ /* case 10 : Ho <> Di */
+
+ if ((hmsc->cbw.bmFlags & 0x80) != 0x80)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+
+ hmsc->scsi_blk_addr = (params[2] << 24) | \
+ (params[3] << 16) | \
+ (params[4] << 8) | \
+ params[5];
+
+ hmsc->scsi_blk_len = (params[7] << 8) | \
+ params[8];
+
+
+
+ if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
+ {
+ return -1; /* error */
+ }
+
+ hmsc->bot_state = USBD_BOT_DATA_IN;
+ hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
+ hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
+
+ /* cases 4,5 : Hi <> Dn */
+ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+ }
+ hmsc->bot_data_length = MSC_MEDIA_PACKET;
+
+ return SCSI_ProcessRead(pdev, lun);
+}
+
+/**
+* @brief SCSI_Write10
+* Process Write10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+
+static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
+ {
+
+ /* case 8 : Hi <> Do */
+
+ if ((hmsc->cbw.bmFlags & 0x80) == 0x80)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ /* Check whether Media is ready */
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+
+ /* Check If media is write-protected */
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ WRITE_PROTECTED);
+ return -1;
+ }
+
+
+ hmsc->scsi_blk_addr = (params[2] << 24) | \
+ (params[3] << 16) | \
+ (params[4] << 8) | \
+ params[5];
+ hmsc->scsi_blk_len = (params[7] << 8) | \
+ params[8];
+
+ /* check if LBA address is in the right range */
+ if(SCSI_CheckAddressRange(pdev,
+ lun,
+ hmsc->scsi_blk_addr,
+ hmsc->scsi_blk_len) < 0)
+ {
+ return -1; /* error */
+ }
+
+ hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
+ hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
+
+ /* cases 3,11,13 : Hn,Ho <> D0 */
+ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ /* Prepare EP to receive first data packet */
+ hmsc->bot_state = USBD_BOT_DATA_OUT;
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ hmsc->bot_data,
+ MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
+ }
+ else /* Write Process ongoing */
+ {
+ return SCSI_ProcessWrite(pdev, lun);
+ }
+ return 0;
+}
+
+
+/**
+* @brief SCSI_Verify10
+* Process Verify10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+
+static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if ((params[1]& 0x02) == 0x02)
+ {
+ SCSI_SenseCode (pdev,
+ lun,
+ ILLEGAL_REQUEST,
+ INVALID_FIELED_IN_COMMAND);
+ return -1; /* Error, Verify Mode Not supported*/
+ }
+
+ if(SCSI_CheckAddressRange(pdev,
+ lun,
+ hmsc->scsi_blk_addr,
+ hmsc->scsi_blk_len) < 0)
+ {
+ return -1; /* error */
+ }
+ hmsc->bot_data_length = 0;
+ return 0;
+}
+
+/**
+* @brief SCSI_CheckAddressRange
+* Check address range
+* @param lun: Logical unit number
+* @param blk_offset: first block address
+* @param blk_nbr: number of block to be processed
+* @retval status
+*/
+static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ ILLEGAL_REQUEST,
+ ADDRESS_OUT_OF_RANGE);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_ProcessRead
+* Handle Read Process
+* @param lun: Logical unit number
+* @retval status
+*/
+static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ uint32_t len;
+
+ len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
+
+ if( ((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun ,
+ hmsc->bot_data,
+ hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
+ len / hmsc->scsi_blk_size) < 0)
+ {
+
+ SCSI_SenseCode(pdev,
+ lun,
+ HARDWARE_ERROR,
+ UNRECOVERED_READ_ERROR);
+ return -1;
+ }
+
+
+ USBD_LL_Transmit (pdev,
+ MSC_IN_EP,
+ hmsc->bot_data,
+ len);
+
+
+ hmsc->scsi_blk_addr += len;
+ hmsc->scsi_blk_len -= len;
+
+ /* case 6 : Hi = Di */
+ hmsc->csw.dDataResidue -= len;
+
+ if (hmsc->scsi_blk_len == 0)
+ {
+ hmsc->bot_state = USBD_BOT_LAST_DATA_IN;
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_ProcessWrite
+* Handle Write Process
+* @param lun: Logical unit number
+* @retval status
+*/
+
+static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
+{
+ uint32_t len;
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun ,
+ hmsc->bot_data,
+ hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
+ len / hmsc->scsi_blk_size) < 0)
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ HARDWARE_ERROR,
+ WRITE_FAULT);
+ return -1;
+ }
+
+
+ hmsc->scsi_blk_addr += len;
+ hmsc->scsi_blk_len -= len;
+
+ /* case 12 : Ho = Do */
+ hmsc->csw.dDataResidue -= len;
+
+ if (hmsc->scsi_blk_len == 0)
+ {
+ MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
+ }
+ else
+ {
+ /* Prapare EP to Receive next packet */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ hmsc->bot_data,
+ MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
+ }
+
+ return 0;
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/core/inc/usbd_conf_template.h b/stmhal/usbdev/core/inc/usbd_conf_template.h
deleted file mode 100644
index d80c1da61b..0000000000
--- a/stmhal/usbdev/core/inc/usbd_conf_template.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- ******************************************************************************
- * @file usbd_conf_template.h
- * @author MCD Application Team
- * @version V2.0.0
- * @date 18-February-2014
- * @brief General low level driver configuration
- ******************************************************************************
- * @attention
- *
- * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
- *
- * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.st.com/software_license_agreement_liberty_v2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************
- */
-
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef __USBD_CONF__H__
-#define __USBD_CONF__H__
-
-#include "stm32f4xx.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Includes ------------------------------------------------------------------*/
-
-/** @addtogroup USBD_OTG_DRIVER
- * @{
- */
-
-/** @defgroup USBD_CONF
- * @brief usb otg low level driver configuration file
- * @{
- */
-
-/** @defgroup USBD_CONF_Exported_Defines
- * @{
- */
-
-#define USBD_MAX_NUM_INTERFACES 1
-#define USBD_MAX_NUM_CONFIGURATION 1
-#define USBD_MAX_STR_DESC_SIZ 0x100
-#define USBD_SUPPORT_USER_STRING 0
-#define USBD_SELF_POWERED 1
-#define USBD_DEBUG_LEVEL 2
-
-/* MSC Class Config */
-#define MSC_MEDIA_PACKET 8192
-
-/* CDC Class Config */
-#define USBD_CDC_INTERVAL 2000
-
- /* DFU Class Config */
-#define USBD_DFU_MAX_ITF_NUM 1
-#define USBD_DFU_XFERS_IZE 1024
-
- /* AUDIO Class Config */
-#define USBD_AUDIO_FREQ 22100
-
-/** @defgroup USBD_Exported_Macros
- * @{
- */
-
- /* Memory management macros */
-#define USBD_malloc malloc
-#define USBD_free free
-#define USBD_memset memset
-#define USBD_memcpy memcpy
-
- /* DEBUG macros */
-
-
-#if (USBD_DEBUG_LEVEL > 0)
-#define USBD_UsrLog(...) printf(__VA_ARGS__);\
- printf("\n");
-#else
-#define USBD_UsrLog(...)
-#endif
-
-
-#if (USBD_DEBUG_LEVEL > 1)
-
-#define USBD_ErrLog(...) printf("ERROR: ") ;\
- printf(__VA_ARGS__);\
- printf("\n");
-#else
-#define USBD_ErrLog(...)
-#endif
-
-
-#if (USBD_DEBUG_LEVEL > 2)
-#define USBD_DbgLog(...) printf("DEBUG : ") ;\
- printf(__VA_ARGS__);\
- printf("\n");
-#else
-#define USBD_DbgLog(...)
-#endif
-
-/**
- * @}
- */
-
-
-
-/**
- * @}
- */
-
-
-/** @defgroup USBD_CONF_Exported_Types
- * @{
- */
-/**
- * @}
- */
-
-
-/** @defgroup USBD_CONF_Exported_Macros
- * @{
- */
-/**
- * @}
- */
-
-/** @defgroup USBD_CONF_Exported_Variables
- * @{
- */
-/**
- * @}
- */
-
-/** @defgroup USBD_CONF_Exported_FunctionsPrototype
- * @{
- */
-/**
- * @}
- */
-
-
-#endif //__USBD_CONF__H__
-
-
-/**
- * @}
- */
-
-/**
- * @}
- */
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
-
diff --git a/stmhal/usbdev/core/src/usbd_conf_template.c b/stmhal/usbdev/core/src/usbd_conf_template.c
deleted file mode 100644
index 8f4608d1f0..0000000000
--- a/stmhal/usbdev/core/src/usbd_conf_template.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/**
- ******************************************************************************
- * @file usbd_storage_template.c
- * @author MCD Application Team
- * @version V2.0.0
- * @date 18-February-2014
- * @brief Memory management layer
- ******************************************************************************
- * @attention
- *
- * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
- *
- * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.st.com/software_license_agreement_liberty_v2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************
- */
-
-/* Includes ------------------------------------------------------------------*/
-#include "usbd_storage.h"
-
-
-/** @addtogroup STM32_USBD_DEVICE_LIBRARY
-* @{
-*/
-
-
-/** @defgroup USBD_STORAGE
-* @brief usbd core module
-* @{
-*/
-
-/** @defgroup USBD_STORAGE_Private_TypesDefinitions
-* @{
-*/
-/**
-* @}
-*/
-
-
-/** @defgroup USBD_STORAGE_Private_Defines
-* @{
-*/
-#define STORAGE_LUN_NBR 1
-#define STORAGE_BLK_NBR 0x10000
-#define STORAGE_BLK_SIZ 0x200
-/**
-* @}
-*/
-
-
-/** @defgroup USBD_STORAGE_Private_Macros
-* @{
-*/
-/**
-* @}
-*/
-
-
-
-
-/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
-* @{
-*/
-
-/**
-* @}
-*/
-
-
-/** @defgroup USBD_STORAGE_Private_Functions
-* @{
-*/
-
-int8_t STORAGE_Init (uint8_t lun);
-
-int8_t STORAGE_GetCapacity (uint8_t lun,
- uint32_t *block_num,
- uint16_t *block_size);
-
-int8_t STORAGE_IsReady (uint8_t lun);
-
-int8_t STORAGE_IsWriteProtected (uint8_t lun);
-
-int8_t STORAGE_Read (uint8_t lun,
- uint8_t *buf,
- uint32_t blk_addr,
- uint16_t blk_len);
-
-int8_t STORAGE_Write (uint8_t lun,
- uint8_t *buf,
- uint32_t blk_addr,
- uint16_t blk_len);
-
-int8_t STORAGE_GetMaxLun (void);
-
-/** @defgroup USBD_STORAGE_Private_Variables
-* @{
-*/
-
-/* USB Mass storage Standard Inquiry Data */
-int8_t STORAGE_Inquirydata[] = {//36
-
- /* LUN 0 */
- 0x00,
- 0x80,
- 0x02,
- 0x02,
- (STANDARD_INQUIRY_DATA_LEN - 5),
- 0x00,
- 0x00,
- 0x00,
- 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
- 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
- ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
- '0', '.', '0' ,'1', /* Version : 4 Bytes */
-};
-
-USBD_StorageTypeDef USBD_MSD_fops =
-{
- STORAGE_Init,
- STORAGE_GetCapacity,
- STORAGE_IsReady,
- STORAGE_IsWriteProtected,
- STORAGE_Read,
- STORAGE_Write,
- STORAGE_GetMaxLun,
- STORAGE_Inquirydata,
-
-};
-/**
- * @}
- */
-
-/** @defgroup USBD_CORE_Private_Functions
- * @{
- */
-
-/**
- * @brief STORAGE_Init
- * Initailizes the storage unit (medium)
- * @param lun: logical unit number
- * @retval status (0 : Ok / -1 : Error)
- */
-
-int8_t STORAGE_Init (uint8_t lun)
-{
- return (0);
-}
-
-/**
- * @brief STORAGE_GetCapacity
- * return medium capacity
- * @param lun: logical unit number
- * @param block_num: number of total block number
- * @param block_size: block size
- * @retval status (0 : Ok / -1 : Error)
- */
-int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
-{
-
- *block_num = STORAGE_BLK_NBR - 1;
- *block_size = STORAGE_BLK_SIZ;
-
- return (0);
-}
-
-/**
- * @brief STORAGE_IsReady
- * check whether the medium is ready
- * @param lun: logical unit number
- * @retval status (0 : Ok / -1 : Error)
- */
-int8_t STORAGE_IsReady (uint8_t lun)
-{
-
- return (0);
-}
-
-/**
- * @brief STORAGE_IsWriteProtected
- * check whether the medium is write protected
- * @param lun: logical unit number
- * @retval status (0 : write enabled / -1 : otherwise)
- */
-int8_t STORAGE_IsWriteProtected (uint8_t lun)
-{
- return 0;
-}
-
-/**
- * @brief STORAGE_Read
- * Read data from the medium
- * @param lun: logical unit number
- * @param blk_addr: logical block address
- * @param blk_len: blocks number
- * @retval status (0 : Ok / -1 : Error)
- */
-int8_t STORAGE_Read (uint8_t lun,
- uint8_t *buf,
- uint32_t blk_addr,
- uint16_t blk_len)
-{
- return (0);
-}
-
-/**
- * @brief STORAGE_Write
- * Write data into the medium
- * @param lun: logical unit number
- * @param blk_addr: logical block address
- * @param blk_len: blocks number
- * @retval status (0 : Ok / -1 : Error)
- */
-int8_t STORAGE_Write (uint8_t lun,
- uint8_t *buf,
- uint32_t blk_addr,
- uint16_t blk_len)
-{
- return (0);
-}
-
-
-/**
- * @brief STORAGE_GetMaxLun
- * return the Max Supported LUNs
- * @param none
- * @retval lun(s) number
- */
-int8_t STORAGE_GetMaxLun (void)
-{
- return (STORAGE_LUN_NBR - 1);
-}
-/**
-* @}
-*/
-
-
-/**
-* @}
-*/
-
-
-/**
-* @}
-*/
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
-
diff --git a/tests/basics/generator-exc.py b/tests/basics/generator-exc.py
new file mode 100644
index 0000000000..09aca5d9a0
--- /dev/null
+++ b/tests/basics/generator-exc.py
@@ -0,0 +1,53 @@
+# Test proper handling of exceptions within generator across yield
+def gen():
+ try:
+ yield 1
+ raise ValueError
+ except ValueError:
+ print("Caught")
+ yield 2
+
+for i in gen():
+ print(i)
+
+
+# Test throwing exceptions out of generator
+def gen2():
+ yield 1
+ raise ValueError
+ yield 2
+ yield 3
+
+g = gen2()
+print(next(g))
+try:
+ print(next(g))
+except ValueError:
+ print("ValueError")
+
+try:
+ print(next(g))
+except StopIteration:
+ print("StopIteration")
+
+
+# Test throwing exception into generator
+def gen3():
+ yield 1
+ try:
+ yield 2
+ except ValueError:
+ print("ValueError received")
+ yield 3
+ yield 4
+ yield 5
+
+g = gen3()
+print(next(g))
+print(next(g))
+print("out of throw:", g.throw(ValueError))
+print(next(g))
+try:
+ print("out of throw2:", g.throw(ValueError))
+except ValueError:
+ print("Boomerang ValueError caught")