diff --git a/src/Makefile b/src/Makefile
index 9aeb957d7..fdeafc853 100755
--- a/src/Makefile
+++ b/src/Makefile
@@ -27,6 +27,7 @@ CAT = $(Q)cat
# Targets
OPENMV = openmv
BOOTLOADER = bootloader
+WEBCAM = webcam
FIRMWARE = firmware
# Directories
@@ -38,7 +39,8 @@ MICROPY_DIR=micropython
OMV_DIR=omv
LEPTON_DIR=lepton
WINC1500_DIR=winc1500
-BOOT_DIR=bootloader
+BOOTLDR_DIR=bootloader
+WEBCAM_DIR=webcam
# Additional qstr definitions for OpenMV
OMV_QSTR_DEFS = $(TOP_DIR)/$(OMV_DIR)/py/qstrdefsomv.h
@@ -80,38 +82,51 @@ CFLAGS += -D$(MCU) -D$(CFLAGS_MCU) -D$(ARM_MATH) -DARM_MATH_DSP -DARM_NN_TRUNCAT
CFLAGS += -D__FPU_PRESENT=1 -D__VFP_FP__ -DUSE_USB_FS -DUSE_DEVICE_MODE -DUSE_USB_OTG_ID=0 -DHSE_VALUE=12000000\
-D$(TARGET) -DSTM32_HAL_H=$(HAL_INC) -DVECT_TAB_OFFSET=$(VECT_TAB_OFFSET) -DMAIN_APP_ADDR=$(MAIN_APP_ADDR)
-CFLAGS += -I. -Iinclude
-CFLAGS += -I$(TOP_DIR)/$(BOOT_DIR)/include/
-CFLAGS += -I$(TOP_DIR)/$(CMSIS_DIR)/include/
-CFLAGS += -I$(TOP_DIR)/$(CMSIS_DIR)/include/st
-CFLAGS += -I$(TOP_DIR)/$(STHAL_DIR)/include/
-CFLAGS += -I$(TOP_DIR)/$(STHAL_DIR)/include/Legacy/
+ST_CFLAGS += -I. -Iinclude
+ST_CFLAGS += -I$(TOP_DIR)/$(CMSIS_DIR)/include/
+ST_CFLAGS += -I$(TOP_DIR)/$(CMSIS_DIR)/include/st
+ST_CFLAGS += -I$(TOP_DIR)/$(STHAL_DIR)/include/
+ST_CFLAGS += -I$(TOP_DIR)/$(STHAL_DIR)/include/Legacy/
-CFLAGS += -I$(BUILD)/$(MICROPY_DIR)/
-CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/
-CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/py/
-CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/lib/mp-readline
-CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/lib/oofatfs
-CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/
-CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/usbdev/core/inc/
-CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/usbdev/class/inc/
-CFLAGS += -I$(MP_BOARD_CONFIG_DIR)
+MP_CFLAGS += -I$(BUILD)/$(MICROPY_DIR)/
+MP_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/
+MP_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/py/
+MP_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/lib/mp-readline
+MP_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/lib/oofatfs
+MP_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/
+MP_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/usbdev/core/inc/
+MP_CFLAGS += -I$(TOP_DIR)/$(MICROPY_DIR)/ports/stm32/usbdev/class/inc/
+MP_CFLAGS += -I$(MP_BOARD_CONFIG_DIR)
-CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/
-CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/py/
-CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/nn/
-CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/img/
-CFLAGS += -I$(OMV_BOARD_CONFIG_DIR)
-CFLAGS += -I$(TOP_DIR)/$(LEPTON_DIR)/include/
-CFLAGS += -I$(TOP_DIR)/$(WINC1500_DIR)/include/
+OMV_CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/
+OMV_CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/py/
+OMV_CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/nn/
+OMV_CFLAGS += -I$(TOP_DIR)/$(OMV_DIR)/img/
+OMV_CFLAGS += -I$(OMV_BOARD_CONFIG_DIR)
+OMV_CFLAGS += -I$(TOP_DIR)/$(LEPTON_DIR)/include/
+OMV_CFLAGS += -I$(TOP_DIR)/$(WINC1500_DIR)/include/
+
+WEBCAM_CFLAGS = $(CFLAGS)
+WEBCAM_CFLAGS += -I$(OMV_BOARD_CONFIG_DIR)
+WEBCAM_CFLAGS += -I$(TOP_DIR)/$(WEBCAM_DIR)/include/
+
+BOOTLDR_CFLAGS = $(CFLAGS)
+BOOTLDR_CFLAGS += -I$(OMV_BOARD_CONFIG_DIR)
+BOOTLDR_CFLAGS += -I$(TOP_DIR)/$(BOOTLDR_DIR)/include/
+
+CFLAGS += $(ST_CFLAGS) $(MP_CFLAGS) $(OMV_CFLAGS)
# Linker Flags
LDFLAGS = -mcpu=$(CPU) -mabi=aapcs-linux -mthumb -mfpu=$(FPU) -mfloat-abi=hard\
-nostdlib -Wl,--gc-sections -Wl,-T$(BUILD)/stm32fxxx.lds
# Linker Flags
-BOOT_LDFLAGS = -mcpu=$(CPU) -mabi=aapcs-linux -mthumb -mfpu=$(FPU) -mfloat-abi=hard\
- -nostdlib -Wl,--gc-sections -Wl,-T$(BUILD)/$(BOOT_DIR)/stm32fxxx.lds
+BOOTLDR_LDFLAGS = -mcpu=$(CPU) -mabi=aapcs-linux -mthumb -mfpu=$(FPU) -mfloat-abi=hard\
+ -nostdlib -Wl,--gc-sections -Wl,-T$(BUILD)/$(BOOTLDR_DIR)/stm32fxxx.lds
+
+# Linker Flags
+WEBCAM_LDFLAGS = -mcpu=$(CPU) -mabi=aapcs-linux -mthumb -mfpu=$(FPU) -mfloat-abi=hard\
+ -nostdlib -Wl,--gc-sections -Wl,-T$(BUILD)/$(WEBCAM_DIR)/stm32fxxx.lds
#------------- Libraries ----------------#
FIRM_OBJ += $(wildcard $(BUILD)/$(CMSIS_DIR)/src/dsp/CommonTables/*.o)
@@ -389,14 +404,51 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(MICROPY_DIR)/drivers/,\
)
# Bootloader object files
-BOOT_OBJ += $(wildcard $(BUILD)/$(BOOT_DIR)/src/*.o)
+BOOT_OBJ += $(wildcard $(BUILD)/$(BOOTLDR_DIR)/src/*.o)
BOOT_OBJ += $(wildcard $(BUILD)/$(STHAL_DIR)/src/*.o)
-
BOOT_OBJ += $(addprefix $(BUILD)/$(CMSIS_DIR)/src/st/,\
$(STARTUP).o \
system_stm32fxxx.o \
)
+# Webcam object files
+WEBCAM_OBJ += $(wildcard $(BUILD)/$(WEBCAM_DIR)/src/*.o)
+WEBCAM_OBJ += $(wildcard $(BUILD)/$(STHAL_DIR)/src/*.o)
+WEBCAM_OBJ += $(addprefix $(BUILD)/$(CMSIS_DIR)/src/st/,\
+ $(STARTUP).o \
+ system_stm32fxxx.o \
+ )
+
+WEBCAM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/, \
+ fb_alloc.o \
+ framebuffer.o \
+ array.o \
+ cambus.o \
+ ov9650.o \
+ ov2640.o \
+ ov7725.o \
+ mt9v034.o \
+ lepton.o \
+ sensor.o \
+ stm32fxxx_hal_msp.o \
+ soft_i2c.o \
+ mutex.o \
+ trace.o \
+ )
+
+WEBCAM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/img/,\
+ lab_tab.o \
+ xyz_tab.o \
+ yuv_tab.o \
+ rainbow_tab.o \
+ rgb2rgb_tab.o \
+ invariant_tab.o \
+ jpeg.o \
+ fmath.o \
+ imlib.o \
+ )
+
+WEBCAM_OBJ += $(wildcard $(BUILD)/$(LEPTON_DIR)/src/*.o)
###################################################
#Export Variables
export Q
@@ -422,7 +474,10 @@ $(BUILD):
$(MKDIR) -p $@
BOOTLOADER_OBJS: FIRMWARE_OBJS
- $(MAKE) -C $(BOOT_DIR) BUILD=$(BUILD)/$(BOOT_DIR)
+ $(MAKE) -C $(BOOTLDR_DIR) BUILD=$(BUILD)/$(BOOTLDR_DIR) CFLAGS="$(BOOTLDR_CFLAGS) -MMD"
+
+WEBCAM_OBJS: FIRMWARE_OBJS
+ $(MAKE) -C $(WEBCAM_DIR) BUILD=$(BUILD)/$(WEBCAM_DIR) CFLAGS="$(WEBCAM_CFLAGS) -MMD"
FIRMWARE_OBJS:
$(MAKE) -C $(CMSIS_DIR) BUILD=$(BUILD)/$(CMSIS_DIR) CFLAGS="$(CFLAGS) -fno-strict-aliasing -MMD"
@@ -443,14 +498,21 @@ $(FIRMWARE): FIRMWARE_OBJS
# once without padding, to generate the bootloader.dfu file, and once with padding
# up to the main fw image (MAIN_APP_ADDR), to generate a contiguous firmware.bin image.
$(BOOTLOADER): FIRMWARE_OBJS BOOTLOADER_OBJS
- $(CPP) -P -E -I$(OMV_BOARD_CONFIG_DIR) $(BOOT_DIR)/stm32fxxx.ld.S > $(BUILD)/$(BOOT_DIR)/stm32fxxx.lds
- $(CC) $(BOOT_LDFLAGS) $(BOOT_OBJ) -o $(FW_DIR)/$(BOOTLOADER).elf
+ $(CPP) -P -E -I$(OMV_BOARD_CONFIG_DIR) $(BOOTLDR_DIR)/stm32fxxx.ld.S > $(BUILD)/$(BOOTLDR_DIR)/stm32fxxx.lds
+ $(CC) $(BOOTLDR_LDFLAGS) $(BOOT_OBJ) -o $(FW_DIR)/$(BOOTLOADER).elf
$(OBJCOPY) -Obinary $(FW_DIR)/$(BOOTLOADER).elf $(FW_DIR)/$(BOOTLOADER).bin
$(PYTHON) $(MKDFU) -b 0x08000000:$(FW_DIR)/$(BOOTLOADER).bin $(FW_DIR)/$(BOOTLOADER).dfu
$(OBJCOPY) -Obinary --pad-to=$(MAIN_APP_ADDR) --gap-fill=0xFF $(FW_DIR)/$(BOOTLOADER).elf $(FW_DIR)/$(BOOTLOADER).bin
+# This target generates the webcam firmware.
+$(WEBCAM): FIRMWARE_OBJS WEBCAM_OBJS
+ $(CPP) -P -E -I$(OMV_BOARD_CONFIG_DIR) $(WEBCAM_DIR)/stm32fxxx.ld.S > $(BUILD)/$(WEBCAM_DIR)/stm32fxxx.lds
+ $(CC) $(WEBCAM_LDFLAGS) $(WEBCAM_OBJ) -o $(FW_DIR)/$(WEBCAM).elf
+ $(OBJCOPY) -Obinary $(FW_DIR)/$(WEBCAM).elf $(FW_DIR)/$(WEBCAM).bin
+ $(PYTHON) $(MKDFU) -b $(MAIN_APP_ADDR):$(FW_DIR)/$(WEBCAM).bin $(FW_DIR)/$(WEBCAM).dfu
+
# This target generates a combined bootloader+main firmware image.
-$(OPENMV): $(BOOTLOADER) $(FIRMWARE) | $(BUILD)
+$(OPENMV): $(BOOTLOADER) $(WEBCAM) $(FIRMWARE) | $(BUILD)
$(CAT) $(FW_DIR)/$(BOOTLOADER).bin $(FW_DIR)/$(FIRMWARE).bin > $(FW_DIR)/$(OPENMV).bin
$(PYTHON) $(MKDFU) -b 0x08000000:$(FW_DIR)/$(BOOTLOADER).bin -b $(MAIN_APP_ADDR):$(FW_DIR)/$(FIRMWARE).bin $(FW_DIR)/$(OPENMV).dfu
$(SIZE) $(FW_DIR)/$(BOOTLOADER).elf
diff --git a/src/omv/fb_alloc.c b/src/omv/fb_alloc.c
index 708d3049b..bf8560625 100644
--- a/src/omv/fb_alloc.c
+++ b/src/omv/fb_alloc.c
@@ -13,7 +13,7 @@
extern char _fballoc;
static char *pointer = &_fballoc;
-NORETURN void fb_alloc_fail()
+__weak NORETURN void fb_alloc_fail()
{
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError,
"Out of fast Frame Buffer Stack Memory!"
diff --git a/src/webcam/Makefile b/src/webcam/Makefile
new file mode 100755
index 000000000..7f1e13956
--- /dev/null
+++ b/src/webcam/Makefile
@@ -0,0 +1,18 @@
+# Sources
+SRCS = $(wildcard src/*.c)
+OBJS = $(addprefix $(BUILD)/, $(SRCS:.c=.o))
+OBJ_DIRS = $(sort $(dir $(OBJS)))
+
+all: | $(OBJ_DIRS) $(OBJS)
+$(OBJ_DIRS):
+ $(MKDIR) -p $@
+
+$(BUILD)/%.o : %.c
+ $(ECHO) "CC $<"
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(BUILD)/%.o : %.s
+ $(ECHO) "AS $<"
+ $(AS) $(AFLAGS) $< -o $@
+
+-include $(OBJS:%.o=%.d)
diff --git a/src/webcam/include/stm32fxxx_it.h b/src/webcam/include/stm32fxxx_it.h
new file mode 100644
index 000000000..965542649
--- /dev/null
+++ b/src/webcam/include/stm32fxxx_it.h
@@ -0,0 +1,74 @@
+/**
+ ******************************************************************************
+ * @file USB_Device/CDC_Standalone/Inc/stm32f4xx_it.h
+ * @author MCD Application Team
+ * @version V1.2.2
+ * @date 25-May-2015
+ * @brief This file contains the headers of the interrupt handlers.
+ ******************************************************************************
+ * @attention
+ *
+ *
© COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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_IT_H
+#define __STM32F4xx_IT_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void SVC_Handler(void);
+void DebugMon_Handler(void);
+void PendSV_Handler(void);
+void SysTick_Handler(void);
+#ifdef USE_USB_FS
+void OTG_FS_IRQHandler(void);
+#else
+void OTG_HS_IRQHandler(void);
+#endif
+void USARTx_DMA_TX_IRQHandler(void);
+void USARTx_IRQHandler(void);
+void TIMx_IRQHandler(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_IT_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/include/usbd_conf.h b/src/webcam/include/usbd_conf.h
new file mode 100644
index 000000000..0b24c7696
--- /dev/null
+++ b/src/webcam/include/usbd_conf.h
@@ -0,0 +1,81 @@
+/**
+ ******************************************************************************
+ * @file USB_Device/CDC_Standalone/Inc/usbd_conf.h
+ * @author MCD Application Team
+ * @version V1.2.2
+ * @date 25-May-2015
+ * @brief General low level driver configuration
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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
+
+/* Includes ------------------------------------------------------------------*/
+#include STM32_HAL_H
+#include
+#include
+#include
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Common Config */
+#define USBD_MAX_NUM_INTERFACES 1
+#define USBD_MAX_NUM_CONFIGURATION 1
+#define USBD_MAX_STR_DESC_SIZ 512
+#define USBD_SUPPORT_USER_STRING 0
+#define USBD_SELF_POWERED 1
+#define USBD_DEBUG_LEVEL 0
+
+/* #define for FS and HS identification */
+#define DEVICE_FS 0
+#define DEVICE_HS 1
+
+/* 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
+
+/* Exported functions ------------------------------------------------------- */
+
+#endif /* __USBD_CONF_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/include/usbd_core.h b/src/webcam/include/usbd_core.h
new file mode 100644
index 000000000..c78c7b363
--- /dev/null
+++ b/src/webcam/include/usbd_core.h
@@ -0,0 +1,159 @@
+/**
+ ******************************************************************************
+ * @file usbd_core.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief Header file for usbd_core.c
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * 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_CORE_H
+#define __USBD_CORE_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+#include "usbd_def.h"
+#include "usbd_ioreq.h"
+#include "usbd_ctlreq.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_CORE
+ * @brief This file is the Header file for usbd_core.c file
+ * @{
+ */
+
+
+/** @defgroup USBD_CORE_Exported_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Exported_TypesDefinitions
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_CORE_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CORE_Exported_Variables
+ * @{
+ */
+#define USBD_SOF USBD_LL_SOF
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CORE_Exported_FunctionsPrototype
+ * @{
+ */
+USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id);
+USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass);
+
+USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+
+USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup);
+USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata);
+USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata);
+
+USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed);
+USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev);
+
+USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum);
+
+USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev);
+
+/* USBD Low Level Driver */
+USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev);
+USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev,
+ uint8_t ep_addr,
+ uint8_t ep_type,
+ uint16_t ep_mps);
+
+USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr);
+USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev,
+ uint8_t ep_addr,
+ uint8_t *pbuf,
+ uint16_t size);
+
+USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
+ uint8_t ep_addr,
+ uint8_t *pbuf,
+ uint16_t size);
+
+uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr);
+void USBD_LL_Delay (uint32_t Delay);
+
+/**
+ * @}
+ */
+
+#endif /* __USBD_CORE_H */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
+
diff --git a/src/webcam/include/usbd_ctlreq.h b/src/webcam/include/usbd_ctlreq.h
new file mode 100644
index 000000000..cd57fa828
--- /dev/null
+++ b/src/webcam/include/usbd_ctlreq.h
@@ -0,0 +1,106 @@
+/**
+ ******************************************************************************
+ * @file usbd_req.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header file for the usbd_req.c file
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * 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 __USB_REQUEST_H_
+#define __USB_REQUEST_H_
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_def.h"
+
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_REQ
+ * @brief header file for the usbd_ioreq.c file
+ * @{
+ */
+
+/** @defgroup USBD_REQ_Exported_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Exported_Types
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_REQ_Exported_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBD_REQ_Exported_Variables
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBD_REQ_Exported_FunctionsPrototype
+ * @{
+ */
+
+USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+
+
+void USBD_CtlError (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+
+void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata);
+
+void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
+/**
+ * @}
+ */
+
+#endif /* __USB_REQUEST_H_ */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/include/usbd_def.h b/src/webcam/include/usbd_def.h
new file mode 100644
index 000000000..e29ad2b26
--- /dev/null
+++ b/src/webcam/include/usbd_def.h
@@ -0,0 +1,323 @@
+/**
+ ******************************************************************************
+ * @file usbd_def.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief general defines for the usb device library
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * 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_DEF_H
+#define __USBD_DEF_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+
+/** @addtogroup STM32_USBD_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USB_DEF
+ * @brief general defines for the usb device library file
+ * @{
+ */
+
+/** @defgroup USB_DEF_Exported_Defines
+ * @{
+ */
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+
+#define USB_LEN_DEV_QUALIFIER_DESC 0x0A
+#define USB_LEN_DEV_DESC 0x12
+#define USB_LEN_CFG_DESC 0x09
+#define USB_LEN_IF_DESC 0x09
+#define USB_LEN_EP_DESC 0x07
+#define USB_LEN_OTG_DESC 0x03
+#define USB_LEN_LANGID_STR_DESC 0x04
+#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09
+
+#define USBD_IDX_LANGID_STR 0x00
+#define USBD_IDX_MFC_STR 0x01
+#define USBD_IDX_PRODUCT_STR 0x02
+#define USBD_IDX_SERIAL_STR 0x03
+#define USBD_IDX_CONFIG_STR 0x04
+#define USBD_IDX_INTERFACE_STR 0x05
+
+#define USB_REQ_TYPE_STANDARD 0x00
+#define USB_REQ_TYPE_CLASS 0x20
+#define USB_REQ_TYPE_VENDOR 0x40
+#define USB_REQ_TYPE_MASK 0x60
+
+#define USB_REQ_RECIPIENT_DEVICE 0x00
+#define USB_REQ_RECIPIENT_INTERFACE 0x01
+#define USB_REQ_RECIPIENT_ENDPOINT 0x02
+#define USB_REQ_RECIPIENT_MASK 0x03
+
+#define USB_REQ_GET_STATUS 0x00
+#define USB_REQ_CLEAR_FEATURE 0x01
+#define USB_REQ_SET_FEATURE 0x03
+#define USB_REQ_SET_ADDRESS 0x05
+#define USB_REQ_GET_DESCRIPTOR 0x06
+#define USB_REQ_SET_DESCRIPTOR 0x07
+#define USB_REQ_GET_CONFIGURATION 0x08
+#define USB_REQ_SET_CONFIGURATION 0x09
+#define USB_REQ_GET_INTERFACE 0x0A
+#define USB_REQ_SET_INTERFACE 0x0B
+#define USB_REQ_SYNCH_FRAME 0x0C
+
+#define USB_DESC_TYPE_DEVICE 1
+#define USB_DESC_TYPE_CONFIGURATION 2
+#define USB_DESC_TYPE_STRING 3
+#define USB_DESC_TYPE_INTERFACE 4
+#define USB_DESC_TYPE_ENDPOINT 5
+#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
+#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
+
+
+#define USB_CONFIG_REMOTE_WAKEUP 2
+#define USB_CONFIG_SELF_POWERED 1
+
+#define USB_FEATURE_EP_HALT 0
+#define USB_FEATURE_REMOTE_WAKEUP 1
+#define USB_FEATURE_TEST_MODE 2
+
+
+#define USB_HS_MAX_PACKET_SIZE 512
+#define USB_FS_MAX_PACKET_SIZE 64
+#define USB_MAX_EP0_SIZE 64
+
+/* Device Status */
+#define USBD_STATE_DEFAULT 1
+#define USBD_STATE_ADDRESSED 2
+#define USBD_STATE_CONFIGURED 3
+#define USBD_STATE_SUSPENDED 4
+
+
+/* EP0 State */
+#define USBD_EP0_IDLE 0
+#define USBD_EP0_SETUP 1
+#define USBD_EP0_DATA_IN 2
+#define USBD_EP0_DATA_OUT 3
+#define USBD_EP0_STATUS_IN 4
+#define USBD_EP0_STATUS_OUT 5
+#define USBD_EP0_STALL 6
+
+#define USBD_EP_TYPE_CTRL 0
+#define USBD_EP_TYPE_ISOC 1
+#define USBD_EP_TYPE_BULK 2
+#define USBD_EP_TYPE_INTR 3
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_DEF_Exported_TypesDefinitions
+ * @{
+ */
+
+typedef struct usb_setup_req
+{
+
+ uint8_t bmRequest;
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+}USBD_SetupReqTypedef;
+
+struct _USBD_HandleTypeDef;
+
+typedef struct _Device_cb
+{
+ uint8_t (*Init) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);
+ uint8_t (*DeInit) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);
+ /* Control Endpoints*/
+ uint8_t (*Setup) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req);
+ uint8_t (*EP0_TxSent) (struct _USBD_HandleTypeDef *pdev );
+ uint8_t (*EP0_RxReady) (struct _USBD_HandleTypeDef *pdev );
+ /* Class Specific Endpoints*/
+ uint8_t (*DataIn) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
+ uint8_t (*DataOut) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
+ uint8_t (*SOF) (struct _USBD_HandleTypeDef *pdev);
+ uint8_t (*IsoINIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
+ uint8_t (*IsoOUTIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);
+
+ uint8_t *(*GetHSConfigDescriptor)(uint16_t *length);
+ uint8_t *(*GetFSConfigDescriptor)(uint16_t *length);
+ uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
+ uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length);
+#if (USBD_SUPPORT_USER_STRING == 1)
+ uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev ,uint8_t index, uint16_t *length);
+#endif
+
+} USBD_ClassTypeDef;
+
+/* Following USB Device Speed */
+typedef enum
+{
+ USBD_SPEED_HIGH = 0,
+ USBD_SPEED_FULL = 1,
+ USBD_SPEED_LOW = 2,
+}USBD_SpeedTypeDef;
+
+/* Following USB Device status */
+typedef enum {
+ USBD_OK = 0,
+ USBD_BUSY,
+ USBD_FAIL,
+}USBD_StatusTypeDef;
+
+/* USB Device descriptors structure */
+typedef struct
+{
+ uint8_t *(*GetDeviceDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
+ uint8_t *(*GetLangIDStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
+ uint8_t *(*GetManufacturerStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
+ uint8_t *(*GetProductStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
+ uint8_t *(*GetSerialStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
+ uint8_t *(*GetConfigurationStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
+ uint8_t *(*GetInterfaceStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
+} USBD_DescriptorsTypeDef;
+
+/* USB Device handle structure */
+typedef struct
+{
+ uint32_t status;
+ uint32_t total_length;
+ uint32_t rem_length;
+ uint32_t maxpacket;
+} USBD_EndpointTypeDef;
+
+/* USB Device handle structure */
+typedef struct _USBD_HandleTypeDef
+{
+ uint8_t id;
+ uint32_t dev_config;
+ uint32_t dev_default_config;
+ uint32_t dev_config_status;
+ USBD_SpeedTypeDef dev_speed;
+ USBD_EndpointTypeDef ep_in[15];
+ USBD_EndpointTypeDef ep_out[15];
+ uint32_t ep0_state;
+ uint32_t ep0_data_len;
+ uint8_t dev_state;
+ uint8_t dev_old_state;
+ uint8_t dev_address;
+ uint8_t dev_connection_status;
+ uint8_t dev_test_mode;
+ uint32_t dev_remote_wakeup;
+
+ USBD_SetupReqTypedef request;
+ USBD_DescriptorsTypeDef *pDesc;
+ USBD_ClassTypeDef *pClass;
+ void *pClassData;
+ void *pUserData;
+ void *pData;
+} USBD_HandleTypeDef;
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_DEF_Exported_Macros
+ * @{
+ */
+#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \
+ (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8))
+
+#define LOBYTE(x) ((uint8_t)(x & 0x00FF))
+#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8))
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+
+#if defined ( __GNUC__ )
+ #ifndef __weak
+ #define __weak __attribute__((weak))
+ #endif /* __weak */
+ #ifndef __packed
+ #define __packed __attribute__((__packed__))
+ #endif /* __packed */
+#endif /* __GNUC__ */
+
+
+/* In HS mode and when the DMA is used, all variables and data structures dealing
+ with the DMA during the transaction process should be 4-bytes aligned */
+
+#if defined (__GNUC__) /* GNU Compiler */
+ #define __ALIGN_END __attribute__ ((aligned (4)))
+ #define __ALIGN_BEGIN
+#else
+ #define __ALIGN_END
+ #if defined (__CC_ARM) /* ARM Compiler */
+ #define __ALIGN_BEGIN __align(4)
+ #elif defined (__ICCARM__) /* IAR Compiler */
+ #define __ALIGN_BEGIN
+ #elif defined (__TASKING__) /* TASKING Compiler */
+ #define __ALIGN_BEGIN __align(4)
+ #endif /* __CC_ARM */
+#endif /* __GNUC__ */
+
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_DEF_Exported_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_DEF_Exported_FunctionsPrototype
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+#endif /* __USBD_DEF_H */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/include/usbd_desc.h b/src/webcam/include/usbd_desc.h
new file mode 100644
index 000000000..32daeaefa
--- /dev/null
+++ b/src/webcam/include/usbd_desc.h
@@ -0,0 +1,34 @@
+/**
+ ******************************************************************************
+ * @file USB_Device/CDC_Standalone/Inc/usbd_desc.h
+ * @author MCD Application Team
+ * @version V1.2.2
+ * @date 25-May-2015
+ * @brief Header for usbd_desc.c module
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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.
+ *
+ ******************************************************************************
+ */
+#ifndef __USBD_DESC_H
+#define __USBD_DESC_H
+
+#include "usbd_def.h"
+
+extern USBD_DescriptorsTypeDef FS_Desc;
+
+#endif /* __USBD_DESC_H */
diff --git a/src/webcam/include/usbd_ioreq.h b/src/webcam/include/usbd_ioreq.h
new file mode 100644
index 000000000..ab83bc086
--- /dev/null
+++ b/src/webcam/include/usbd_ioreq.h
@@ -0,0 +1,121 @@
+/**
+ ******************************************************************************
+ * @file usbd_ioreq.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header file for the usbd_ioreq.c file
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * 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_IOREQ_H_
+#define __USBD_IOREQ_H_
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_def.h"
+#include "usbd_core.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_IOREQ
+ * @brief header file for the usbd_ioreq.c file
+ * @{
+ */
+
+/** @defgroup USBD_IOREQ_Exported_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Exported_Types
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_IOREQ_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_IOREQ_Exported_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype
+ * @{
+ */
+
+USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev,
+ uint8_t *buf,
+ uint16_t len);
+
+USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf,
+ uint16_t len);
+
+USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf,
+ uint16_t len);
+
+USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf,
+ uint16_t len);
+
+USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev);
+
+USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev);
+
+uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev ,
+ uint8_t epnum);
+
+/**
+ * @}
+ */
+
+#endif /* __USBD_IOREQ_H_ */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/include/usbd_types.h b/src/webcam/include/usbd_types.h
new file mode 100644
index 000000000..5ee57d741
--- /dev/null
+++ b/src/webcam/include/usbd_types.h
@@ -0,0 +1,65 @@
+#ifndef __USBD_TYPES_H
+#define __USBD_TYPES_H
+
+#define USB_REQ_READ_MASK 0x80
+
+/* USB_DT_CONFIG: Configuration descriptor information. */
+struct usb_config_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+
+ uint16_t wTotalLength;
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t bMaxPower;
+} __attribute__ ((packed));
+
+#define USB_DT_CONFIG_SIZE 9
+
+/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
+struct usb_interface_assoc_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+} __attribute__ ((packed));
+
+#define USB_DT_INTERFACE_ASSOC_SIZE 8
+
+/* USB_DT_INTERFACE: Interface descriptor */
+struct usb_interface_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+} __attribute__ ((packed));
+
+#define USB_DT_INTERFACE_SIZE 9
+
+/* USB_DT_ENDPOINT: Endpoint descriptor */
+struct usb_endpoint_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+} __attribute__ ((packed));
+
+#define USB_DT_ENDPOINT_SIZE 7
+
+#endif
\ No newline at end of file
diff --git a/src/webcam/include/usbd_uvc.h b/src/webcam/include/usbd_uvc.h
new file mode 100644
index 000000000..19931300f
--- /dev/null
+++ b/src/webcam/include/usbd_uvc.h
@@ -0,0 +1,372 @@
+/**
+ ******************************************************************************
+ * @file usbd_cdc.h
+ * @author MCD Application Team
+ * @version V2.4.1
+ * @date 19-June-2015
+ * @brief header file for the usbd_cdc.c file.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2015 STMicroelectronics
+ *
+ * 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 __USB_UVC_H
+#define __USB_UVC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_ioreq.h"
+#include "uvc.h"
+
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup usbd_cdc
+ * @brief This file is the Header file for usbd_cdc.c
+ * @{
+ */
+
+
+/** @defgroup usbd_cdc_Exported_Defines
+ * @{
+ */
+
+// USB Video device class specification version 1.10
+#ifdef UVC_1_1
+#define UVC_VERSION 0x0110 // UVC 1.1
+#else
+#define UVC_VERSION 0x0100 // UVC 1.0
+#endif
+
+#define UVC_IN_EP 0x81 /* EP1 for data IN */
+#define UVC_CMD_EP 0x82 /* EP2 for UVC commands */
+#define VIDEO_PACKET_SIZE ((unsigned int)(960 + 2))
+#define VIDEO_MAX_SETUP_PACKET_SIZE ((unsigned int)(1024))
+#define CMD_PACKET_SIZE ((unsigned int)(8))
+
+#define CAM_FPS 120
+
+enum CUST_COMTROL_IDS {
+ CUST_CONTROL_COMMAND=0,
+ CUST_CONTROL_GET,
+ CUST_CONTROL_SET,
+ CUST_CONTROL_RUN,
+ CUST_CONTROL_DIRECT_WRITE,
+ CUST_CONTROL_DIRECT_READ,
+ CUST_CONTROL_END
+};
+
+enum _vs_fmt_indexes {
+ VS_FMT_INDEX_YUYV = 1,
+ VS_FMT_INDEX_GREY,
+ VS_FMT_INDEX_RGB565,
+};
+
+#define VS_NUM_FORMATS 3
+
+enum _vs_fmt_size {
+ VS_FMT_SIZE_YUYV = 16,
+ VS_FMT_SIZE_GREY = 8,
+ VS_FMT_SIZE_RGB565 = 16,
+};
+
+#define VS_FMT_GUID_NONE \
+ '0', '0', '0', '0', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define VS_FMT_GUID_GREY \
+ 'Y', '8', ' ', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+
+#define VS_FMT_GUID_Y16 \
+ 'Y', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+
+#define VS_FMT_GUID_YUYV \
+ 'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+
+#define VS_FMT_GUID_NV12 \
+ 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+
+#define VS_FMT_GUID_YU12 \
+ 'I', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+
+#define VS_FMT_GUID_BGR3 \
+ 0x7d, 0xeb, 0x36, 0xe4, 0x4f, 0x52, 0xce, 0x11, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70
+
+#define VS_FMT_GUID_RGB565 \
+ 'R', 'G', 'B', 'P', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+
+#define VS_FMT_INDEX(NAME) VS_FMT_INDEX_ ## NAME
+#define VS_FMT_GUID(NAME) { VS_FMT_GUID_ ## NAME }
+#define VS_FMT_SIZE(NAME) VS_FMT_SIZE_ ## NAME
+
+enum _vs_frame_indexes {
+ VS_FRAME_INDEX_1 = 1,
+ VS_FRAME_INDEX_2 = 2,
+ VS_FRAME_INDEX_3 = 3,
+ VS_FRAME_INDEX_4 = 4,
+};
+
+#define VS_FRAME_INDEX(NAME) VS_FRAME_INDEX_ ## NAME
+
+#define USB_UVC_VCIF_NUM 0
+#define USB_UVC_VSIF_NUM (char)1
+
+#define VIDEO_TOTAL_IF_NUM 2
+#define WINDOWS_MAX_CONTROLS 31
+
+typedef enum _vs_terminal_id {
+ VC_INPUT_TERMINAL_ID = 1,
+ VC_CONTROL_PU_ID,
+ VC_CONTROL_XU_LEP_AGC_ID,
+ VC_CONTROL_XU_LEP_OEM_ID,
+ VC_CONTROL_XU_LEP_RAD_ID,
+ VC_CONTROL_XU_LEP_SYS_ID,
+ VC_CONTROL_XU_LEP_VID_ID,
+ VC_CONTROL_XU_LEP_AGC_2_ID = VC_CONTROL_XU_LEP_AGC_ID + 0x10,
+ VC_CONTROL_XU_LEP_OEM_2_ID,
+ VC_CONTROL_XU_LEP_RAD_2_ID,
+ VC_CONTROL_XU_LEP_SYS_2_ID,
+ VC_CONTROL_XU_LEP_VID_2_ID,
+ VC_CONTROL_XU_LEP_CUST_ID = 0xfe,
+ VC_OUTPUT_TERMINAL_ID = 0xff
+} VC_TERMINAL_ID;
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Exported_TypesDefinitions
+ * @{
+ */
+
+
+typedef struct _USBD_UVC_Itf
+{
+ int8_t (* Init) (void);
+ int8_t (* DeInit) (void);
+ int8_t (* Control) (uint8_t, uint8_t * , uint16_t, uint16_t, uint16_t);
+ int8_t (* VS_CtrlGet) (uint8_t, uint8_t * , uint16_t, uint16_t, uint16_t);
+ int8_t (* VS_CtrlSet) (uint8_t, uint8_t * , uint16_t, uint16_t, uint16_t);
+ int8_t (* ControlGet) (VC_TERMINAL_ID, uint8_t, uint8_t * , uint16_t, uint16_t, uint16_t);
+ int8_t (* ControlSet) (VC_TERMINAL_ID, uint8_t, uint8_t * , uint16_t, uint16_t, uint16_t);
+ int8_t (* Receive) (uint8_t *, uint32_t *);
+
+}USBD_UVC_ItfTypeDef;
+
+
+typedef struct
+{
+ uint32_t data[VIDEO_MAX_SETUP_PACKET_SIZE/4]; /* Force 32bits alignment */
+ uint8_t CmdOpCode;
+ uint16_t CmdLength;
+ uint16_t CmdIndex;
+ uint16_t CmdValue;
+ uint8_t *RxBuffer;
+ uint8_t *TxBuffer;
+ uint32_t RxLength;
+ uint32_t TxLength;
+
+ __IO uint32_t TxState;
+ __IO uint32_t RxState;
+}
+USBD_UVC_HandleTypeDef;
+
+#if 0
+struct uvc_input_terminal_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType; /* : CS_INTERFACE */
+ uint8_t bDescriptorSubtype; /* VC_INPUT_TERMINAL descriptor subtype */
+ uint8_t bTerminalID; /* Constant uniquely identifying the Terminal within the video function.
+ This value is used in all requests to address this Terminal. */
+ uint8_t[2] wTerminalType; /* ITT_MEDIA_TRANSPORT_INPUT */
+ uint8_t bAssocTerminal; /* ID of the Output Terminal to which this Input Terminal is associated. */
+ uint8_t iTerminal; /* */
+ uint8_t bControlSize; /* Size of the bmControls field, in bytes: n=1 */
+ uint8_t[1] bmControls; /*
+ A bit set to 1 indicates that the mentioned Control is supported for the video stream.
+ D0: Transport Control
+ D1: Absolute Track Number Control
+ D2: Media Information
+ D3: Time Code Information D4...(n*8-1): Reserved
+ */
+ uint8_t bTransportModeSize; /* Size of the bmTransportModes field, in bytes: m=4 */
+ uint8_t[4] bmTransportModes; /*
+ A bit set to 1 indicates that the mentioned Transport mode is supported.
+ D0: Play Forward
+ D1: Pause
+ D2: Rewind
+ D3: Fast Forward
+ D4: High Speed Rewind
+ D5: Stop
+ D6: Eject
+ D7: Play Next Frame
+ D8: Play Slowest Forward
+ D9: Play Slow Forward 4
+ D10: Play Slow Forward 3
+ D11: Play Slow Forward 2
+ D12: Play Slow Forward 1
+ D13: Play X1
+ D14: Play Fast Forward 1
+ D15: Play Fast Forward 2
+ D16: Play Fast Forward 3
+ D17: Play Fast Forward 4
+ D18: Play Fastest Forward
+ D19: Play Previous Frame
+ D20: Play Slowest Reverse
+ D21: Play Slow Reverse 4
+ D22: Play Slow Reverse 3
+ D23: Play Slow Reverse 2
+ D24: Play Slow Reverse 1
+ D25: Play X1 Reverse
+ D26: Play Fast Reverse 1
+ D27: Play Fast Reverse 2
+ D28: Play Fast Reverse 3
+ D29: Play Fast Reverse 4
+ D30: Play Fastest Reverse
+ D31: Record StateStart
+ */
+};
+#endif
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CORE_Exported_Macros
+ * @{
+ */
+
+#define SIZEOF_M(type, member) sizeof(((type *)0)->member)
+
+#define UVC_DATA_HS_IN_PACKET_SIZE VIDEO_PACKET_SIZE
+#define UVC_DATA_HS_OUT_PACKET_SIZE VIDEO_PACKET_SIZE
+
+#define UVC_DATA_FS_IN_PACKET_SIZE VIDEO_PACKET_SIZE
+#define UVC_DATA_FS_OUT_PACKET_SIZE VIDEO_PACKET_SIZE
+
+#define UVC_LEN_IF_ASSOCIATION_DESC (char)8
+
+#define UVC_VS_INTERFACE_INPUT_HEADER_DESC_SIZE(a,b) (char) (13+a*b)
+
+#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8
+#define USB_OTG_DESCRIPTOR_TYPE 9
+#define USB_DEBUG_DESCRIPTOR_TYPE 10
+#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 11
+
+/* bmAttributes in Configuration Descriptor */
+#define USB_CONFIG_POWERED_MASK 0xC0
+#define USB_CONFIG_BUS_POWERED 0x80
+
+/* bMaxPower in Configuration Descriptor */
+#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
+#define MAX_FRAME_SIZE(width, height, bits_per_pixel) ((unsigned long)((width*height*bits_per_pixel)>>3))
+#define MIN_BIT_RATE(width, height, bits_per_pixel) ((unsigned long)(width*height*bits_per_pixel*CAM_FPS))
+#define MAX_BIT_RATE(width, height, bits_per_pixel) ((unsigned long)(width*height*bits_per_pixel*CAM_FPS))
+#define INTERVAL ((unsigned long)(10000000/CAM_FPS))
+
+/* bEndpointAddress in Endpoint Descriptor */
+#define USB_ENDPOINT_DIRECTION_MASK 0x80
+#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
+#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
+
+#define UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(FMT_NAME, NUM_FRAME_DESCS) { \
+ .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE, \
+ .bDescriptorType = UVC_CS_INTERFACE, /* CS_INTERFACE */ \
+ .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED, /* VS_FORMAT_UNCOMPRESSED subtype */ \
+ .bFormatIndex = VS_FMT_INDEX(FMT_NAME), /* First format descriptor */ \
+ .bNumFrameDescriptors = NUM_FRAME_DESCS, /* One frame descriptor for this format follows. */ \
+ .guidFormat = VS_FMT_GUID(FMT_NAME), /* */ \
+ .bBitsPerPixel = VS_FMT_SIZE(FMT_NAME), /* Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2, 12 for nv12... */ \
+ .bDefaultFrameIndex = 0x01, /* Default frame index is 1. */ \
+ .bAspectRatioX = 0x00, /* Non-interlaced stream not required. */ \
+ .bAspectRatioY = 0x00, /* Non-interlaced stream not required. */ \
+ .bmInterlaceFlags = 0x00, /* Non-interlaced stream */ \
+ .bCopyProtect = 0x00, /* No restrictions imposed on the duplication of this video stream. */ \
+}
+
+#define UVC_FRAME_FORMAT(FRAME_INDEX, FMT_NAME, WIDTH, HEIGHT) { \
+ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), \
+ .bDescriptorType = UVC_CS_INTERFACE, /* CS_INTERFACE */ \
+ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, /* VS_FRAME_UNCOMPRESSED */ \
+ .bFrameIndex = FRAME_INDEX, /* First (and only) frame descriptor */ \
+ .bmCapabilities = 0x02, /* Still images using capture method 0 are supported at this frame setting.D1: Fixed frame-rate. */ \
+ .wWidth = WIDTH, /* Width of frame is 128 pixels. */ \
+ .wHeight = HEIGHT, /* Height of frame is 64 pixels. */ \
+ .dwMinBitRate = MIN_BIT_RATE(WIDTH,HEIGHT,VS_FMT_SIZE(FMT_NAME)), /* Min bit rate in bits/s */ \
+ .dwMaxBitRate = MAX_BIT_RATE(WIDTH,HEIGHT,VS_FMT_SIZE(FMT_NAME)), /* Max bit rate in bits/s */ \
+ .dwMaxVideoFrameBufferSize = MAX_FRAME_SIZE(WIDTH,HEIGHT,VS_FMT_SIZE(FMT_NAME)), /* Maximum video or still frame size, in bytes. */ \
+ .dwDefaultFrameInterval = INTERVAL, /* */ \
+ .bFrameIntervalType = 0x01, /* Continuous frame interval */ \
+ .dwFrameInterval = { INTERVAL }, /* 1,000,000 ns *100ns -> 10 FPS */ \
+}
+
+#define UVC_COLOR_MATCHING_DESCRIPTOR() { \
+ .bLength = UVC_DT_COLOR_MATCHING_SIZE, \
+ .bDescriptorType = UVC_CS_INTERFACE, /* CS_INTERFACE */ \
+ .bDescriptorSubType = UVC_VS_COLORFORMAT, /* VS_COLORFORMAT */ \
+ .bColorPrimaries = 0x01, /* 1: BT.709, sRGB (default) */ \
+ .bTransferCharacteristics = 0x01, /* 1: BT.709 (default) */ \
+ .bMatrixCoefficients = 0x04, /* 1: SMPTE 170M (BT.601) */ \
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_CORE_Exported_Variables
+ * @{
+ */
+
+extern USBD_ClassTypeDef USBD_UVC;
+#define USBD_UVC_CLASS &USBD_UVC
+/**
+ * @}
+ */
+
+/** @defgroup USB_CORE_Exported_Functions
+ * @{
+ */
+uint8_t USBD_UVC_RegisterInterface (USBD_HandleTypeDef *pdev,
+ USBD_UVC_ItfTypeDef *fops);
+
+uint8_t USBD_UVC_SetTxBuffer (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuff,
+ uint16_t length);
+
+uint8_t USBD_UVC_SetRxBuffer (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuff);
+
+uint8_t USBD_UVC_ReceivePacket (USBD_HandleTypeDef *pdev);
+
+uint8_t USBD_UVC_TransmitPacket (USBD_HandleTypeDef *pdev);
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USB_UVC_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/include/usbd_uvc_if.h b/src/webcam/include/usbd_uvc_if.h
new file mode 100644
index 000000000..be61cf04f
--- /dev/null
+++ b/src/webcam/include/usbd_uvc_if.h
@@ -0,0 +1,65 @@
+/**
+ ******************************************************************************
+ * @file : usbd_cdc_if.h
+ * @brief : Header for usbd_cdc_if file.
+ ******************************************************************************
+ * COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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 __USBD_UVC_IF_H
+#define __USBD_UVC_IF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_uvc.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported cariables --------------------------------------------------------*/
+extern USBD_UVC_ItfTypeDef USBD_Interface_fops_FS;
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+/** @defgroup USBD_UVC_IF_Exported_FunctionsPrototype
+ * @{
+ */
+uint8_t UVC_Transmit_FS(uint8_t* Buf, uint16_t Len);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_UVC_IF_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/include/uvc.h b/src/webcam/include/uvc.h
new file mode 100644
index 000000000..54be1ce8c
--- /dev/null
+++ b/src/webcam/include/uvc.h
@@ -0,0 +1,522 @@
+#ifndef __UVC_H
+#define __UVC_H
+
+/*----------------------------------------------------------------------------
+ * Definitions based on USB_Video_Class_1.1.pdf (www.usb.org)
+ *---------------------------------------------------------------------------*/
+
+/* --------------------------------------------------------------------------
+ * UVC constants
+ */
+
+/* A.1 Video Interface Class Code */
+#define UVC_CC_VIDEO 0x0E
+
+/* A.2. Video Interface Subclass Codes */
+#define UVC_SC_UNDEFINED 0x00
+#define UVC_SC_VIDEOCONTROL 0x01
+#define UVC_SC_VIDEOSTREAMING 0x02
+#define UVC_SC_VIDEO_INTERFACE_COLLECTION 0x03
+
+/* A.3. Video Interface Protocol Codes */
+#define UVC_PC_PROTOCOL_UNDEFINED 0x00
+
+/* A.4 Video Class-Specific Descriptor Types */
+#define UVC_CS_UNDEFINED 0x20
+#define UVC_CS_DEVICE 0x21
+#define UVC_CS_CONFIGURATION 0x22
+#define UVC_CS_STRING 0x23
+#define UVC_CS_INTERFACE 0x24
+#define UVC_CS_ENDPOINT 0x25
+
+/* A.5. Video Class-Specific VC Interface Descriptor Subtypes */
+#define UVC_VC_DESCRIPTOR_UNDEFINED 0x00
+#define UVC_VC_HEADER 0x01
+#define UVC_VC_INPUT_TERMINAL 0x02
+#define UVC_VC_OUTPUT_TERMINAL 0x03
+#define UVC_VC_SELECTOR_UNIT 0x04
+#define UVC_VC_PROCESSING_UNIT 0x05
+#define UVC_VC_EXTENSION_UNIT 0x06
+
+/* A.6. Video Class-Specific VS Interface Descriptor Subtypes */
+#define UVC_VS_UNDEFINED 0x00
+#define UVC_VS_INPUT_HEADER 0x01
+#define UVC_VS_OUTPUT_HEADER 0x02
+#define UVC_VS_STILL_IMAGE_FRAME 0x03
+#define UVC_VS_FORMAT_UNCOMPRESSED 0x04
+#define UVC_VS_FRAME_UNCOMPRESSED 0x05
+#define UVC_VS_FORMAT_MJPEG 0x06
+#define UVC_VS_FRAME_MJPEG 0x07
+#define UVC_VS_FORMAT_MPEG2TS 0x0a
+#define UVC_VS_FORMAT_DV 0x0c
+#define UVC_VS_COLORFORMAT 0x0d
+#define UVC_VS_FORMAT_FRAME_BASED 0x10
+#define UVC_VS_FRAME_FRAME_BASED 0x11
+#define UVC_VS_FORMAT_STREAM_BASED 0x12
+
+/* A.7. Video Class-Specific Endpoint Descriptor Subtypes */
+#define UVC_EP_UNDEFINED 0x00
+#define UVC_EP_GENERAL 0x01
+#define UVC_EP_ENDPOINT 0x02
+#define UVC_EP_INTERRUPT 0x03
+
+/* A.8. Video Class-Specific Request Codes */
+#define UVC_RC_UNDEFINED 0x00
+#define UVC_SET_CUR 0x01
+#define UVC_GET_CUR 0x81
+#define UVC_GET_MIN 0x82
+#define UVC_GET_MAX 0x83
+#define UVC_GET_RES 0x84
+#define UVC_GET_LEN 0x85
+#define UVC_GET_INFO 0x86
+#define UVC_GET_DEF 0x87
+
+/* A.9.1. VideoControl Interface Control Selectors */
+#define UVC_VC_CONTROL_UNDEFINED 0x00
+#define UVC_VC_VIDEO_POWER_MODE_CONTROL 0x01
+#define UVC_VC_REQUEST_ERROR_CODE_CONTROL 0x02
+
+/* A.9.2. Terminal Control Selectors */
+#define UVC_TE_CONTROL_UNDEFINED 0x00
+
+/* A.9.3. Selector Unit Control Selectors */
+#define UVC_SU_CONTROL_UNDEFINED 0x00
+#define UVC_SU_INPUT_SELECT_CONTROL 0x01
+
+/* A.9.4. Camera Terminal Control Selectors */
+#define UVC_CT_CONTROL_UNDEFINED 0x00
+#define UVC_CT_SCANNING_MODE_CONTROL 0x01
+#define UVC_CT_AE_MODE_CONTROL 0x02
+#define UVC_CT_AE_PRIORITY_CONTROL 0x03
+#define UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04
+#define UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05
+#define UVC_CT_FOCUS_ABSOLUTE_CONTROL 0x06
+#define UVC_CT_FOCUS_RELATIVE_CONTROL 0x07
+#define UVC_CT_FOCUS_AUTO_CONTROL 0x08
+#define UVC_CT_IRIS_ABSOLUTE_CONTROL 0x09
+#define UVC_CT_IRIS_RELATIVE_CONTROL 0x0a
+#define UVC_CT_ZOOM_ABSOLUTE_CONTROL 0x0b
+#define UVC_CT_ZOOM_RELATIVE_CONTROL 0x0c
+#define UVC_CT_PANTILT_ABSOLUTE_CONTROL 0x0d
+#define UVC_CT_PANTILT_RELATIVE_CONTROL 0x0e
+#define UVC_CT_ROLL_ABSOLUTE_CONTROL 0x0f
+#define UVC_CT_ROLL_RELATIVE_CONTROL 0x10
+#define UVC_CT_PRIVACY_CONTROL 0x11
+
+/* A.9.5. Processing Unit Control Selectors */
+#define UVC_PU_CONTROL_UNDEFINED 0x00
+#define UVC_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01
+#define UVC_PU_BRIGHTNESS_CONTROL 0x02
+#define UVC_PU_CONTRAST_CONTROL 0x03
+#define UVC_PU_GAIN_CONTROL 0x04
+#define UVC_PU_POWER_LINE_FREQUENCY_CONTROL 0x05
+#define UVC_PU_HUE_CONTROL 0x06
+#define UVC_PU_SATURATION_CONTROL 0x07
+#define UVC_PU_SHARPNESS_CONTROL 0x08
+#define UVC_PU_GAMMA_CONTROL 0x09
+#define UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a
+#define UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b
+#define UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c
+#define UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d
+#define UVC_PU_DIGITAL_MULTIPLIER_CONTROL 0x0e
+#define UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f
+#define UVC_PU_HUE_AUTO_CONTROL 0x10
+#define UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
+#define UVC_PU_ANALOG_LOCK_STATUS_CONTROL 0x12
+
+/* A.9.7. VideoStreaming Interface Control Selectors */
+#define UVC_VS_CONTROL_UNDEFINED 0x00
+#define UVC_VS_PROBE_CONTROL 0x01
+#define UVC_VS_COMMIT_CONTROL 0x02
+#define UVC_VS_STILL_PROBE_CONTROL 0x03
+#define UVC_VS_STILL_COMMIT_CONTROL 0x04
+#define UVC_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05
+#define UVC_VS_STREAM_ERROR_CODE_CONTROL 0x06
+#define UVC_VS_GENERATE_KEY_FRAME_CONTROL 0x07
+#define UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
+#define UVC_VS_SYNC_DELAY_CONTROL 0x09
+
+/* B.1. USB Terminal Types */
+#define UVC_TT_VENDOR_SPECIFIC 0x0100
+#define UVC_TT_STREAMING 0x0101
+
+/* B.2. Input Terminal Types */
+#define UVC_ITT_VENDOR_SPECIFIC 0x0200
+#define UVC_ITT_CAMERA 0x0201
+#define UVC_ITT_MEDIA_TRANSPORT_INPUT 0x0202
+
+/* B.3. Output Terminal Types */
+#define UVC_OTT_VENDOR_SPECIFIC 0x0300
+#define UVC_OTT_DISPLAY 0x0301
+#define UVC_OTT_MEDIA_TRANSPORT_OUTPUT 0x0302
+
+/* B.4. External Terminal Types */
+#define UVC_EXTERNAL_VENDOR_SPECIFIC 0x0400
+#define UVC_COMPOSITE_CONNECTOR 0x0401
+#define UVC_SVIDEO_CONNECTOR 0x0402
+#define UVC_COMPONENT_CONNECTOR 0x0403
+
+/* 2.4.2.2. Status Packet Type */
+#define UVC_STATUS_TYPE_CONTROL 1
+#define UVC_STATUS_TYPE_STREAMING 2
+
+/* 2.4.3.3. Payload Header Information */
+#define UVC_STREAM_EOH (1 << 7)
+#define UVC_STREAM_ERR (1 << 6)
+#define UVC_STREAM_STI (1 << 5)
+#define UVC_STREAM_RES (1 << 4)
+#define UVC_STREAM_SCR (1 << 3)
+#define UVC_STREAM_PTS (1 << 2)
+#define UVC_STREAM_EOF (1 << 1)
+#define UVC_STREAM_FID (1 << 0)
+
+/* 4.1.2. Control Capabilities */
+#define UVC_CONTROL_CAP_GET (1 << 0)
+#define UVC_CONTROL_CAP_SET (1 << 1)
+#define UVC_CONTROL_CAP_DISABLED (1 << 2)
+#define UVC_CONTROL_CAP_AUTOUPDATE (1 << 3)
+#define UVC_CONTROL_CAP_ASYNCHRONOUS (1 << 4)
+
+/* ------------------------------------------------------------------------
+ * UVC structures
+ */
+
+/* All UVC descriptors have these 3 fields at the beginning */
+struct uvc_descriptor_header {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+} __attribute__((packed));
+
+/* 3.7.2. Video Control Interface Header Descriptor */
+struct uvc_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint16_t bcdUVC;
+ uint16_t wTotalLength;
+ uint32_t dwClockFrequency;
+ uint8_t bInCollection;
+ uint8_t baInterfaceNr[];
+} __attribute__((__packed__));
+
+#define UVC_DT_HEADER_SIZE(n) (12+(n))
+
+#define UVC_HEADER_DESCRIPTOR(n) \
+ uvc_header_descriptor_##n
+
+#define DECLARE_UVC_HEADER_DESCRIPTOR(n) \
+struct UVC_HEADER_DESCRIPTOR(n) { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint16_t bcdUVC; \
+ uint16_t wTotalLength; \
+ uint32_t dwClockFrequency; \
+ uint8_t bInCollection; \
+ uint8_t baInterfaceNr[n]; \
+} __attribute__ ((packed))
+
+/* 3.7.2.1. Input Terminal Descriptor */
+struct uvc_input_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t iTerminal;
+} __attribute__((__packed__));
+
+#define UVC_DT_INPUT_TERMINAL_SIZE 8
+
+/* 3.7.2.2. Output Terminal Descriptor */
+struct uvc_output_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bSourceID;
+ uint8_t iTerminal;
+} __attribute__((__packed__));
+
+#define UVC_DT_OUTPUT_TERMINAL_SIZE 9
+
+/* 3.7.2.3. Camera Terminal Descriptor */
+struct uvc_camera_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t iTerminal;
+ uint16_t wObjectiveFocalLengthMin;
+ uint16_t wObjectiveFocalLengthMax;
+ uint16_t wOcularFocalLength;
+ uint8_t bControlSize;
+ uint8_t bmControls[3];
+} __attribute__((__packed__));
+
+#define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n))
+
+/* 3.7.2.4. Selector Unit Descriptor */
+struct uvc_selector_unit_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bUnitID;
+ uint8_t bNrInPins;
+ uint8_t baSourceID[0];
+ uint8_t iSelector;
+} __attribute__((__packed__));
+
+#define UVC_DT_SELECTOR_UNIT_SIZE(n) (6+(n))
+
+#define UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
+ uvc_selector_unit_descriptor_##n
+
+#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n) \
+struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bUnitID; \
+ uint8_t bNrInPins; \
+ uint8_t baSourceID[n]; \
+ uint8_t iSelector; \
+} __attribute__ ((packed))
+
+/* 3.7.2.5. Processing Unit Descriptor */
+struct uvc_processing_unit_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bUnitID;
+ uint8_t bSourceID;
+ uint16_t wMaxMultiplier;
+ uint8_t bControlSize;
+ uint8_t bmControls[3];
+ uint8_t iProcessing;
+} __attribute__((__packed__));
+
+#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n))
+
+/* 3.7.2.6. Extension Unit Descriptor */
+struct uvc_extension_unit_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bUnitID;
+ uint8_t guidExtensionCode[16];
+ uint8_t bNumControls;
+ uint8_t bNrInPins;
+ uint8_t baSourceID[0];
+ uint8_t bControlSize;
+ uint8_t bmControls[0];
+ uint8_t iExtension;
+} __attribute__((__packed__));
+
+#define UVC_DT_EXTENSION_UNIT_SIZE(p, n) (24+(p)+(n))
+
+#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
+ uvc_extension_unit_descriptor_##p_##n
+
+#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
+struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bUnitID; \
+ uint8_t guidExtensionCode[16]; \
+ uint8_t bNumControls; \
+ uint8_t bNrInPins; \
+ uint8_t baSourceID[p]; \
+ uint8_t bControlSize; \
+ uint8_t bmControls[n]; \
+ uint8_t iExtension; \
+} __attribute__ ((packed))
+
+/* 3.8.2.2. Video Control Interrupt Endpoint Descriptor */
+struct uvc_control_endpoint_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint16_t wMaxTransferSize;
+} __attribute__((__packed__));
+
+#define UVC_DT_CONTROL_ENDPOINT_SIZE 5
+
+/* 3.9.2.1. Input Header Descriptor */
+struct uvc_input_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bNumFormats;
+ uint16_t wTotalLength;
+ uint8_t bEndpointAddress;
+ uint8_t bmInfo;
+ uint8_t bTerminalLink;
+ uint8_t bStillCaptureMethod;
+ uint8_t bTriggerSupport;
+ uint8_t bTriggerUsage;
+ uint8_t bControlSize;
+ uint8_t bmaControls[];
+} __attribute__((__packed__));
+
+#define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p))
+
+#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
+ uvc_input_header_descriptor_##n_##p
+
+#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
+struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bNumFormats; \
+ uint16_t wTotalLength; \
+ uint8_t bEndpointAddress; \
+ uint8_t bmInfo; \
+ uint8_t bTerminalLink; \
+ uint8_t bStillCaptureMethod; \
+ uint8_t bTriggerSupport; \
+ uint8_t bTriggerUsage; \
+ uint8_t bControlSize; \
+ uint8_t bmaControls[p][n]; \
+} __attribute__ ((packed))
+
+/* 3.9.2.2. Output Header Descriptor */
+struct uvc_output_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bNumFormats;
+ uint16_t wTotalLength;
+ uint8_t bEndpointAddress;
+ uint8_t bTerminalLink;
+ uint8_t bControlSize;
+ uint8_t bmaControls[];
+} __attribute__((__packed__));
+
+#define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p))
+
+#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
+ uvc_output_header_descriptor_##n_##p
+
+#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
+struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bNumFormats; \
+ uint16_t wTotalLength; \
+ uint8_t bEndpointAddress; \
+ uint8_t bTerminalLink; \
+ uint8_t bControlSize; \
+ uint8_t bmaControls[p][n]; \
+} __attribute__ ((packed))
+
+/* 3.9.2.6. Color matching descriptor */
+struct uvc_color_matching_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bColorPrimaries;
+ uint8_t bTransferCharacteristics;
+ uint8_t bMatrixCoefficients;
+} __attribute__((__packed__));
+
+#define UVC_DT_COLOR_MATCHING_SIZE 6
+
+/* 4.3.1.1. Video Probe and Commit Controls */
+struct uvc_streaming_control {
+ uint16_t bmHint;
+ uint8_t bFormatIndex;
+ uint8_t bFrameIndex;
+ uint32_t dwFrameInterval;
+ uint16_t wKeyFrameRate;
+ uint16_t wPFrameRate;
+ uint16_t wCompQuality;
+ uint16_t wCompWindowSize;
+ uint16_t wDelay;
+ uint32_t dwMaxVideoFrameSize;
+ uint32_t dwMaxPayloadTransferSize;
+ uint32_t dwClockFrequency;
+ uint8_t bmFramingInfo;
+ uint8_t bPreferedVersion;
+ uint8_t bMinVersion;
+ uint8_t bMaxVersion;
+} __attribute__((__packed__));
+
+/* Uncompressed Payload - 3.1.1. Uncompressed Video Format Descriptor */
+struct uvc_format_uncompressed {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFormatIndex;
+ uint8_t bNumFrameDescriptors;
+ uint8_t guidFormat[16];
+ uint8_t bBitsPerPixel;
+ uint8_t bDefaultFrameIndex;
+ uint8_t bAspectRatioX;
+ uint8_t bAspectRatioY;
+ uint8_t bmInterlaceFlags;
+ uint8_t bCopyProtect;
+} __attribute__((__packed__));
+
+#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE 27
+
+/* Uncompressed Payload - 3.1.2. Uncompressed Video Frame Descriptor */
+struct uvc_frame_uncompressed {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFrameIndex;
+ uint8_t bmCapabilities;
+ uint16_t wWidth;
+ uint16_t wHeight;
+ uint32_t dwMinBitRate;
+ uint32_t dwMaxBitRate;
+ uint32_t dwMaxVideoFrameBufferSize;
+ uint32_t dwDefaultFrameInterval;
+ uint8_t bFrameIntervalType;
+ uint32_t dwFrameInterval[];
+} __attribute__((__packed__));
+
+#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n))
+
+#define UVC_FRAME_UNCOMPRESSED(n) \
+ uvc_frame_uncompressed_##n
+
+#define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \
+struct UVC_FRAME_UNCOMPRESSED(n) { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bFrameIndex; \
+ uint8_t bmCapabilities; \
+ uint16_t wWidth; \
+ uint16_t wHeight; \
+ uint32_t dwMinBitRate; \
+ uint32_t dwMaxBitRate; \
+ uint32_t dwMaxVideoFrameBufferSize; \
+ uint32_t dwDefaultFrameInterval; \
+ uint8_t bFrameIntervalType; \
+ uint32_t dwFrameInterval[n]; \
+} __attribute__ ((packed))
+
+#define UVC_FRAMES_FORMAT_UNCOMPRESSED(n) \
+ uvc_vs_frame_format_desc_##n
+
+#define DECLARE_UVC_FRAMES_FORMAT_UNCOMPRESSED(n) \
+struct UVC_FRAMES_FORMAT_UNCOMPRESSED(n) { \
+ struct uvc_format_uncompressed uvc_vs_format; \
+ struct UVC_FRAME_UNCOMPRESSED(1) uvc_vs_frame[n]; \
+ struct uvc_color_matching_descriptor uvc_vs_color; \
+} __attribute__ ((packed));
+
+#endif /* __UVC_H */
+
diff --git a/src/webcam/include/uvc_desc.h b/src/webcam/include/uvc_desc.h
new file mode 100644
index 000000000..1b330499e
--- /dev/null
+++ b/src/webcam/include/uvc_desc.h
@@ -0,0 +1,61 @@
+/*
+ * uvc_desc.h
+ *
+ * Created on: Nov 23, 2017
+ * Author: kurt
+ */
+
+#ifndef ST_STM32_USB_DEVICE_LIBRARY_CLASS_VIDEO_INC_UVC_DESC_H_
+#define ST_STM32_USB_DEVICE_LIBRARY_CLASS_VIDEO_INC_UVC_DESC_H_
+
+#include "usbd_desc.h"
+#include "usbd_types.h"
+#include "uvc.h"
+
+// consistent macro expansion of VS_NUM_FORMATS
+#define _UVC_INPUT_HEADER_DESCRIPTOR(n, p) UVC_INPUT_HEADER_DESCRIPTOR(n, p)
+
+DECLARE_UVC_HEADER_DESCRIPTOR(1);
+DECLARE_UVC_FRAME_UNCOMPRESSED(1);
+DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(1, 4);
+DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(1, 8);
+DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, VS_NUM_FORMATS);
+DECLARE_UVC_FRAMES_FORMAT_UNCOMPRESSED(3);
+DECLARE_UVC_FRAMES_FORMAT_UNCOMPRESSED(4);
+
+struct uvc_vs_frames_formats_descriptor {
+ struct UVC_FRAMES_FORMAT_UNCOMPRESSED(3) uvc_vs_frames_format_1;
+ struct UVC_FRAMES_FORMAT_UNCOMPRESSED(4) uvc_vs_frames_format_2;
+ struct UVC_FRAMES_FORMAT_UNCOMPRESSED(3) uvc_vs_frames_format_3;
+};
+
+struct usbd_uvc_cfg {
+ struct usb_config_descriptor usb_configuration;
+ struct usb_interface_assoc_descriptor usb_uvc_association;
+
+ struct usb_interface_descriptor uvc_vc_if_desc;
+ struct UVC_HEADER_DESCRIPTOR(1) ucv_vc_header;
+ struct uvc_camera_terminal_descriptor uvc_vc_input_terminal;
+ struct uvc_processing_unit_descriptor uvc_vc_processing_unit;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 4) uvc_vc_xu_lep_agc;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 4) uvc_vc_xu_lep_oem;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 8) uvc_vc_xu_lep_rad;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 4) uvc_vc_xu_lep_sys;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 4) uvc_vc_xu_lep_vid;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 4) uvc_vc_xu_lep_rad_2;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 4) uvc_vc_xu_lep_cust;
+ struct uvc_output_terminal_descriptor uvc_vc_output_terminal;
+ struct usb_endpoint_descriptor uvc_vc_ep;
+ struct uvc_control_endpoint_descriptor uvc_vc_cs_ep;
+
+ struct usb_interface_descriptor uvc_vs_if_alt0_desc;
+ struct _UVC_INPUT_HEADER_DESCRIPTOR(1, VS_NUM_FORMATS) uvc_vs_input_header_desc;
+ struct uvc_vs_frames_formats_descriptor uvc_vs_frames_formats_desc;
+
+ struct usb_interface_descriptor uvc_vs_if_alt1_desc;
+ struct usb_endpoint_descriptor uvc_vs_if_alt1_ep;
+} __attribute__ ((packed));
+
+extern struct usbd_uvc_cfg USBD_UVC_CfgFSDesc;
+
+#endif /* ST_STM32_USB_DEVICE_LIBRARY_CLASS_VIDEO_INC_UVC_DESC_H_ */
diff --git a/src/webcam/include/uvc_desc_conf.h b/src/webcam/include/uvc_desc_conf.h
new file mode 100644
index 000000000..81236dce2
--- /dev/null
+++ b/src/webcam/include/uvc_desc_conf.h
@@ -0,0 +1,11 @@
+/* Configuration 1 */
+.usb_configuration = {
+ .bLength = USB_LEN_CFG_DESC, // 9
+ .bDescriptorType = USB_DESC_TYPE_CONFIGURATION, // 2
+ .wTotalLength = sizeof(struct usbd_uvc_cfg),
+ .bNumInterfaces = 0x02, // 2
+ .bConfigurationValue = 0x01, // 1 ID of this configuration
+ .iConfiguration = 0x00, // 0 no description available
+ .bmAttributes = USB_CONFIG_BUS_POWERED , // 0x80 Bus Powered
+ .bMaxPower = USB_CONFIG_POWER_MA(100), // 100 mA
+},
diff --git a/src/webcam/include/uvc_desc_va.h b/src/webcam/include/uvc_desc_va.h
new file mode 100644
index 000000000..1988a6dfe
--- /dev/null
+++ b/src/webcam/include/uvc_desc_va.h
@@ -0,0 +1,13 @@
+/*----------------- Video Association (Control + stream) ------------------*/
+
+/* Interface Association Descriptor */
+.usb_uvc_association = {
+ .bLength = USB_DT_INTERFACE_ASSOC_SIZE, // 8
+ .bDescriptorType = USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE, // 11
+ .bFirstInterface = 0x00, // 0
+ .bInterfaceCount = 0x02, // 2
+ .bFunctionClass = UVC_CC_VIDEO, // 14 Video
+ .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, // 3 Video Interface Collection
+ .bFunctionProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iFunction = 0x02, // 2
+},
diff --git a/src/webcam/include/uvc_desc_vc.h b/src/webcam/include/uvc_desc_vc.h
new file mode 100644
index 000000000..3a949520a
--- /dev/null
+++ b/src/webcam/include/uvc_desc_vc.h
@@ -0,0 +1,261 @@
+/*----------------- Video Association (Control + stream) ------------------*/
+
+/* Interface Association Descriptor */
+.usb_uvc_association = {
+ .bLength = USB_DT_INTERFACE_ASSOC_SIZE, // 8
+ .bDescriptorType = USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE, // 11
+ .bFirstInterface = 0x00, // 0
+ .bInterfaceCount = 0x02, // 2
+ .bFunctionClass = UVC_CC_VIDEO, // 14 Video
+ .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, // 3 Video Interface Collection
+ .bFunctionProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iFunction = 0x02, // 2
+},
+
+
+/*------------------ VideoControl Interface descriptor --------------------*/
+
+/* Standard VC Interface Descriptor = interface 0 */
+.uvc_vc_if_desc = {
+ .bLength = USB_LEN_IF_DESC, // 9
+ .bDescriptorType = USB_DESC_TYPE_INTERFACE, // 4
+ .bInterfaceNumber = USB_UVC_VCIF_NUM, // 0 index of this interface (VC)
+ .bAlternateSetting = 0x00, // 0 index of this setting
+ .bNumEndpoints = 0x01, // 1 endpoint
+ .bInterfaceClass = UVC_CC_VIDEO, // 14 Video
+ .bInterfaceSubClass = UVC_SC_VIDEOCONTROL, // 1 Video Control
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iInterface = 0x00,
+},
+
+/* Class-specific VC Interface Descriptor */
+.ucv_vc_header = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, ucv_vc_header),
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VC_HEADER, // 1 (HEADER)
+ .bcdUVC = UVC_VERSION, // 1.10 or 1.00
+ .wTotalLength =
+ SIZEOF_M(struct usbd_uvc_cfg, ucv_vc_header) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_input_terminal) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_processing_unit) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_agc) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_oem) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_sys) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_vid) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad_2) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_cust) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_output_terminal), // header+units+terminals
+ .dwClockFrequency = 0x005B8D80, // 6.000000 MHz
+ .bInCollection = 0x01, // 1 one streaming interface
+ .baInterfaceNr = { 0x01 }, // 1 VS interface 1 belongs to this VC interface
+},
+
+/* Input Terminal Descriptor (Camera) */
+.uvc_vc_input_terminal = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_input_terminal), // Descriptor size
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VC_INPUT_TERMINAL, // 2 (INPUT_TERMINAL)
+ .bTerminalID = VC_INPUT_TERMINAL_ID, // 1 ID of this Terminal
+ .wTerminalType = UVC_ITT_CAMERA, // 0x0201 Camera Sensor
+ .bAssocTerminal = 0x00, // 0 no Terminal associated
+ .iTerminal = 0x00, // 0 no description available
+ .wObjectiveFocalLengthMin = 0x0000, // 0
+ .wObjectiveFocalLengthMax = 0x0000, // 0
+ .wOcularFocalLength = 0x0000, // 0
+ .bControlSize = 0x03, // 2
+ .bmControls = { 0x00, 0x00, 0x00 }, // 0x0000 no controls supported
+},
+
+/* Processing Unit Descriptor */
+.uvc_vc_processing_unit = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_processing_unit), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x05, // Processing Unit Descriptor type
+ .bUnitID = VC_CONTROL_PU_ID, // ID of this terminal
+ .bSourceID = 0x01, // Source ID : 1 : Connected to input terminal
+ .wMaxMultiplier = 0, // Digital multiplier
+ .bControlSize = 0x03, // Size of controls field for this terminal : 2 bytes
+ .bmControls = { 0x03, 0x00, 0x00 }, // Brightness and contrast
+ .iProcessing = 0x00, // String desc index : Not used
+},
+
+/* Extension Unit Descriptor */
+.uvc_vc_xu_lep_agc = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_agc), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_AGC_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'a','g','c','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x14, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xff, 0xff, 0x0f, 0x00 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+},
+
+/* Extension Unit Descriptor */
+.uvc_vc_xu_lep_oem = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_oem), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_OEM_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'o','e','m','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x1e, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xbf, 0xff, 0xff, 0x7f }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+},
+
+/* Extension Unit Descriptor */
+.uvc_vc_xu_lep_rad = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_RAD_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'r','a','d','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 48, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x08, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xFF, 0xFF, 0xFF, 0x81, 0xFC, 0xCF, 0xFF, 0x03 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+},
+
+/* Extension Unit Descriptor */
+.uvc_vc_xu_lep_rad_2 = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad_2), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_RAD_2_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'r','a','d','2',
+ '0','0','0','0'
+ },
+ .bNumControls = 27, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xf9, 0x9f, 0xff, 0x07 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+},
+
+/* Extension Unit Descriptor */
+.uvc_vc_xu_lep_sys = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_sys), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_SYS_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 's','y','s','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x17, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xFF, 0xFF, 0x7F, 0x00 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+},
+
+/* Extension Unit Descriptor */
+.uvc_vc_xu_lep_vid = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_vid), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_VID_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'v','i','d','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x0e, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xFF, 0x3F, 0x00, 0x00 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+},
+
+/* Extension Unit Descriptor */
+.uvc_vc_xu_lep_cust = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_cust), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_CUST_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'c','u','s','t',
+ '0','0','0','0'
+ },
+ .bNumControls = CUST_CONTROL_END, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { (1 << CUST_CONTROL_END) - 1, 0, 0, 0 }, //
+ .iExtension = 0x00, // String desc index : Not used
+},
+
+/* Output Terminal Descriptor */
+.uvc_vc_output_terminal = {
+ .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE, // 9
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL, // 3 (OUTPUT_TERMINAL)
+ .bTerminalID = VC_OUTPUT_TERMINAL_ID, // 2 ID of this Terminal
+ .wTerminalType = UVC_TT_STREAMING, // 0x0101 USB streaming terminal
+ .bAssocTerminal = 0x00, // 0 no Terminal assiciated
+ .bSourceID = 0x03, // 1 input pin connected to output pin unit 1
+ .iTerminal = 0x00, // 0 no description available
+},
+
+/* Standard Interrupt Endpoint Descriptor */
+.uvc_vc_ep = {
+ .bLength = USB_DT_ENDPOINT_SIZE, // 7
+ .bDescriptorType = USB_DESC_TYPE_ENDPOINT, // 5 (ENDPOINT)
+ .bEndpointAddress = UVC_CMD_EP, // 0x82 EP 2 IN
+ .bmAttributes = USBD_EP_TYPE_INTR, // interrupt
+ .wMaxPacketSize = CMD_PACKET_SIZE, // 8 bytes status
+ .bInterval = 0x20, // poll at least every 32ms
+},
+
+/* Class-specific Interrupt Endpoint Descriptor */
+.uvc_vc_cs_ep = {
+ .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE,
+ .bDescriptorType = UVC_CS_ENDPOINT,
+ .bDescriptorSubType = USBD_EP_TYPE_INTR,
+ .wMaxTransferSize = CMD_PACKET_SIZE,
+},
diff --git a/src/webcam/include/uvc_desc_vs.h b/src/webcam/include/uvc_desc_vs.h
new file mode 100644
index 000000000..d06b0afca
--- /dev/null
+++ b/src/webcam/include/uvc_desc_vs.h
@@ -0,0 +1,75 @@
+/*-------------- Video Streaming (VS) Interface Descriptor ----------------*/
+
+/* Standard VS Interface Descriptor = interface 1 */
+// alternate setting 0 = Zero Bandwidth
+.uvc_vs_if_alt0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE, // 9
+ .bDescriptorType = USB_DESC_TYPE_INTERFACE, // 4
+ .bInterfaceNumber = USB_UVC_VSIF_NUM, // 1 index of this interface
+ .bAlternateSetting = 0x00, // 0 index of this setting
+ .bNumEndpoints = 0x00, // 0 no EP used
+ .bInterfaceClass = UVC_CC_VIDEO, // 14 Video
+ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, // 2 Video Streaming
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iInterface = 0x00, // 0 no description available
+},
+
+/* Class-specific VS Header Descriptor (Input) */
+.uvc_vs_input_header_desc = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vs_input_header_desc),
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VS_INPUT_HEADER, // 1 (INPUT_HEADER)
+ .bNumFormats = VS_NUM_FORMATS, // 4 four format descriptors follow
+ .wTotalLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vs_input_header_desc) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vs_frames_formats_desc),
+ .bEndpointAddress = UVC_IN_EP, // 0x83 EP 3 IN
+ .bmInfo = 0x00, // 0 no dynamic format change supported
+ .bTerminalLink = VC_OUTPUT_TERMINAL_ID, // 2 supplies terminal ID 2 (Output terminal)
+ .bStillCaptureMethod = 0x01, // 1 Host captures from video stream
+ .bTriggerSupport = 0x00, // 0 HW trigger supported for still image capture
+ .bTriggerUsage = 0x00, // 0 HW trigger initiate a still image capture
+ .bControlSize = 0x01, // 1 one byte bmaControls field size
+ .bmaControls = {
+ { 0x00 }, // bmaControls(0) 0 no VS specific controls
+ { 0x00 }, // bmaControls(1) 0 no VS specific controls
+ { 0x00 }, // bmaControls(2) 0 no VS specific controls
+ { 0x00 }, // bmaControls(3) 0 no VS specific controls
+ { 0x00 }, // bmaControls(4) 0 no VS specific controls
+ },
+},
+
+.uvc_vs_frames_formats_desc = {
+.uvc_vs_frames_format_1 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(YUYV, 1),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_DEFAULT, YUYV, 80, 60) },
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+.uvc_vs_frames_format_2 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(Y16, 1),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_DEFAULT, Y16, 80, 60),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_TELEMETRIC, Y16, 80, 63) },
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+.uvc_vs_frames_format_3 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(GREY, 1),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_DEFAULT, GREY, 80, 60) },
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+.uvc_vs_frames_format_4 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(RGB565, 1),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_DEFAULT, RGB565, 80, 60) },
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+.uvc_vs_frames_format_5 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(BGR3, 1),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_DEFAULT, BGR3, 80, 60) },
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+},
diff --git a/src/webcam/include/uvc_desc_vs_if.h b/src/webcam/include/uvc_desc_vs_if.h
new file mode 100644
index 000000000..74979ce44
--- /dev/null
+++ b/src/webcam/include/uvc_desc_vs_if.h
@@ -0,0 +1,23 @@
+/* Standard VS Interface Descriptor = interface 1 */
+// alternate setting 1 = operational setting
+.uvc_vs_if_alt1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE, // 9
+ .bDescriptorType = USB_DESC_TYPE_INTERFACE, // 4
+ .bInterfaceNumber = USB_UVC_VSIF_NUM, // 1 index of this interface
+ .bAlternateSetting = 0x01, // 1 index of this setting
+ .bNumEndpoints = 0x01, // 1 one EP used
+ .bInterfaceClass = UVC_CC_VIDEO, // 14 Video
+ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, // 2 Video Streaming
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iInterface = 0x00, // 0 no description available
+},
+
+/* Standard VS Isochronous Video data Endpoint Descriptor */
+.uvc_vs_if_alt1_ep = {
+ .bLength = USB_DT_ENDPOINT_SIZE, // 7
+ .bDescriptorType = USB_DESC_TYPE_ENDPOINT, // 5 (ENDPOINT)
+ .bEndpointAddress = UVC_IN_EP, // 0x83 EP 3 IN
+ .bmAttributes = USBD_EP_TYPE_ISOC, // 1 isochronous transfer type
+ .wMaxPacketSize = VIDEO_PACKET_SIZE,
+ .bInterval = 0x01, // 1 one frame interval
+},
diff --git a/src/webcam/src/main.c b/src/webcam/src/main.c
new file mode 100644
index 000000000..fed39122f
--- /dev/null
+++ b/src/webcam/src/main.c
@@ -0,0 +1,177 @@
+#include STM32_HAL_H
+#include "usbd_core.h"
+#include "usbd_desc.h"
+#include "usbd_uvc.h"
+#include "usbd_uvc_if.h"
+#include "sensor.h"
+#include "framebuffer.h"
+#include "omv_boardconfig.h"
+
+extern sensor_t sensor;
+USBD_HandleTypeDef hUsbDeviceFS;
+extern volatile uint8_t g_uvc_stream_status;
+extern struct uvc_streaming_control videoCommitControl;
+
+void __attribute__((noreturn)) __fatal_error()
+{
+ while (1) {
+ }
+}
+
+#ifdef STACK_PROTECTOR
+uint32_t __stack_chk_guard=0xDEADBEEF;
+
+void __attribute__((noreturn)) __stack_chk_fail(void)
+{
+ __asm__ volatile ("BKPT");
+ while (1) {
+ }
+}
+#endif
+
+void *xrealloc(void *mem, uint32_t size)
+{
+ // Will never be called.
+ __fatal_error();
+ return NULL;
+}
+
+NORETURN void fb_alloc_fail()
+{
+ __fatal_error();
+}
+
+int main()
+{
+ HAL_Init();
+
+ // Re-enable IRQs (disabled by bootloader)
+ __enable_irq();
+
+
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Pull = GPIO_PULLUP;
+ GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+
+ GPIO_InitStructure.Pin = OMV_BOOTLDR_LED_PIN;
+ HAL_GPIO_Init(OMV_BOOTLDR_LED_PORT, &GPIO_InitStructure);
+ HAL_GPIO_WritePin(OMV_BOOTLDR_LED_PORT, OMV_BOOTLDR_LED_PIN, GPIO_PIN_SET);
+
+ sensor_init0();
+ fb_alloc_init0();
+
+ // Initialize the sensor
+ if (sensor_init() != 0) {
+ __fatal_error();
+ }
+
+ sensor_reset();
+
+ /* Init Device Library */
+ USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
+
+ /* Add Supported Class */
+ USBD_RegisterClass(&hUsbDeviceFS, &USBD_UVC);
+
+ /* Add Interface Class */
+ USBD_UVC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
+
+ USBD_Start(&hUsbDeviceFS);
+
+ image_t image = {0};
+ uint32_t frame_size = 0;
+ uint8_t frame_index = 0;
+ uint8_t format_index = 0;
+ uint32_t packet_size = VIDEO_PACKET_SIZE;
+ static uint8_t uvc_header[2] = { 2, 0 };
+ static uint8_t packet[VIDEO_PACKET_SIZE];
+
+ while (1) {
+ uint32_t idx = 0;
+ while (g_uvc_stream_status == 2) {
+ uint32_t pidx = 0;
+ packet[pidx++] = uvc_header[0];
+ packet[pidx++] = uvc_header[1];
+
+ if (image.bpp == 0) {
+ if (frame_index != videoCommitControl.bFrameIndex ||
+ format_index != videoCommitControl.bFormatIndex) {
+
+ switch (videoCommitControl.bFormatIndex) {
+ case VS_FMT_INDEX(YUYV):
+ sensor_set_pixformat(PIXFORMAT_YUV422);
+ break;
+ case VS_FMT_INDEX(GREY):
+ sensor_set_pixformat(PIXFORMAT_GRAYSCALE);
+ break;
+ case VS_FMT_INDEX(RGB565):
+ sensor_set_pixformat(PIXFORMAT_RGB565);
+ break;
+ default:
+ break;
+ }
+
+ switch (videoCommitControl.bFrameIndex) {
+ case VS_FRAME_INDEX_1:
+ sensor_set_framesize(FRAMESIZE_QQQVGA);
+ break;
+ case VS_FRAME_INDEX_2:
+ sensor_set_framesize(FRAMESIZE_QQVGA);
+ break;
+ case VS_FRAME_INDEX_3:
+ sensor_set_framesize(FRAMESIZE_QVGA);
+ break;
+ case VS_FRAME_INDEX_4:
+ sensor_set_framesize(FRAMESIZE_VGA);
+ break;
+ default:
+ break;
+ }
+
+ frame_index = videoCommitControl.bFrameIndex;
+ format_index = videoCommitControl.bFormatIndex;
+ }
+
+ // capture new frame
+ sensor.snapshot(&sensor, &image);
+ frame_size = image.w * image.h * image.bpp;
+ }
+
+ switch (videoCommitControl.bFormatIndex) {
+ case VS_FMT_INDEX(YUYV): {
+ for (; pidx
+ * This work is licensed under the MIT license, see the file LICENSE for details.
+ *
+ * Interrupt handlers.
+ *
+ */
+
+/**
+ ******************************************************************************
+ * @file USB_Device/CDC_Standalone/Src/stm32f4xx_it.c
+ * @author MCD Application Team
+ * @version V1.2.2
+ * @date 25-May-2015
+ * @brief Main Interrupt Service Routines.
+ * This file provides template for all exceptions handler and
+ * peripherals interrupt service routine.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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.
+ *
+ ******************************************************************************
+ */
+
+#include STM32_HAL_H
+#include
+
+extern PCD_HandleTypeDef hpcd;
+extern DCMI_HandleTypeDef DCMIHandle;
+extern void DCMI_VsyncExtiCallback();
+extern TIM_HandleTypeDef TIM5_Handle;
+
+/**
+ * @brief This function handles NMI exception.
+ * @param None
+ * @retval None
+ */
+void NMI_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles Hard Fault exception.
+ * @param None
+ * @retval None
+ */
+void HardFault_Handler(void)
+{
+ /* Go to infinite loop when Hard Fault exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles Memory Manage exception.
+ * @param None
+ * @retval None
+ */
+void MemManage_Handler(void)
+{
+ /* Go to infinite loop when Memory Manage exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles Bus Fault exception.
+ * @param None
+ * @retval None
+ */
+void BusFault_Handler(void)
+{
+ /* Go to infinite loop when Bus Fault exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles Usage Fault exception.
+ * @param None
+ * @retval None
+ */
+void UsageFault_Handler(void)
+{
+ /* Go to infinite loop when Usage Fault exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles SVCall exception.
+ * @param None
+ * @retval None
+ */
+void SVC_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles Debug Monitor exception.
+ * @param None
+ * @retval None
+ */
+void DebugMon_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles PendSVC exception.
+ * @param None
+ * @retval None
+ */
+void PendSV_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles SysTick Handler.
+ * @param None
+ * @retval None
+ */
+void SysTick_Handler(void)
+{
+ HAL_IncTick();
+}
+
+/**
+ * @brief This function handles USB-On-The-Go FS global interrupt request.
+ * @param None
+ * @retval None
+ */
+#ifdef USE_USB_FS
+void OTG_FS_IRQHandler(void)
+#else
+void OTG_HS_IRQHandler(void)
+#endif
+{
+ HAL_PCD_IRQHandler(&hpcd);
+}
+
+void DCMI_IRQHandler(void) {
+ HAL_DCMI_IRQHandler(&DCMIHandle);
+}
+
+void DMA2_Stream1_IRQHandler(void) {
+ HAL_DMA_IRQHandler(DCMIHandle.DMA_Handle);
+}
diff --git a/src/webcam/src/string0.c b/src/webcam/src/string0.c
new file mode 100644
index 000000000..c2f2abd0f
--- /dev/null
+++ b/src/webcam/src/string0.c
@@ -0,0 +1,219 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#define likely(x) __builtin_expect((x), 1)
+
+void *memcpy(void *dst, const void *src, size_t n) {
+ if (likely(!(((uintptr_t)dst) & 3) && !(((uintptr_t)src) & 3))) {
+ // pointers aligned
+ uint32_t *d = dst;
+ const uint32_t *s = src;
+
+ // copy words first
+ for (size_t i = (n >> 2); i; i--) {
+ *d++ = *s++;
+ }
+
+ if (n & 2) {
+ // copy half-word
+ *(uint16_t*)d = *(const uint16_t*)s;
+ d = (uint32_t*)((uint16_t*)d + 1);
+ s = (const uint32_t*)((const uint16_t*)s + 1);
+ }
+
+ if (n & 1) {
+ // copy byte
+ *((uint8_t*)d) = *((const uint8_t*)s);
+ }
+ } else {
+ // unaligned access, copy bytes
+ uint8_t *d = dst;
+ const uint8_t *s = src;
+
+ for (; n; n--) {
+ *d++ = *s++;
+ }
+ }
+
+ return dst;
+}
+
+void *memmove(void *dest, const void *src, size_t n) {
+ if (src < dest && (uint8_t*)dest < (const uint8_t*)src + n) {
+ // need to copy backwards
+ uint8_t *d = (uint8_t*)dest + n - 1;
+ const uint8_t *s = (const uint8_t*)src + n - 1;
+ for (; n > 0; n--) {
+ *d-- = *s--;
+ }
+ return dest;
+ } else {
+ // can use normal memcpy
+ return memcpy(dest, src, n);
+ }
+}
+
+void *memset(void *s, int c, size_t n) {
+ if (c == 0 && ((uintptr_t)s & 3) == 0) {
+ // aligned store of 0
+ uint32_t *s32 = s;
+ for (size_t i = n >> 2; i > 0; i--) {
+ *s32++ = 0;
+ }
+ if (n & 2) {
+ *((uint16_t*)s32) = 0;
+ s32 = (uint32_t*)((uint16_t*)s32 + 1);
+ }
+ if (n & 1) {
+ *((uint8_t*)s32) = 0;
+ }
+ } else {
+ uint8_t *s2 = s;
+ for (; n > 0; n--) {
+ *s2++ = c;
+ }
+ }
+ return s;
+}
+
+int memcmp(const void *s1, const void *s2, size_t n) {
+ const uint8_t *s1_8 = s1;
+ const uint8_t *s2_8 = s2;
+ while (n--) {
+ char c1 = *s1_8++;
+ char c2 = *s2_8++;
+ if (c1 < c2) return -1;
+ else if (c1 > c2) return 1;
+ }
+ return 0;
+}
+
+void *memchr(const void *s, int c, size_t n) {
+ if (n != 0) {
+ const unsigned char *p = s;
+
+ do {
+ if (*p++ == c)
+ return ((void *)(p - 1));
+ } while (--n != 0);
+ }
+ return 0;
+}
+
+size_t strlen(const char *str) {
+ int len = 0;
+ for (const char *s = str; *s; s++) {
+ len += 1;
+ }
+ return len;
+}
+
+int strcmp(const char *s1, const char *s2) {
+ while (*s1 && *s2) {
+ char c1 = *s1++; // XXX UTF8 get char, next char
+ char c2 = *s2++; // XXX UTF8 get char, next char
+ if (c1 < c2) return -1;
+ else if (c1 > c2) return 1;
+ }
+ if (*s2) return -1;
+ else if (*s1) return 1;
+ else return 0;
+}
+
+int strncmp(const char *s1, const char *s2, size_t n) {
+ while (*s1 && *s2 && n > 0) {
+ char c1 = *s1++; // XXX UTF8 get char, next char
+ char c2 = *s2++; // XXX UTF8 get char, next char
+ n--;
+ if (c1 < c2) return -1;
+ else if (c1 > c2) return 1;
+ }
+ if (n == 0) return 0;
+ else if (*s2) return -1;
+ else if (*s1) return 1;
+ else return 0;
+}
+
+char *strcpy(char *dest, const char *src) {
+ char *d = dest;
+ while (*src) {
+ *d++ = *src++;
+ }
+ *d = '\0';
+ return dest;
+}
+
+// needed because gcc optimises strcpy + strcat to this
+char *stpcpy(char *dest, const char *src) {
+ while (*src) {
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+ return dest;
+}
+
+char *strcat(char *dest, const char *src) {
+ char *d = dest;
+ while (*d) {
+ d++;
+ }
+ while (*src) {
+ *d++ = *src++;
+ }
+ *d = '\0';
+ return dest;
+}
+
+// Public Domain implementation of strchr from:
+// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strchr_function
+char *strchr(const char *s, int c)
+{
+ /* Scan s for the character. When this loop is finished,
+ s will either point to the end of the string or the
+ character we were looking for. */
+ while (*s != '\0' && *s != (char)c)
+ s++;
+ return ((*s == c) ? (char *) s : 0);
+}
+
+
+// Public Domain implementation of strstr from:
+// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strstr_function
+char *strstr(const char *haystack, const char *needle)
+{
+ size_t needlelen;
+ /* Check for the null needle case. */
+ if (*needle == '\0')
+ return (char *) haystack;
+ needlelen = strlen(needle);
+ for (; (haystack = strchr(haystack, *needle)) != 0; haystack++)
+ if (strncmp(haystack, needle, needlelen) == 0)
+ return (char *) haystack;
+ return 0;
+}
diff --git a/src/webcam/src/systick.c b/src/webcam/src/systick.c
new file mode 100644
index 000000000..f31efe437
--- /dev/null
+++ b/src/webcam/src/systick.c
@@ -0,0 +1,21 @@
+#include STM32_HAL_H
+#include "stdint.h"
+#include "stdbool.h"
+#include "systick.h"
+
+void systick_sleep(volatile uint32_t ms)
+{
+ volatile uint32_t curr_ticks = HAL_GetTick();
+ while ((HAL_GetTick() - curr_ticks) < ms) {
+ __WFI();
+ }
+}
+
+uint32_t systick_current_millis()
+{
+ return HAL_GetTick();
+}
+
+bool sys_tick_has_passed(uint32_t start_tick, uint32_t delay_ms) {
+ return HAL_GetTick() - start_tick >= delay_ms;
+}
diff --git a/src/webcam/src/usbd_conf.c b/src/webcam/src/usbd_conf.c
new file mode 100644
index 000000000..f38559f94
--- /dev/null
+++ b/src/webcam/src/usbd_conf.c
@@ -0,0 +1,522 @@
+/**
+ ******************************************************************************
+ * @file USB_Device/CDC_Standalone/Src/usbd_conf.c
+ * @author MCD Application Team
+ * @version V1.2.2
+ * @date 25-May-2015
+ * @brief This file implements the USB Device library callbacks and MSP
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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 STM32_HAL_H
+#include "stm32_hal_legacy.h"
+#include "usbd_core.h"
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+PCD_HandleTypeDef hpcd;
+
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/*******************************************************************************
+ PCD BSP Routines
+*******************************************************************************/
+/**
+ * @brief Initializes the PCD MSP.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ if(hpcd->Instance == USB_OTG_FS)
+ {
+ /* Configure USB FS GPIOs */
+ __GPIOA_CLK_ENABLE();
+
+ GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /* Configure VBUS Pin */
+ // USB VBUS detect pin is always A9
+ GPIO_InitStruct.Pin = GPIO_PIN_9;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+#if 0 //defined(MICROPY_HW_USB_OTG_ID_PIN)
+ // Not used
+ // USB ID pin is always A10
+ GPIO_InitStruct.Pin = GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+#endif
+
+ #if defined(MCU_SERIES_H7)
+ // Keep USB clock running during sleep or else __WFI() will disable the USB
+ __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_ENABLE();
+ __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
+ #endif
+
+ /* Enable USB FS Clocks */
+ __USB_OTG_FS_CLK_ENABLE();
+
+ /* Set USBFS Interrupt priority */
+ HAL_NVIC_SetPriority(OTG_FS_IRQn, 6, 0);
+
+ /* Enable USBFS Interrupt */
+ HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
+ }
+}
+/**
+ * @brief DeInitializes the PCD MSP.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
+{
+ if(hpcd->Instance == USB_OTG_FS)
+ {
+ /* Disable USB FS Clocks */
+ __USB_OTG_FS_CLK_DISABLE();
+ __SYSCFG_CLK_DISABLE();
+ }
+ #if defined(USE_USB_HS)
+ else if(hpcd->Instance == USB_OTG_HS)
+ {
+ /* Disable USB FS Clocks */
+ __USB_OTG_HS_CLK_DISABLE();
+ __SYSCFG_CLK_DISABLE();
+ }
+ #endif
+}
+
+
+/*******************************************************************************
+ LL Driver Callbacks (PCD -> USB Device Library)
+*******************************************************************************/
+
+
+/**
+ * @brief Setup stage callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
+{
+ USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup);
+}
+
+/**
+ * @brief Data Out stage callback.
+ * @param hpcd: PCD handle
+ * @param epnum: Endpoint Number
+ * @retval None
+ */
+void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ USBD_LL_DataOutStage(hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
+}
+
+/**
+ * @brief Data In stage callback.
+ * @param hpcd: PCD handle
+ * @param epnum: Endpoint Number
+ * @retval None
+ */
+void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ USBD_LL_DataInStage(hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
+}
+
+/**
+ * @brief SOF callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
+{
+ USBD_LL_SOF(hpcd->pData);
+}
+
+/**
+ * @brief Reset callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
+{
+ USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
+
+ /* Set USB Current Speed */
+ switch(hpcd->Init.speed)
+ {
+ case PCD_SPEED_HIGH:
+ speed = USBD_SPEED_HIGH;
+ break;
+
+ case PCD_SPEED_FULL:
+ speed = USBD_SPEED_FULL;
+ break;
+
+ default:
+ speed = USBD_SPEED_FULL;
+ break;
+ }
+ USBD_LL_SetSpeed(hpcd->pData, speed);
+
+ /* Reset Device */
+ USBD_LL_Reset(hpcd->pData);
+}
+
+/**
+ * @brief Suspend callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
+{
+ USBD_LL_Suspend(hpcd->pData);
+}
+
+/**
+ * @brief Resume callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
+{
+ USBD_LL_Resume(hpcd->pData);
+}
+
+/**
+ * @brief ISOC Out Incomplete callback.
+ * @param hpcd: PCD handle
+ * @param epnum: Endpoint Number
+ * @retval None
+ */
+void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ USBD_LL_IsoOUTIncomplete(hpcd->pData, epnum);
+}
+
+/**
+ * @brief ISOC In Incomplete callback.
+ * @param hpcd: PCD handle
+ * @param epnum: Endpoint Number
+ * @retval None
+ */
+void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ USBD_LL_IsoINIncomplete(hpcd->pData, epnum);
+}
+
+/**
+ * @brief Connect callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
+{
+ USBD_HandleTypeDef *pdev = hpcd->pData;
+ pdev->dev_connection_status = 1;
+ USBD_LL_DevConnected(hpcd->pData);
+}
+
+/**
+ * @brief Disconnect callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
+{
+ USBD_HandleTypeDef *pdev = hpcd->pData;
+ pdev->dev_connection_status = 0;
+ USBD_LL_DevDisconnected(hpcd->pData);
+}
+
+/*******************************************************************************
+ LL Driver Interface (USB Device Library --> PCD)
+*******************************************************************************/
+/**
+ * @brief Initializes the Low Level portion of the Device driver.
+ * @param pdev: Device handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
+{
+ /* Change Systick prioity */
+ NVIC_SetPriority (SysTick_IRQn, 0);
+
+#ifdef USE_USB_FS
+ /*Set LL Driver parameters */
+ hpcd.Instance = USB_OTG_FS;
+ hpcd.Init.dev_endpoints = 3;
+ hpcd.Init.use_dedicated_ep1 = 0;
+ hpcd.Init.ep0_mps = DEP0CTL_MPS_64;
+ hpcd.Init.dma_enable = 0;
+ hpcd.Init.low_power_enable = 0;
+ hpcd.Init.phy_itface = PCD_PHY_EMBEDDED;
+ hpcd.Init.Sof_enable = 1;
+ hpcd.Init.speed = PCD_SPEED_FULL;
+ hpcd.Init.vbus_sensing_enable = 1;
+ /* Link The driver to the stack */
+ hpcd.pData = pdev;
+ pdev->pData = &hpcd;
+ /*Initialize LL Driver */
+ HAL_PCD_Init(&hpcd);
+
+ HAL_PCDEx_SetRxFiFo(&hpcd, 0x2E);
+ HAL_PCDEx_SetTxFiFo(&hpcd, 0, 0x20);
+ HAL_PCDEx_SetTxFiFo(&hpcd, 1, 0xF2);
+
+
+#endif
+#ifdef USE_USB_HS
+ /*Set LL Driver parameters */
+ hpcd.Instance = USB_OTG_HS;
+ hpcd.Init.dev_endpoints = 6;
+ hpcd.Init.use_dedicated_ep1 = 0;
+ hpcd.Init.ep0_mps = 0x40;
+
+ /* Be aware that enabling USB-DMA mode will result in data being sent only by
+ multiple of 4 packet sizes. This is due to the fact that USB-DMA does
+ not allow sending data from non word-aligned addresses.
+ For this specific application, it is advised to not enable this option
+ unless required. */
+ hpcd.Init.dma_enable = 0;
+
+ hpcd.Init.low_power_enable = 0;
+ hpcd.Init.phy_itface = PCD_PHY_ULPI;
+ hpcd.Init.Sof_enable = 0;
+ hpcd.Init.speed = PCD_SPEED_HIGH;
+ hpcd.Init.vbus_sensing_enable = 1;
+ /* Link The driver to the stack */
+ hpcd.pData = pdev;
+ pdev->pData = &hpcd;
+ /*Initialize LL Driver */
+ HAL_PCD_Init(&hpcd);
+
+ HAL_PCDEx_SetRxFiFo(&hpcd, 0x200);
+ HAL_PCDEx_SetTxFiFo(&hpcd, 0, 0x80);
+ HAL_PCDEx_SetTxFiFo(&hpcd, 1, 0x174);
+
+
+#endif
+ return USBD_OK;
+}
+
+/**
+ * @brief De-Initializes the Low Level portion of the Device driver.
+ * @param pdev: Device handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
+{
+ HAL_PCD_DeInit(pdev->pData);
+ return USBD_OK;
+}
+
+/**
+ * @brief Starts the Low Level portion of the Device driver.
+ * @param pdev: Device handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
+{
+ HAL_PCD_Start(pdev->pData);
+ return USBD_OK;
+}
+
+/**
+ * @brief Stops the Low Level portion of the Device driver.
+ * @param pdev: Device handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
+{
+ HAL_PCD_Stop(pdev->pData);
+ return USBD_OK;
+}
+
+/**
+ * @brief Opens an endpoint of the Low Level Driver.
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @param ep_type: Endpoint Type
+ * @param ep_mps: Endpoint Max Packet Size
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,
+ uint8_t ep_addr,
+ uint8_t ep_type,
+ uint16_t ep_mps)
+{
+ HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
+ return USBD_OK;
+}
+
+/**
+ * @brief Closes an endpoint of the Low Level Driver.
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+ HAL_PCD_EP_Close(pdev->pData, ep_addr);
+ return USBD_OK;
+}
+
+/**
+ * @brief Flushes an endpoint of the Low Level Driver.
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+ HAL_PCD_EP_Flush(pdev->pData, ep_addr);
+ return USBD_OK;
+}
+
+/**
+ * @brief Sets a Stall condition on an endpoint of the Low Level Driver.
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+ HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
+ return USBD_OK;
+}
+
+/**
+ * @brief Clears a Stall condition on an endpoint of the Low Level Driver.
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+ HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
+ return USBD_OK;
+}
+
+/**
+ * @brief Returns Stall condition.
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @retval Stall (1: yes, 0: No)
+ */
+uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+ PCD_HandleTypeDef *hpcd = pdev->pData;
+
+ if((ep_addr & 0x80) == 0x80)
+ {
+ return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
+ }
+ else
+ {
+ return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
+ }
+}
+
+/**
+ * @brief Assigns an USB address to the device
+ * @param pdev: Device handle
+ * @param dev_addr: USB address
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
+{
+ HAL_PCD_SetAddress(pdev->pData, dev_addr);
+ return USBD_OK;
+}
+
+/**
+ * @brief Transmits data over an endpoint
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @param pbuf: Pointer to data to be sent
+ * @param size: Data size
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev,
+ uint8_t ep_addr,
+ uint8_t *pbuf,
+ uint16_t size)
+{
+ HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
+ return USBD_OK;
+}
+
+/**
+ * @brief Prepares an endpoint for reception
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @param pbuf:pointer to data to be received
+ * @param size: data size
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
+ uint8_t ep_addr,
+ uint8_t *pbuf,
+ uint16_t size)
+{
+ HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
+ return USBD_OK;
+}
+
+/**
+ * @brief Returns the last transfered packet size.
+ * @param pdev: Device handle
+ * @param ep_addr: Endpoint Number
+ * @retval Recived Data Size
+ */
+uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
+{
+ return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr);
+}
+
+/**
+ * @brief Delay routine for the USB Device Library
+ * @param Delay: Delay in ms
+ * @retval None
+ */
+void USBD_LL_Delay(uint32_t Delay)
+{
+ HAL_Delay(Delay);
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/src/usbd_core.c b/src/webcam/src/usbd_core.c
new file mode 100644
index 000000000..66acf1ebd
--- /dev/null
+++ b/src/webcam/src/usbd_core.c
@@ -0,0 +1,554 @@
+/**
+ ******************************************************************************
+ * @file usbd_core.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the USBD core functions.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * 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"
+
+/** @addtogroup STM32_USBD_DEVICE_LIBRARY
+* @{
+*/
+
+
+/** @defgroup USBD_CORE
+* @brief usbd core module
+* @{
+*/
+
+/** @defgroup USBD_CORE_Private_TypesDefinitions
+* @{
+*/
+/**
+* @}
+*/
+
+
+/** @defgroup USBD_CORE_Private_Defines
+* @{
+*/
+
+/**
+* @}
+*/
+
+
+/** @defgroup USBD_CORE_Private_Macros
+* @{
+*/
+/**
+* @}
+*/
+
+
+
+
+/** @defgroup USBD_CORE_Private_FunctionPrototypes
+* @{
+*/
+
+/**
+* @}
+*/
+
+/** @defgroup USBD_CORE_Private_Variables
+* @{
+*/
+
+/**
+* @}
+*/
+
+/** @defgroup USBD_CORE_Private_Functions
+* @{
+*/
+
+/**
+* @brief USBD_Init
+* Initailizes the device stack and load the class driver
+* @param pdev: device instance
+* @param core_address: USB OTG core ID
+* @param pdesc: Descriptor structure address
+* @param id: Low level core index
+* @retval None
+*/
+USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id)
+{
+ /* Check whether the USB Host handle is valid */
+ if(pdev == NULL)
+ {
+ USBD_ErrLog("Invalid Device handle");
+ return USBD_FAIL;
+ }
+
+ /* Unlink previous class*/
+ if(pdev->pClass != NULL)
+ {
+ pdev->pClass = NULL;
+ }
+
+ /* Assign USBD Descriptors */
+ if(pdesc != NULL)
+ {
+ pdev->pDesc = pdesc;
+ }
+
+ /* Set Device initial State */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ pdev->id = id;
+ /* Initialize low level driver */
+ USBD_LL_Init(pdev);
+
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_DeInit
+* Re-Initialize th device library
+* @param pdev: device instance
+* @retval status: status
+*/
+USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
+{
+ /* Set Default State */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+
+ /* Free Class Resources */
+ pdev->pClass->DeInit(pdev, pdev->dev_config);
+
+ /* Stop the low level driver */
+ USBD_LL_Stop(pdev);
+
+ /* Initialize low level driver */
+ USBD_LL_DeInit(pdev);
+
+ return USBD_OK;
+}
+
+
+/**
+ * @brief USBD_RegisterClass
+ * Link class driver to Device Core.
+ * @param pDevice : Device Handle
+ * @param pclass: Class handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
+{
+ USBD_StatusTypeDef status = USBD_OK;
+ if(pclass != 0)
+ {
+ /* link the class tgo the USB Device handle */
+ pdev->pClass = pclass;
+ status = USBD_OK;
+ }
+ else
+ {
+ USBD_ErrLog("Invalid Class handle");
+ status = USBD_FAIL;
+ }
+
+ return status;
+}
+
+/**
+ * @brief USBD_Start
+ * Start the USB Device Core.
+ * @param pdev: Device Handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev)
+{
+
+ /* Start the low level driver */
+ USBD_LL_Start(pdev);
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_Stop
+ * Stop the USB Device Core.
+ * @param pdev: Device Handle
+ * @retval USBD Status
+ */
+USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev)
+{
+ /* Free Class Resources */
+ pdev->pClass->DeInit(pdev, pdev->dev_config);
+
+ /* Stop the low level driver */
+ USBD_LL_Stop(pdev);
+
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_RunTestMode
+* Launch test mode process
+* @param pdev: device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev)
+{
+ return USBD_OK;
+}
+
+
+/**
+* @brief USBD_SetClassConfig
+* Configure device and start the interface
+* @param pdev: device instance
+* @param cfgidx: configuration index
+* @retval status
+*/
+
+USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+ USBD_StatusTypeDef ret = USBD_FAIL;
+
+ if(pdev->pClass != NULL)
+ {
+ /* Set configuration and Start the Class*/
+ if(pdev->pClass->Init(pdev, cfgidx) == 0)
+ {
+ ret = USBD_OK;
+ }
+ }
+ return ret;
+}
+
+/**
+* @brief USBD_ClrClassConfig
+* Clear current configuration
+* @param pdev: device instance
+* @param cfgidx: configuration index
+* @retval status: USBD_StatusTypeDef
+*/
+USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+ /* Clear configuration and Deinitialize the Class process*/
+ pdev->pClass->DeInit(pdev, cfgidx);
+ return USBD_OK;
+}
+
+
+/**
+* @brief USBD_SetupStage
+* Handle the setup stage
+* @param pdev: device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
+{
+
+ USBD_ParseSetupRequest(&pdev->request, psetup);
+
+ pdev->ep0_state = USBD_EP0_SETUP;
+ pdev->ep0_data_len = pdev->request.wLength;
+
+ switch (pdev->request.bmRequest & 0x1F)
+ {
+ case USB_REQ_RECIPIENT_DEVICE:
+ USBD_StdDevReq (pdev, &pdev->request);
+ break;
+
+ case USB_REQ_RECIPIENT_INTERFACE:
+ USBD_StdItfReq(pdev, &pdev->request);
+ break;
+
+ case USB_REQ_RECIPIENT_ENDPOINT:
+ USBD_StdEPReq(pdev, &pdev->request);
+ break;
+
+ default:
+ USBD_LL_StallEP(pdev , pdev->request.bmRequest & 0x80);
+ break;
+ }
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_DataOutStage
+* Handle data OUT stage
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata)
+{
+ USBD_EndpointTypeDef *pep;
+
+ if(epnum == 0)
+ {
+ pep = &pdev->ep_out[0];
+
+ if ( pdev->ep0_state == USBD_EP0_DATA_OUT)
+ {
+ if(pep->rem_length > pep->maxpacket)
+ {
+ pep->rem_length -= pep->maxpacket;
+
+ USBD_CtlContinueRx (pdev,
+ pdata,
+ MIN(pep->rem_length ,pep->maxpacket));
+ }
+ else
+ {
+ if((pdev->pClass->EP0_RxReady != NULL)&&
+ (pdev->dev_state == USBD_STATE_CONFIGURED))
+ {
+ pdev->pClass->EP0_RxReady(pdev);
+ }
+ USBD_CtlSendStatus(pdev);
+ }
+ }
+ }
+ else if((pdev->pClass->DataOut != NULL)&&
+ (pdev->dev_state == USBD_STATE_CONFIGURED))
+ {
+ pdev->pClass->DataOut(pdev, epnum);
+ }
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_DataInStage
+* Handle data in stage
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata)
+{
+ USBD_EndpointTypeDef *pep;
+
+ if(epnum == 0)
+ {
+ pep = &pdev->ep_in[0];
+
+ if ( pdev->ep0_state == USBD_EP0_DATA_IN)
+ {
+ if(pep->rem_length > pep->maxpacket)
+ {
+ pep->rem_length -= pep->maxpacket;
+
+ USBD_CtlContinueSendData (pdev,
+ pdata,
+ pep->rem_length);
+ }
+ else
+ { /* last packet is MPS multiple, so send ZLP packet */
+ if((pep->total_length % pep->maxpacket == 0) &&
+ (pep->total_length >= pep->maxpacket) &&
+ (pep->total_length < pdev->ep0_data_len ))
+ {
+
+ USBD_CtlContinueSendData(pdev , NULL, 0);
+ pdev->ep0_data_len = 0;
+ }
+ else
+ {
+ if((pdev->pClass->EP0_TxSent != NULL)&&
+ (pdev->dev_state == USBD_STATE_CONFIGURED))
+ {
+ pdev->pClass->EP0_TxSent(pdev);
+ }
+ USBD_CtlReceiveStatus(pdev);
+ }
+ }
+ }
+ if (pdev->dev_test_mode == 1)
+ {
+ USBD_RunTestMode(pdev);
+ pdev->dev_test_mode = 0;
+ }
+ }
+ else if((pdev->pClass->DataIn != NULL)&&
+ (pdev->dev_state == USBD_STATE_CONFIGURED))
+ {
+ pdev->pClass->DataIn(pdev, epnum);
+ }
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_LL_Reset
+* Handle Reset event
+* @param pdev: device instance
+* @retval status
+*/
+
+USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
+{
+ /* Open EP0 OUT */
+ USBD_LL_OpenEP(pdev,
+ 0x00,
+ USBD_EP_TYPE_CTRL,
+ USB_MAX_EP0_SIZE);
+
+ pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
+
+ /* Open EP0 IN */
+ USBD_LL_OpenEP(pdev,
+ 0x80,
+ USBD_EP_TYPE_CTRL,
+ USB_MAX_EP0_SIZE);
+
+ pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
+ /* Upon Reset call usr call back */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+
+ if (pdev->pClassData)
+ pdev->pClass->DeInit(pdev, pdev->dev_config);
+
+
+ return USBD_OK;
+}
+
+
+
+
+/**
+* @brief USBD_LL_Reset
+* Handle Reset event
+* @param pdev: device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed)
+{
+ pdev->dev_speed = speed;
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_Suspend
+* Handle Suspend event
+* @param pdev: device instance
+* @retval status
+*/
+
+USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
+{
+ pdev->dev_old_state = pdev->dev_state;
+ pdev->dev_state = USBD_STATE_SUSPENDED;
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_Resume
+* Handle Resume event
+* @param pdev: device instance
+* @retval status
+*/
+
+USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
+{
+ pdev->dev_state = pdev->dev_old_state;
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_SOF
+* Handle SOF event
+* @param pdev: device instance
+* @retval status
+*/
+
+USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
+{
+ if(pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ if(pdev->pClass->SOF != NULL)
+ {
+ pdev->pClass->SOF(pdev);
+ }
+ }
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_IsoINIncomplete
+* Handle iso in incomplete event
+* @param pdev: device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_IsoOUTIncomplete
+* Handle iso out incomplete event
+* @param pdev: device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_DevConnected
+* Handle device connection event
+* @param pdev: device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
+{
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_DevDisconnected
+* Handle device disconnection event
+* @param pdev: device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
+{
+ /* Free Class Resources */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ pdev->pClass->DeInit(pdev, pdev->dev_config);
+
+ return USBD_OK;
+}
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/src/webcam/src/usbd_ctlreq.c b/src/webcam/src/usbd_ctlreq.c
new file mode 100644
index 000000000..d0bd68086
--- /dev/null
+++ b/src/webcam/src/usbd_ctlreq.c
@@ -0,0 +1,769 @@
+/**
+ ******************************************************************************
+ * @file usbd_req.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides the standard USB requests following chapter 9.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * 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_ctlreq.h"
+#include "usbd_ioreq.h"
+
+
+/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup USBD_REQ
+ * @brief USB standard requests module
+ * @{
+ */
+
+/** @defgroup USBD_REQ_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Variables
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_FunctionPrototypes
+ * @{
+ */
+static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req);
+
+static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req);
+
+static void USBD_SetConfig(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req);
+
+static void USBD_GetConfig(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req);
+
+static void USBD_GetStatus(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req);
+
+static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req);
+
+static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req);
+
+static uint8_t USBD_GetLen(uint8_t *buf);
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_REQ_Private_Functions
+ * @{
+ */
+
+
+/**
+* @brief USBD_StdDevReq
+* Handle standard usb device requests
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+
+ switch (req->bRequest)
+ {
+ case USB_REQ_GET_DESCRIPTOR:
+
+ USBD_GetDescriptor (pdev, req) ;
+ break;
+
+ case USB_REQ_SET_ADDRESS:
+ USBD_SetAddress(pdev, req);
+ break;
+
+ case USB_REQ_SET_CONFIGURATION:
+ USBD_SetConfig (pdev , req);
+ break;
+
+ case USB_REQ_GET_CONFIGURATION:
+ USBD_GetConfig (pdev , req);
+ break;
+
+ case USB_REQ_GET_STATUS:
+ USBD_GetStatus (pdev , req);
+ break;
+
+
+ case USB_REQ_SET_FEATURE:
+ USBD_SetFeature (pdev , req);
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ USBD_ClrFeature (pdev , req);
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ break;
+ }
+
+ return ret;
+}
+
+/**
+* @brief USBD_StdItfReq
+* Handle standard usb interface requests
+* @param pdev: USB OTG device instance
+* @param req: usb request
+* @retval status
+*/
+USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
+{
+ USBD_StatusTypeDef ret = USBD_OK;
+
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_CONFIGURED:
+
+ if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES)
+ {
+ pdev->pClass->Setup (pdev, req);
+
+ if((req->wLength == 0)&& (ret == USBD_OK))
+ {
+ USBD_CtlSendStatus(pdev);
+ }
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ break;
+ }
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_StdEPReq
+* Handle standard usb endpoint requests
+* @param pdev: USB OTG device instance
+* @param req: usb request
+* @retval status
+*/
+USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req)
+{
+
+ uint8_t ep_addr;
+ USBD_StatusTypeDef ret = USBD_OK;
+ USBD_EndpointTypeDef *pep;
+ ep_addr = LOBYTE(req->wIndex);
+
+ switch (req->bRequest)
+ {
+
+ case USB_REQ_SET_FEATURE :
+
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if ((ep_addr != 0x00) && (ep_addr != 0x80))
+ {
+ USBD_LL_StallEP(pdev , ep_addr);
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if (req->wValue == USB_FEATURE_EP_HALT)
+ {
+ if ((ep_addr != 0x00) && (ep_addr != 0x80))
+ {
+ USBD_LL_StallEP(pdev , ep_addr);
+
+ }
+ }
+ pdev->pClass->Setup (pdev, req);
+ USBD_CtlSendStatus(pdev);
+
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ break;
+ }
+ break;
+
+ case USB_REQ_CLEAR_FEATURE :
+
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if ((ep_addr != 0x00) && (ep_addr != 0x80))
+ {
+ USBD_LL_StallEP(pdev , ep_addr);
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if (req->wValue == USB_FEATURE_EP_HALT)
+ {
+ if ((ep_addr & 0x7F) != 0x00)
+ {
+ USBD_LL_ClearStallEP(pdev , ep_addr);
+ pdev->pClass->Setup (pdev, req);
+ }
+ USBD_CtlSendStatus(pdev);
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ break;
+ }
+ break;
+
+ case USB_REQ_GET_STATUS:
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if ((ep_addr & 0x7F) != 0x00)
+ {
+ USBD_LL_StallEP(pdev , ep_addr);
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\
+ &pdev->ep_out[ep_addr & 0x7F];
+ if(USBD_LL_IsStallEP(pdev, ep_addr))
+ {
+ pep->status = 0x0001;
+ }
+ else
+ {
+ pep->status = 0x0000;
+ }
+
+ USBD_CtlSendData (pdev,
+ (uint8_t *)&pep->status,
+ 2);
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return ret;
+}
+/**
+* @brief USBD_GetDescriptor
+* Handle Get Descriptor requests
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+ uint16_t len;
+ uint8_t *pbuf;
+
+
+ switch (req->wValue >> 8)
+ {
+ case USB_DESC_TYPE_DEVICE:
+ pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len);
+ break;
+
+ case USB_DESC_TYPE_CONFIGURATION:
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ pbuf = (uint8_t *)pdev->pClass->GetHSConfigDescriptor(&len);
+ pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+ }
+ else
+ {
+ pbuf = (uint8_t *)pdev->pClass->GetFSConfigDescriptor(&len);
+ pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+ }
+ break;
+
+ case USB_DESC_TYPE_STRING:
+ switch ((uint8_t)(req->wValue))
+ {
+ case USBD_IDX_LANGID_STR:
+ pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len);
+ break;
+
+ case USBD_IDX_MFC_STR:
+ pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len);
+ break;
+
+ case USBD_IDX_PRODUCT_STR:
+ pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len);
+ break;
+
+ case USBD_IDX_SERIAL_STR:
+ pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len);
+ break;
+
+ case USBD_IDX_CONFIG_STR:
+ pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len);
+ break;
+
+ case USBD_IDX_INTERFACE_STR:
+ pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len);
+ break;
+
+ default:
+#if (USBD_SUPPORT_USER_STRING == 1)
+ pbuf = pdev->pClass->GetUsrStrDescriptor(pdev, (req->wValue) , &len);
+ break;
+#else
+ USBD_CtlError(pdev , req);
+ return;
+#endif
+ }
+ break;
+ case USB_DESC_TYPE_DEVICE_QUALIFIER:
+
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ pbuf = (uint8_t *)pdev->pClass->GetDeviceQualifierDescriptor(&len);
+ break;
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return;
+ }
+
+ case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ pbuf = (uint8_t *)pdev->pClass->GetOtherSpeedConfigDescriptor(&len);
+ pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
+ break;
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return;
+ }
+
+ default:
+ USBD_CtlError(pdev , req);
+ return;
+ }
+
+ if((len != 0)&& (req->wLength != 0))
+ {
+
+ len = MIN(len , req->wLength);
+
+ USBD_CtlSendData (pdev,
+ pbuf,
+ len);
+ }
+
+}
+
+/**
+* @brief USBD_SetAddress
+* Set device address
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+static void USBD_SetAddress(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+ uint8_t dev_addr;
+
+ if ((req->wIndex == 0) && (req->wLength == 0))
+ {
+ dev_addr = (uint8_t)(req->wValue) & 0x7F;
+
+ if (pdev->dev_state == USBD_STATE_CONFIGURED)
+ {
+ USBD_CtlError(pdev , req);
+ }
+ else
+ {
+ pdev->dev_address = dev_addr;
+ USBD_LL_SetUSBAddress(pdev, dev_addr);
+ USBD_CtlSendStatus(pdev);
+
+ if (dev_addr != 0)
+ {
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ }
+ else
+ {
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ }
+ }
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ }
+}
+
+/**
+* @brief USBD_SetConfig
+* Handle Set device configuration request
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+static void USBD_SetConfig(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+
+ static uint8_t cfgidx;
+
+ cfgidx = (uint8_t)(req->wValue);
+
+ if (cfgidx > USBD_MAX_NUM_CONFIGURATION )
+ {
+ USBD_CtlError(pdev , req);
+ }
+ else
+ {
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ if (cfgidx)
+ {
+ pdev->dev_config = cfgidx;
+ pdev->dev_state = USBD_STATE_CONFIGURED;
+ if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL)
+ {
+ USBD_CtlError(pdev , req);
+ return;
+ }
+ USBD_CtlSendStatus(pdev);
+ }
+ else
+ {
+ USBD_CtlSendStatus(pdev);
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if (cfgidx == 0)
+ {
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ pdev->dev_config = cfgidx;
+ USBD_ClrClassConfig(pdev , cfgidx);
+ USBD_CtlSendStatus(pdev);
+
+ }
+ else if (cfgidx != pdev->dev_config)
+ {
+ /* Clear old configuration */
+ USBD_ClrClassConfig(pdev , pdev->dev_config);
+
+ /* set new configuration */
+ pdev->dev_config = cfgidx;
+ if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL)
+ {
+ USBD_CtlError(pdev , req);
+ return;
+ }
+ USBD_CtlSendStatus(pdev);
+ }
+ else
+ {
+ USBD_CtlSendStatus(pdev);
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ break;
+ }
+ }
+}
+
+/**
+* @brief USBD_GetConfig
+* Handle Get device configuration request
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+static void USBD_GetConfig(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+
+ if (req->wLength != 1)
+ {
+ USBD_CtlError(pdev , req);
+ }
+ else
+ {
+ switch (pdev->dev_state )
+ {
+ case USBD_STATE_ADDRESSED:
+ pdev->dev_default_config = 0;
+ USBD_CtlSendData (pdev,
+ (uint8_t *)&pdev->dev_default_config,
+ 1);
+ break;
+
+ case USBD_STATE_CONFIGURED:
+
+ USBD_CtlSendData (pdev,
+ (uint8_t *)&pdev->dev_config,
+ 1);
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ break;
+ }
+ }
+}
+
+/**
+* @brief USBD_GetStatus
+* Handle Get Status request
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+static void USBD_GetStatus(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+
+
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ case USBD_STATE_CONFIGURED:
+
+#if ( USBD_SELF_POWERED == 1)
+ pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
+#else
+ pdev->dev_config_status = 0;
+#endif
+
+ if (pdev->dev_remote_wakeup)
+ {
+ pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
+ }
+
+ USBD_CtlSendData (pdev,
+ (uint8_t *)& pdev->dev_config_status,
+ 2);
+ break;
+
+ default :
+ USBD_CtlError(pdev , req);
+ break;
+ }
+}
+
+
+/**
+* @brief USBD_SetFeature
+* Handle Set device feature request
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+static void USBD_SetFeature(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+
+ if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
+ {
+ pdev->dev_remote_wakeup = 1;
+ pdev->pClass->Setup (pdev, req);
+ USBD_CtlSendStatus(pdev);
+ }
+
+}
+
+
+/**
+* @brief USBD_ClrFeature
+* Handle clear device feature request
+* @param pdev: device instance
+* @param req: usb request
+* @retval status
+*/
+static void USBD_ClrFeature(USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+ switch (pdev->dev_state)
+ {
+ case USBD_STATE_ADDRESSED:
+ case USBD_STATE_CONFIGURED:
+ if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
+ {
+ pdev->dev_remote_wakeup = 0;
+ pdev->pClass->Setup (pdev, req);
+ USBD_CtlSendStatus(pdev);
+ }
+ break;
+
+ default :
+ USBD_CtlError(pdev , req);
+ break;
+ }
+}
+
+/**
+* @brief USBD_ParseSetupRequest
+* Copy buffer into setup structure
+* @param pdev: device instance
+* @param req: usb request
+* @retval None
+*/
+
+void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata)
+{
+ req->bmRequest = *(uint8_t *) (pdata);
+ req->bRequest = *(uint8_t *) (pdata + 1);
+ req->wValue = SWAPBYTE (pdata + 2);
+ req->wIndex = SWAPBYTE (pdata + 4);
+ req->wLength = SWAPBYTE (pdata + 6);
+
+}
+
+/**
+* @brief USBD_CtlError
+* Handle USB low level Error
+* @param pdev: device instance
+* @param req: usb request
+* @retval None
+*/
+
+void USBD_CtlError( USBD_HandleTypeDef *pdev ,
+ USBD_SetupReqTypedef *req)
+{
+ USBD_LL_StallEP(pdev , 0x80);
+ USBD_LL_StallEP(pdev , 0);
+}
+
+
+/**
+ * @brief USBD_GetString
+ * Convert Ascii string into unicode one
+ * @param desc : descriptor buffer
+ * @param unicode : Formatted string buffer (unicode)
+ * @param len : descriptor length
+ * @retval None
+ */
+void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
+{
+ uint8_t idx = 0;
+
+ if (desc != NULL)
+ {
+ *len = USBD_GetLen(desc) * 2 + 2;
+ unicode[idx++] = *len;
+ unicode[idx++] = USB_DESC_TYPE_STRING;
+
+ while (*desc != '\0')
+ {
+ unicode[idx++] = *desc++;
+ unicode[idx++] = 0x00;
+ }
+ }
+}
+
+/**
+ * @brief USBD_GetLen
+ * return the string length
+ * @param buf : pointer to the ascii string buffer
+ * @retval string length
+ */
+static uint8_t USBD_GetLen(uint8_t *buf)
+{
+ uint8_t len = 0;
+
+ while (*buf != '\0')
+ {
+ len++;
+ buf++;
+ }
+
+ return len;
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/src/usbd_desc.c b/src/webcam/src/usbd_desc.c
new file mode 100644
index 000000000..30d43f928
--- /dev/null
+++ b/src/webcam/src/usbd_desc.c
@@ -0,0 +1,214 @@
+/**
+ ******************************************************************************
+ * @file USB_Device/CDC_Standalone/Src/usbd_desc.c
+ * @author MCD Application Team
+ * @version V1.2.2
+ * @date 25-May-2015
+ * @brief This file provides the USBD descriptors and string formating method.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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 0x1209
+#define USBD_PID 0xabd1
+#define USBD_LANGID_STRING 0x409
+#define USBD_MANUFACTURER_STRING "OpenMV"
+#define USBD_PRODUCT_HS_STRING "OpenMV UVC in HS Mode"
+#define USBD_SERIALNUMBER_HS_STRING "000000000010"
+#define USBD_PRODUCT_FS_STRING "OpenMV UVC in FS Mode"
+#define USBD_SERIALNUMBER_FS_STRING "000000000011"
+#define USBD_CONFIGURATION_HS_STRING "UVC Config"
+#define USBD_INTERFACE_HS_STRING "UVC Interface"
+#define USBD_CONFIGURATION_FS_STRING "UVC Config"
+#define USBD_INTERFACE_FS_STRING "UVC Interface"
+
+
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
+#ifdef USB_SUPPORT_USER_STRING_DESC
+uint8_t *USBD_FS_USRStringDesc (USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
+#endif /* USB_SUPPORT_USER_STRING_DESC */
+
+/* Private variables ---------------------------------------------------------*/
+USBD_DescriptorsTypeDef FS_Desc = {
+ USBD_FS_DeviceDescriptor,
+ USBD_FS_LangIDStrDescriptor,
+ USBD_FS_ManufacturerStrDescriptor,
+ USBD_FS_ProductStrDescriptor,
+ USBD_FS_SerialStrDescriptor,
+ USBD_FS_ConfigStrDescriptor,
+ USBD_FS_InterfaceStrDescriptor,
+};
+
+/* USB Standard Device Descriptor */
+#if defined ( __ICCARM__ ) /*!< IAR Compiler */
+ #pragma data_alignment=4
+#endif
+__ALIGN_BEGIN uint8_t USBD_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
+ 0x12, /* bLength */
+ USB_DESC_TYPE_DEVICE, /* bDescriptorType */
+ 0x00, /* bcdUSB */
+ 0x02,
+ 0xef, /* bDeviceClass */
+ 0x02, /* bDeviceSubClass */
+ 0x01, /* 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 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 uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
+
+/**
+ * @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_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+ *length = sizeof(USBD_DeviceDesc);
+ return (uint8_t*)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_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+ *length = sizeof(USBD_LangIDDesc);
+ return (uint8_t*)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_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+ if(speed == 0) {
+ USBD_GetString((uint8_t *)USBD_PRODUCT_HS_STRING, USBD_StrDesc, length);
+ } else {
+ USBD_GetString((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_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+ USBD_GetString((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_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+ if(speed == USBD_SPEED_HIGH) {
+ USBD_GetString((uint8_t *)USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length);
+ } else {
+ USBD_GetString((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_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+ if(speed == USBD_SPEED_HIGH) {
+ USBD_GetString((uint8_t *)USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length);
+ } else {
+ USBD_GetString((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_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
+{
+ if(speed == 0) {
+ USBD_GetString((uint8_t *)USBD_INTERFACE_HS_STRING, USBD_StrDesc, length);
+ } else {
+ USBD_GetString((uint8_t *)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
+ }
+ return USBD_StrDesc;
+}
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/src/webcam/src/usbd_ioreq.c b/src/webcam/src/usbd_ioreq.c
new file mode 100644
index 000000000..41d4cbcc9
--- /dev/null
+++ b/src/webcam/src/usbd_ioreq.c
@@ -0,0 +1,236 @@
+/**
+ ******************************************************************************
+ * @file usbd_ioreq.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides the IO requests APIs for control endpoints.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * 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_ioreq.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup USBD_IOREQ
+ * @brief control I/O requests module
+ * @{
+ */
+
+/** @defgroup USBD_IOREQ_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_FunctionPrototypes
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_IOREQ_Private_Functions
+ * @{
+ */
+
+/**
+* @brief USBD_CtlSendData
+* send data on the ctl pipe
+* @param pdev: device instance
+* @param buff: pointer to data buffer
+* @param len: length of data to be sent
+* @retval status
+*/
+USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf,
+ uint16_t len)
+{
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = len;
+ pdev->ep_in[0].rem_length = len;
+ /* Start the transfer */
+ USBD_LL_Transmit (pdev, 0x00, pbuf, len);
+
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_CtlContinueSendData
+* continue sending data on the ctl pipe
+* @param pdev: device instance
+* @param buff: pointer to data buffer
+* @param len: length of data to be sent
+* @retval status
+*/
+USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf,
+ uint16_t len)
+{
+ /* Start the next transfer */
+ USBD_LL_Transmit (pdev, 0x00, pbuf, len);
+
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_CtlPrepareRx
+* receive data on the ctl pipe
+* @param pdev: USB OTG device instance
+* @param buff: pointer to data buffer
+* @param len: length of data to be received
+* @retval status
+*/
+USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf,
+ uint16_t len)
+{
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_DATA_OUT;
+ pdev->ep_out[0].total_length = len;
+ pdev->ep_out[0].rem_length = len;
+ /* Start the transfer */
+ USBD_LL_PrepareReceive (pdev,
+ 0,
+ pbuf,
+ len);
+
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_CtlContinueRx
+* continue receive data on the ctl pipe
+* @param pdev: USB OTG device instance
+* @param buff: pointer to data buffer
+* @param len: length of data to be received
+* @retval status
+*/
+USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuf,
+ uint16_t len)
+{
+
+ USBD_LL_PrepareReceive (pdev,
+ 0,
+ pbuf,
+ len);
+ return USBD_OK;
+}
+/**
+* @brief USBD_CtlSendStatus
+* send zero lzngth packet on the ctl pipe
+* @param pdev: USB OTG device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev)
+{
+
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_IN;
+
+ /* Start the transfer */
+ USBD_LL_Transmit (pdev, 0x00, NULL, 0);
+
+ return USBD_OK;
+}
+
+/**
+* @brief USBD_CtlReceiveStatus
+* receive zero lzngth packet on the ctl pipe
+* @param pdev: USB OTG device instance
+* @retval status
+*/
+USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev)
+{
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_OUT;
+
+ /* Start the transfer */
+ USBD_LL_PrepareReceive ( pdev,
+ 0,
+ NULL,
+ 0);
+
+ return USBD_OK;
+}
+
+
+/**
+* @brief USBD_GetRxCount
+* returns the received data length
+* @param pdev: USB OTG device instance
+* epnum: endpoint index
+* @retval Rx Data blength
+*/
+uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t ep_addr)
+{
+ return USBD_LL_GetRxDataSize(pdev, ep_addr);
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/src/usbd_uvc.c b/src/webcam/src/usbd_uvc.c
new file mode 100644
index 000000000..2f634294f
--- /dev/null
+++ b/src/webcam/src/usbd_uvc.c
@@ -0,0 +1,879 @@
+/**
+ ******************************************************************************
+ * @file usbd_cdc.c
+ * @author MCD Application Team
+ * @version V2.4.1
+ * @date 19-June-2015
+ * @brief This file provides the high layer firmware functions to manage the
+ * following functionalities of the USB UVC Class:
+ * - Initialization and Configuration of high and low layer
+ * - Enumeration as UVC Device (and enumeration for each implemented memory interface)
+ * - OUT/IN data transfer
+ * - Command IN transfer (class requests management)
+ * - Error management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * UVC Class Driver Description
+ * ===================================================================
+ * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices
+ * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus
+ * Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007"
+ * This driver implements the following aspects of the specification:
+ * - Device descriptor management
+ * - Configuration descriptor management
+ * - Enumeration as UVC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)
+ * - Requests management (as described in section 6.2 in specification)
+ * - Abstract Control Model compliant
+ * - Union Functional collection (using 1 IN endpoint for control)
+ * - Data interface class
+ *
+ * These aspects may be enriched or modified for a specific user application.
+ *
+ * This driver doesn't implement the following aspects of the specification
+ * (but it is possible to manage these features with some modifications on this driver):
+ * - Any class-specific aspect relative to communication classes should be managed by user application.
+ * - All communication classes other than PSTN are not managed
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2015 STMicroelectronics
+ *
+ * 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_uvc.h"
+#include "usbd_desc.h"
+#include "usbd_ctlreq.h"
+#include "usbd_types.h"
+#include "uvc_desc.h"
+
+static USBD_UVC_HandleTypeDef USBD_UVC_Handle;
+volatile uint8_t g_uvc_stream_status = 0;
+
+static uint8_t USBD_UVC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+static uint8_t USBD_UVC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
+static uint8_t USBD_UVC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
+static uint8_t USBD_UVC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
+static uint8_t USBD_UVC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
+static uint8_t USBD_UVC_SOF(USBD_HandleTypeDef *pdev);
+static uint8_t USBD_UVC_EP0_RxReady(USBD_HandleTypeDef *pdev);
+static uint8_t *USBD_UVC_GetFSCfgDesc(uint16_t *length);
+uint8_t *USBD_UVC_GetDeviceQualifierDescriptor(uint16_t *length);
+
+/* USB Standard Device Descriptor */
+__ALIGN_BEGIN static uint8_t USBD_UVC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = {
+ USB_LEN_DEV_QUALIFIER_DESC,
+ USB_DESC_TYPE_DEVICE_QUALIFIER,
+ 0x00,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x01,
+ 0x00,
+};
+
+/* UVC interface class callbacks structure */
+USBD_ClassTypeDef USBD_UVC = {
+ USBD_UVC_Init,
+ USBD_UVC_DeInit,
+ USBD_UVC_Setup,
+ NULL, /* EP0_TxSent, */
+ USBD_UVC_EP0_RxReady,
+ USBD_UVC_DataIn,
+ USBD_UVC_DataOut,
+ USBD_UVC_SOF,
+ NULL,
+ NULL,
+ USBD_UVC_GetFSCfgDesc,
+ USBD_UVC_GetFSCfgDesc,
+ USBD_UVC_GetFSCfgDesc,
+ USBD_UVC_GetDeviceQualifierDescriptor,
+};
+
+/* USB UVC device Configuration Descriptor */
+__ALIGN_BEGIN struct usbd_uvc_cfg USBD_UVC_CfgFSDesc __ALIGN_END = {
+ /* Configuration 1 */
+ .usb_configuration = {
+ .bLength = USB_LEN_CFG_DESC, // 9
+ .bDescriptorType = USB_DESC_TYPE_CONFIGURATION, // 2
+ .wTotalLength = sizeof(struct usbd_uvc_cfg),
+ .bNumInterfaces = 0x02, // 2
+ .bConfigurationValue = 0x01, // 1 ID of this configuration
+ .iConfiguration = 0x00, // 0 no description available
+ .bmAttributes = USB_CONFIG_BUS_POWERED , // 0x80 Bus Powered
+ .bMaxPower = USB_CONFIG_POWER_MA(100), // 100 mA
+ },
+
+ /*----------------- Video Association (Control + stream) ------------------*/
+
+ /* Interface Association Descriptor */
+ .usb_uvc_association = {
+ .bLength = USB_DT_INTERFACE_ASSOC_SIZE, // 8
+ .bDescriptorType = USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE, // 11
+ .bFirstInterface = 0x00, // 0
+ .bInterfaceCount = 0x02, // 2
+ .bFunctionClass = UVC_CC_VIDEO, // 14 Video
+ .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, // 3 Video Interface Collection
+ .bFunctionProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iFunction = 0x02, // 2
+ },
+
+ /*----------------- Video Association (Control + stream) ------------------*/
+
+ /* Interface Association Descriptor */
+ .usb_uvc_association = {
+ .bLength = USB_DT_INTERFACE_ASSOC_SIZE, // 8
+ .bDescriptorType = USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE, // 11
+ .bFirstInterface = 0x00, // 0
+ .bInterfaceCount = 0x02, // 2
+ .bFunctionClass = UVC_CC_VIDEO, // 14 Video
+ .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, // 3 Video Interface Collection
+ .bFunctionProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iFunction = 0x02, // 2
+ },
+
+
+ /*------------------ VideoControl Interface descriptor --------------------*/
+
+ /* Standard VC Interface Descriptor = interface 0 */
+ .uvc_vc_if_desc = {
+ .bLength = USB_LEN_IF_DESC, // 9
+ .bDescriptorType = USB_DESC_TYPE_INTERFACE, // 4
+ .bInterfaceNumber = USB_UVC_VCIF_NUM, // 0 index of this interface (VC)
+ .bAlternateSetting = 0x00, // 0 index of this setting
+ .bNumEndpoints = 0x01, // 1 endpoint
+ .bInterfaceClass = UVC_CC_VIDEO, // 14 Video
+ .bInterfaceSubClass = UVC_SC_VIDEOCONTROL, // 1 Video Control
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iInterface = 0x00,
+ },
+
+ /* Class-specific VC Interface Descriptor */
+ .ucv_vc_header = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, ucv_vc_header),
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VC_HEADER, // 1 (HEADER)
+ .bcdUVC = UVC_VERSION, // 1.10 or 1.00
+ .wTotalLength =
+ SIZEOF_M(struct usbd_uvc_cfg, ucv_vc_header) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_input_terminal) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_processing_unit) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_agc) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_oem) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_sys) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_vid) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad_2) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_cust) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_output_terminal), // header+units+terminals
+ .dwClockFrequency = 0x005B8D80, // 6.000000 MHz
+ .bInCollection = 0x01, // 1 one streaming interface
+ .baInterfaceNr = { 0x01 }, // 1 VS interface 1 belongs to this VC interface
+ },
+
+ /* Input Terminal Descriptor (Camera) */
+ .uvc_vc_input_terminal = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_input_terminal), // Descriptor size
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VC_INPUT_TERMINAL, // 2 (INPUT_TERMINAL)
+ .bTerminalID = VC_INPUT_TERMINAL_ID, // 1 ID of this Terminal
+ .wTerminalType = UVC_ITT_CAMERA, // 0x0201 Camera Sensor
+ .bAssocTerminal = 0x00, // 0 no Terminal associated
+ .iTerminal = 0x00, // 0 no description available
+ .wObjectiveFocalLengthMin = 0x0000, // 0
+ .wObjectiveFocalLengthMax = 0x0000, // 0
+ .wOcularFocalLength = 0x0000, // 0
+ .bControlSize = 0x03, // 2
+ .bmControls = { 0x00, 0x00, 0x00 }, // 0x0000 no controls supported
+ },
+
+ /* Processing Unit Descriptor */
+ .uvc_vc_processing_unit = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_processing_unit), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x05, // Processing Unit Descriptor type
+ .bUnitID = VC_CONTROL_PU_ID, // ID of this terminal
+ .bSourceID = 0x01, // Source ID : 1 : Connected to input terminal
+ .wMaxMultiplier = 0, // Digital multiplier
+ .bControlSize = 0x03, // Size of controls field for this terminal : 2 bytes
+ .bmControls = { 0x03, 0x00, 0x00 }, // Brightness and contrast
+ .iProcessing = 0x00, // String desc index : Not used
+ },
+
+ /* Extension Unit Descriptor */
+ .uvc_vc_xu_lep_agc = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_agc), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_AGC_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'a','g','c','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x14, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xff, 0xff, 0x0f, 0x00 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+ },
+
+ /* Extension Unit Descriptor */
+ .uvc_vc_xu_lep_oem = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_oem), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_OEM_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'o','e','m','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x1e, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xbf, 0xff, 0xff, 0x7f }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+ },
+
+ /* Extension Unit Descriptor */
+ .uvc_vc_xu_lep_rad = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_RAD_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'r','a','d','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 48, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x08, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xFF, 0xFF, 0xFF, 0x81, 0xFC, 0xCF, 0xFF, 0x03 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+ },
+
+ /* Extension Unit Descriptor */
+ .uvc_vc_xu_lep_rad_2 = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_rad_2), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_RAD_2_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'r','a','d','2',
+ '0','0','0','0'
+ },
+ .bNumControls = 27, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xf9, 0x9f, 0xff, 0x07 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+ },
+
+ /* Extension Unit Descriptor */
+ .uvc_vc_xu_lep_sys = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_sys), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_SYS_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 's','y','s','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x17, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xFF, 0xFF, 0x7F, 0x00 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+ },
+
+ /* Extension Unit Descriptor */
+ .uvc_vc_xu_lep_vid = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_vid), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_VID_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'v','i','d','-',
+ '0','0','0','0'
+ },
+ .bNumControls = 0x0e, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { 0xFF, 0x3F, 0x00, 0x00 }, // Registers 0x00 to 0x48
+ .iExtension = 0x00, // String desc index : Not used
+ },
+
+ /* Extension Unit Descriptor */
+ .uvc_vc_xu_lep_cust = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vc_xu_lep_cust), // Descriptor size
+ .bDescriptorType = 0x24, // Class specific interface desc type
+ .bDescriptorSubType = 0x06, // Extension Unit Descriptor type
+ .bUnitID = VC_CONTROL_XU_LEP_CUST_ID, // ID of this terminal
+ .guidExtensionCode = { // 16 byte GUID
+ 'p','t','1','-',
+ 'l','e','p','-',
+ 'c','u','s','t',
+ '0','0','0','0'
+ },
+ .bNumControls = CUST_CONTROL_END, // Number of controls in this terminal
+ .bNrInPins = 0x01, // Number of input pins in this terminal
+ .baSourceID = { 0x02 }, // Source ID : 2 : Connected to Proc Unit
+ .bControlSize = 0x04, // Size of controls field for this terminal : 1 byte
+ .bmControls = { (1 << CUST_CONTROL_END) - 1, 0, 0, 0 }, //
+ .iExtension = 0x00, // String desc index : Not used
+ },
+
+ /* Output Terminal Descriptor */
+ .uvc_vc_output_terminal = {
+ .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE, // 9
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL, // 3 (OUTPUT_TERMINAL)
+ .bTerminalID = VC_OUTPUT_TERMINAL_ID, // 2 ID of this Terminal
+ .wTerminalType = UVC_TT_STREAMING, // 0x0101 USB streaming terminal
+ .bAssocTerminal = 0x00, // 0 no Terminal assiciated
+ .bSourceID = 0x03, // 1 input pin connected to output pin unit 1
+ .iTerminal = 0x00, // 0 no description available
+ },
+
+ /* Standard Interrupt Endpoint Descriptor */
+ .uvc_vc_ep = {
+ .bLength = USB_DT_ENDPOINT_SIZE, // 7
+ .bDescriptorType = USB_DESC_TYPE_ENDPOINT, // 5 (ENDPOINT)
+ .bEndpointAddress = UVC_CMD_EP, // 0x82 EP 2 IN
+ .bmAttributes = USBD_EP_TYPE_INTR, // interrupt
+ .wMaxPacketSize = CMD_PACKET_SIZE, // 8 bytes status
+ .bInterval = 0x20, // poll at least every 32ms
+ },
+
+ /* Class-specific Interrupt Endpoint Descriptor */
+ .uvc_vc_cs_ep = {
+ .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE,
+ .bDescriptorType = UVC_CS_ENDPOINT,
+ .bDescriptorSubType = USBD_EP_TYPE_INTR,
+ .wMaxTransferSize = CMD_PACKET_SIZE,
+ },
+
+ /*-------------- Video Streaming (VS) Interface Descriptor ----------------*/
+
+ /* Standard VS Interface Descriptor = interface 1 */
+ // alternate setting 0 = Zero Bandwidth
+ .uvc_vs_if_alt0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE, // 9
+ .bDescriptorType = USB_DESC_TYPE_INTERFACE, // 4
+ .bInterfaceNumber = USB_UVC_VSIF_NUM, // 1 index of this interface
+ .bAlternateSetting = 0x00, // 0 index of this setting
+ .bNumEndpoints = 0x00, // 0 no EP used
+ .bInterfaceClass = UVC_CC_VIDEO, // 14 Video
+ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, // 2 Video Streaming
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iInterface = 0x00, // 0 no description available
+ },
+
+ /* Class-specific VS Header Descriptor (Input) */
+ .uvc_vs_input_header_desc = {
+ .bLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vs_input_header_desc),
+ .bDescriptorType = UVC_CS_INTERFACE, // 36 (INTERFACE)
+ .bDescriptorSubType = UVC_VS_INPUT_HEADER, // 1 (INPUT_HEADER)
+ .bNumFormats = VS_NUM_FORMATS, // number of format descriptors
+ .wTotalLength =
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vs_input_header_desc) +
+ SIZEOF_M(struct usbd_uvc_cfg, uvc_vs_frames_formats_desc),
+ .bEndpointAddress = UVC_IN_EP, // 0x83 EP 3 IN
+ .bmInfo = 0x00, // 0 no dynamic format change supported
+ .bTerminalLink = VC_OUTPUT_TERMINAL_ID, // 2 supplies terminal ID 2 (Output terminal)
+ .bStillCaptureMethod = 0x01, // 1 Host captures from video stream
+ .bTriggerSupport = 0x00, // 0 HW trigger supported for still image capture
+ .bTriggerUsage = 0x00, // 0 HW trigger initiate a still image capture
+ .bControlSize = 0x01, // 1 one byte bmaControls field size
+ .bmaControls = {
+ { 0x00 }, // bmaControls(0) 0 no VS specific controls
+ { 0x00 }, // bmaControls(1) 0 no VS specific controls
+ { 0x00 }, // bmaControls(2) 0 no VS specific controls
+ },
+ },
+
+ .uvc_vs_frames_formats_desc = {
+ .uvc_vs_frames_format_1 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(YUYV, 3),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_1, YUYV, 80, 60),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_2, YUYV, 160, 120),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_3, YUYV, 320, 240)},
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+ .uvc_vs_frames_format_2 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(GREY, 4),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_1, GREY, 80, 60),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_2, GREY, 160, 120),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_3, GREY, 320, 240),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_4, GREY, 640, 480)},
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+ .uvc_vs_frames_format_3 =
+ {
+ .uvc_vs_format = UVC_FORMAT_UNCOMPRESSED_DESCRIPTOR(RGB565, 3),
+ .uvc_vs_frame = { UVC_FRAME_FORMAT(VS_FRAME_INDEX_1, RGB565, 80, 60),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_2, RGB565, 160, 120),
+ UVC_FRAME_FORMAT(VS_FRAME_INDEX_3, RGB565, 320, 240)},
+ .uvc_vs_color = UVC_COLOR_MATCHING_DESCRIPTOR(),
+ },
+ },
+
+ /* Standard VS Interface Descriptor = interface 1 */
+ // alternate setting 1 = operational setting
+ .uvc_vs_if_alt1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE, // 9
+ .bDescriptorType = USB_DESC_TYPE_INTERFACE, // 4
+ .bInterfaceNumber = USB_UVC_VSIF_NUM, // 1 index of this interface
+ .bAlternateSetting = 0x01, // 1 index of this setting
+ .bNumEndpoints = 0x01, // 1 one EP used
+ .bInterfaceClass = UVC_CC_VIDEO, // 14 Video
+ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, // 2 Video Streaming
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_UNDEFINED, // 0 (protocol undefined)
+ .iInterface = 0x00, // 0 no description available
+ },
+
+ /* Standard VS Isochronous Video data Endpoint Descriptor */
+ .uvc_vs_if_alt1_ep = {
+ .bLength = USB_DT_ENDPOINT_SIZE, // 7
+ .bDescriptorType = USB_DESC_TYPE_ENDPOINT, // 5 (ENDPOINT)
+ .bEndpointAddress = UVC_IN_EP, // 0x83 EP 3 IN
+ .bmAttributes = USBD_EP_TYPE_ISOC, // 1 isochronous transfer type
+ .wMaxPacketSize = VIDEO_PACKET_SIZE,
+ .bInterval = 0x01, // 1 one frame interval
+ },
+
+};
+
+/**
+ * @brief USBD_UVC_Init
+ * Initialize the UVC interface
+ * @param pdev: device instance
+ * @param cfgidx: Configuration index
+ * @retval status
+ */
+static uint8_t USBD_UVC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+ uint8_t ret = 0;
+ USBD_UVC_HandleTypeDef *hcdc;
+
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ UVC_IN_EP,
+ USBD_EP_TYPE_ISOC,
+ VIDEO_PACKET_SIZE);
+
+ USBD_LL_OpenEP(pdev,
+ UVC_CMD_EP,
+ USBD_EP_TYPE_INTR,
+ CMD_PACKET_SIZE);
+
+
+ pdev->pClassData = &USBD_UVC_Handle;
+ hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ /* Init physical Interface components */
+ ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->Init();
+
+ /* Init Xfer states */
+ hcdc->TxState =0;
+ hcdc->RxState =0;
+ return ret;
+}
+
+/**
+ * @brief USBD_UVC_Init
+ * DeInitialize the UVC layer
+ * @param pdev: device instance
+ * @param cfgidx: Configuration index
+ * @retval status
+ */
+static uint8_t USBD_UVC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
+{
+ uint8_t ret = 0;
+
+ /* Open EP IN */
+ USBD_LL_CloseEP(pdev, UVC_IN_EP);
+
+ USBD_LL_CloseEP(pdev, UVC_CMD_EP);
+
+ /* DeInit physical Interface components */
+ if(pdev->pClassData != NULL) {
+ ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->DeInit();
+ //USBD_free(pdev->pClassData); //TODO
+ pdev->pClassData = NULL;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_UVC_Setup
+ * Handle the UVC specific requests
+ * @param pdev: instance
+ * @param req: usb requests
+ * @retval status
+ */
+static uint8_t USBD_UVC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ uint8_t ret = USBD_OK;
+ static uint8_t ifalt = 0;
+ USBD_UVC_HandleTypeDef *hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ switch (req->bmRequest & USB_REQ_TYPE_MASK) {
+ case USB_REQ_TYPE_CLASS :
+ if (req->wLength) {
+ // TODO: what to do with recipient as endpoint?
+ uint8_t address = (req->wIndex >> 0) & 0xff;
+ VC_TERMINAL_ID entity_id = (VC_TERMINAL_ID)((req->wIndex >> 8) & 0xff);
+ if (req->bmRequest & USB_REQ_READ_MASK) {
+ USBD_LL_FlushEP (pdev,USB_ENDPOINT_OUT(0));
+ if (address == USB_UVC_VSIF_NUM) {
+ ret = ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->VS_CtrlGet(req->bRequest,
+ (uint8_t *)hcdc->data, req->wLength, req->wIndex, req->wValue);
+ } else {
+ ret = ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->ControlGet(entity_id, req->bRequest,
+ (uint8_t *)hcdc->data, req->wLength, req->wIndex, req->wValue);
+ }
+
+ if (ret == USBD_OK) {
+ USBD_CtlSendData (pdev, (uint8_t *)hcdc->data, req->wLength);
+ } else {
+ USBD_CtlError (pdev, req);
+ }
+ } else {
+ hcdc->CmdOpCode = req->bRequest;
+ hcdc->CmdLength = req->wLength;
+ hcdc->CmdIndex = req->wIndex;
+ hcdc->CmdValue = req->wValue;
+ USBD_CtlPrepareRx (pdev, (uint8_t *)hcdc->data, req->wLength);
+ }
+ } else {
+ ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, (uint8_t*)req, 0, 0, 0);
+ }
+ break;
+
+ case USB_REQ_TYPE_STANDARD:
+ switch (req->bRequest) {
+ case USB_REQ_GET_DESCRIPTOR:
+ if( (req->wValue >> 8) == UVC_CS_DEVICE) {
+ USBD_CtlSendData (pdev, (uint8_t *)&USBD_UVC_CfgFSDesc.uvc_vc_if_desc, MIN(sizeof(USBD_UVC_CfgFSDesc), req->wLength));
+ } else {
+ USBD_CtlSendData (pdev, (uint8_t *)hcdc->data, req->wLength);
+ }
+ break;
+
+ case USB_REQ_GET_INTERFACE :
+ USBD_CtlSendData (pdev, &ifalt, 1);
+ break;
+
+ case USB_REQ_SET_INTERFACE :
+ if ((uint8_t)(req->wValue) < VIDEO_TOTAL_IF_NUM) {
+ ifalt = (uint8_t)(req->wValue);
+ // TODO: refactor this to callback user code instead of doing this here
+ if (ifalt == 1) {
+ g_uvc_stream_status = 1;
+ } else {
+ g_uvc_stream_status = 0;
+ }
+ } else {
+ /* Call the error management function (command will be nacked */
+ USBD_CtlError (pdev, req);
+ return USBD_FAIL;
+ }
+ break;
+ default:
+ return USBD_FAIL;
+ }
+ break;
+
+ default:
+ return USBD_FAIL;
+ break;
+ }
+ return ret;
+}
+
+/**
+ * @brief USBD_UVC_DataIn
+ * Data sent on non-control IN endpoint
+ * @param pdev: device instance
+ * @param epnum: endpoint number
+ * @retval status
+ */
+static uint8_t USBD_UVC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+ USBD_UVC_HandleTypeDef *hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ if(pdev->pClassData != NULL) {
+ hcdc->TxState = 0;
+ return USBD_OK;
+ } else {
+ return USBD_FAIL;
+ }
+}
+
+/**
+ * @brief USBD_UVC_DataOut
+ * Data received on non-control Out endpoint
+ * @param pdev: device instance
+ * @param epnum: endpoint number
+ * @retval status
+ */
+static uint8_t USBD_UVC_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+ USBD_UVC_HandleTypeDef *hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ /* Get the received data length */
+ hcdc->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 */
+ if(pdev->pClassData != NULL) {
+ ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength);
+ return USBD_OK;
+ } else {
+ return USBD_FAIL;
+ }
+}
+
+static uint8_t USBD_UVC_SOF (USBD_HandleTypeDef *pdev)
+{
+ if (g_uvc_stream_status == 1) {
+ USBD_LL_FlushEP(pdev, USB_ENDPOINT_IN(1));
+ USBD_LL_Transmit(pdev, USB_ENDPOINT_IN(1), (uint8_t*)0x0002, 2);//header
+ g_uvc_stream_status = 2;
+ }
+ return USBD_OK;
+}
+
+
+/**
+ * @brief USBD_UVC_DataOut
+ * Data received on non-control Out endpoint
+ * @param pdev: device instance
+ * @param epnum: endpoint number
+ * @retval status
+ */
+static uint8_t USBD_UVC_EP0_RxReady (USBD_HandleTypeDef *pdev)
+{
+ uint8_t ret = USBD_OK;
+ USBD_UVC_HandleTypeDef *hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ if((pdev->pUserData != NULL) && (hcdc->CmdOpCode != 0xFF))
+ {
+ uint8_t address = (hcdc->CmdIndex >> 0) & 0xff;
+ uint8_t entity_id = (hcdc->CmdIndex >> 8) & 0xff;
+
+ if (address == USB_UVC_VSIF_NUM) {
+ ret = ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->VS_CtrlSet(hcdc->CmdOpCode,
+ (uint8_t *)hcdc->data, hcdc->CmdLength, hcdc->CmdIndex, hcdc->CmdValue);
+ } else {
+ ret = ((USBD_UVC_ItfTypeDef *)pdev->pUserData)->ControlSet(entity_id, hcdc->CmdOpCode,
+ (uint8_t *)hcdc->data, hcdc->CmdLength, hcdc->CmdIndex, hcdc->CmdValue);
+ }
+
+ hcdc->CmdOpCode = 0xFF;
+ }
+ return ret;
+}
+
+/**
+ * @brief USBD_UVC_GetFSCfgDesc
+ * Return configuration descriptor
+ * @param speed : current device speed
+ * @param length : pointer data length
+ * @retval pointer to descriptor buffer
+ */
+static uint8_t *USBD_UVC_GetFSCfgDesc (uint16_t *length)
+{
+ *length = sizeof(USBD_UVC_CfgFSDesc);
+ return (uint8_t*)&USBD_UVC_CfgFSDesc;
+}
+
+/**
+* @brief DeviceQualifierDescriptor
+* return Device Qualifier descriptor
+* @param length : pointer data length
+* @retval pointer to descriptor buffer
+*/
+uint8_t *USBD_UVC_GetDeviceQualifierDescriptor (uint16_t *length)
+{
+ *length = sizeof (USBD_UVC_DeviceQualifierDesc);
+ return USBD_UVC_DeviceQualifierDesc;
+}
+
+/**
+* @brief USBD_UVC_RegisterInterface
+ * @param pdev: device instance
+ * @param fops: CD Interface callback
+ * @retval status
+ */
+uint8_t USBD_UVC_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_UVC_ItfTypeDef *fops)
+{
+ uint8_t ret = USBD_FAIL;
+ if(fops != NULL) {
+ pdev->pUserData= fops;
+ ret = USBD_OK;
+ }
+ return ret;
+}
+
+/**
+ * @brief USBD_UVC_SetTxBuffer
+ * @param pdev: device instance
+ * @param pbuff: Tx Buffer
+ * @retval status
+ */
+uint8_t USBD_UVC_SetTxBuffer (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuff,
+ uint16_t length)
+{
+ USBD_UVC_HandleTypeDef *hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ hcdc->TxBuffer = pbuff;
+ hcdc->TxLength = length;
+
+ return USBD_OK;
+}
+
+
+/**
+ * @brief USBD_UVC_SetRxBuffer
+ * @param pdev: device instance
+ * @param pbuff: Rx Buffer
+ * @retval status
+ */
+uint8_t USBD_UVC_SetRxBuffer (USBD_HandleTypeDef *pdev,
+ uint8_t *pbuff)
+{
+ USBD_UVC_HandleTypeDef *hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ hcdc->RxBuffer = pbuff;
+
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_UVC_DataOut
+ * Data received on non-control Out endpoint
+ * @param pdev: device instance
+ * @param epnum: endpoint number
+ * @retval status
+ */
+uint8_t USBD_UVC_TransmitPacket(USBD_HandleTypeDef *pdev)
+{
+ USBD_UVC_HandleTypeDef *hcdc = (USBD_UVC_HandleTypeDef*) pdev->pClassData;
+
+ if(pdev->pClassData != NULL)
+ {
+ if(hcdc->TxState == 0)
+ {
+ /* Tx Transfer in progress */
+ hcdc->TxState = 1;
+
+ /* Transmit next packet */
+ USBD_LL_Transmit(pdev,
+ UVC_IN_EP,
+ hcdc->TxBuffer,
+ hcdc->TxLength);
+
+ return USBD_OK;
+ }
+ else
+ {
+ return USBD_BUSY;
+ }
+ }
+ else
+ {
+ return USBD_FAIL;
+ }
+}
+
+
+/**
+ * @brief USBD_UVC_ReceivePacket
+ * prepare OUT Endpoint for reception
+ * @param pdev: device instance
+ * @retval status
+ */
+uint8_t USBD_UVC_ReceivePacket(USBD_HandleTypeDef *pdev)
+{
+ /* Suspend or Resume USB Out process */
+ if(pdev->pClassData != NULL)
+ {
+ /* Prepare Out endpoint to receive next packet */
+ // USBD_LL_PrepareReceive(pdev,
+ // UVC_OUT_EP,
+ // hcdc->RxBuffer,
+ // UVC_DATA_FS_OUT_PACKET_SIZE);
+ return USBD_OK;
+ }
+ else
+ {
+ return USBD_FAIL;
+ }
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/src/usbd_uvc_if.c b/src/webcam/src/usbd_uvc_if.c
new file mode 100644
index 000000000..e1c8fb8a4
--- /dev/null
+++ b/src/webcam/src/usbd_uvc_if.c
@@ -0,0 +1,398 @@
+/**
+ ******************************************************************************
+ * @file : usbd_cdc_if.c
+ * @brief :
+ ******************************************************************************
+ * COPYRIGHT(c) 2015 STMicroelectronics
+ *
+ * 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.
+ *
+ ******************************************************************************
+*/
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_uvc_if.h"
+#include "uvc_desc.h"
+
+/* Define size for the receive and transmit buffer over UVC */
+/* It's up to user to redefine and/or remove those define */
+#define APP_RX_DATA_SIZE 1024
+#define APP_TX_DATA_SIZE 1024
+
+/* Create buffer for reception and transmission */
+/* It's up to user to redefine and/or remove those define */
+/* Received Data over USB are stored in this buffer */
+uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
+
+/* Send Data over USB UVC are stored in this buffer */
+uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
+
+/* USB handle declaration */
+USBD_HandleTypeDef *hUsbDevice_0;
+
+extern USBD_HandleTypeDef hUsbDeviceFS;
+
+//data array for Video Probe and Commit
+__ALIGN_BEGIN struct uvc_streaming_control videoCommitControl __ALIGN_END =
+{
+ .bmHint = 0x00,
+ .bFormatIndex = VS_FMT_INDEX(YUYV),
+ .bFrameIndex = 0x01,
+ .dwFrameInterval = 0,
+ .wKeyFrameRate = 0,
+ .wPFrameRate = 0,
+ .wCompQuality = 0,
+ .wCompWindowSize = 0,
+ .wDelay = 0,
+ .dwMaxVideoFrameSize = MAX_FRAME_SIZE(640, 480, 8),
+ .dwMaxPayloadTransferSize = VIDEO_PACKET_SIZE,
+ .dwClockFrequency = 0,
+ .bmFramingInfo = 0,
+ .bPreferedVersion = 0,
+ .bMinVersion = 0,
+ .bMaxVersion = 0,
+};
+
+__ALIGN_BEGIN struct uvc_streaming_control videoProbeControl __ALIGN_END =
+{
+ .bmHint = 0x00,
+ .bFormatIndex = VS_FMT_INDEX(YUYV),
+ .bFrameIndex = 0x01,
+ .dwFrameInterval = 0,
+ .wKeyFrameRate = 0,
+ .wPFrameRate = 0,
+ .wCompQuality = 0,
+ .wCompWindowSize = 0,
+ .wDelay = 0,
+ .dwMaxVideoFrameSize = MAX_FRAME_SIZE(640, 480, 8),
+ .dwMaxPayloadTransferSize = VIDEO_PACKET_SIZE,
+ .dwClockFrequency = 0,
+ .bmFramingInfo = 0,
+ .bPreferedVersion = 0,
+ .bMinVersion = 0,
+ .bMaxVersion = 0,
+};
+
+static int8_t UVC_Init_FS (void);
+static int8_t UVC_DeInit_FS (void);
+static int8_t UVC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t index, uint16_t value);
+static int8_t UVC_VC_ControlGet (VC_TERMINAL_ID entity_id,
+ uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t index, uint16_t value);
+static int8_t UVC_VC_ControlSet (VC_TERMINAL_ID entity_id,
+ uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t index, uint16_t value);
+static int8_t UVC_VS_ControlGet(uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t index, uint16_t value);
+static int8_t UVC_VS_ControlSet(uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t index, uint16_t value);
+static int8_t UVC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
+
+USBD_UVC_ItfTypeDef USBD_Interface_fops_FS = {
+ .Init = UVC_Init_FS,
+ .DeInit = UVC_DeInit_FS,
+ .Control = UVC_Control,
+ .VS_CtrlGet = UVC_VS_ControlGet,
+ .VS_CtrlSet = UVC_VS_ControlSet,
+ .ControlGet = UVC_VC_ControlGet,
+ .ControlSet = UVC_VC_ControlSet,
+ .Receive = UVC_Receive_FS,
+};
+
+/**
+ * @brief UVC_Init_FS
+ * Initializes the UVC media low layer over the FS USB IP
+ * @param None
+ * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
+ */
+static int8_t UVC_Init_FS(void)
+{
+ hUsbDevice_0 = &hUsbDeviceFS;
+ /* Set Application Buffers */
+ USBD_UVC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, 0);
+ USBD_UVC_SetRxBuffer(hUsbDevice_0, UserRxBufferFS);
+ return (USBD_OK);
+}
+
+/**
+ * @brief UVC_DeInit_FS
+ * DeInitializes the UVC media low layer
+ * @param None
+ * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
+ */
+static int8_t UVC_DeInit_FS(void)
+{
+ return (USBD_OK);
+}
+
+static int8_t UVC_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t idx, uint16_t value)
+{
+ return USBD_OK;
+}
+
+/**
+ * @brief UVC_Control_FS
+ * Manage the UVC class requests
+ * @param cmd: Command code
+ * @param pbuf: Buffer containing command data (request parameters)
+ * @param length: Number of data to be sent (in bytes)
+ * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
+ */
+static int8_t UVC_VC_ControlGet(VC_TERMINAL_ID entity_id, uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t idx, uint16_t value)
+{
+ uint8_t cs_value = (value >> 8) & 0xFF;
+ (void) cs_value; //TODO
+
+ switch (entity_id) {
+ case VC_CONTROL_XU_LEP_AGC_ID:
+ case VC_CONTROL_XU_LEP_OEM_ID:
+ case VC_CONTROL_XU_LEP_RAD_ID:
+ case VC_CONTROL_XU_LEP_RAD_2_ID:
+ case VC_CONTROL_XU_LEP_SYS_ID:
+ case VC_CONTROL_XU_LEP_VID_ID:
+ case VC_CONTROL_XU_LEP_CUST_ID:
+ memset(pbuf, 0, length);
+ switch (cmd) {
+ case UVC_GET_DEF:
+ case UVC_GET_MIN:
+ break;
+ case UVC_GET_CUR:
+ if (length > 1) {
+ //VC_LEP_GetAttribute(entity_id, (cs_value - 1) << 2, pbuf, length);
+ }
+ break;
+ case UVC_GET_MAX:
+ //VC_LEP_GetMaxValue(entity_id, (cs_value - 1) << 2, pbuf, length);
+ break;
+ case UVC_GET_RES:
+ pbuf[0] = 1;
+ break;
+ case UVC_GET_LEN:
+ //VC_LEP_GetAttributeLen(entity_id, (cs_value - 1) << 2, (uint16_t*)pbuf);
+ break;
+ case UVC_GET_INFO:
+ pbuf[0] = UVC_CONTROL_CAP_GET | UVC_CONTROL_CAP_SET;
+ break;
+ default:
+ return USBD_FAIL;
+ }
+
+ break;
+
+ case VC_CONTROL_PU_ID:
+ switch (cmd) {
+ case UVC_GET_MIN:
+ pbuf[0] = 0;
+ break;
+ case UVC_GET_DEF:
+ case UVC_GET_CUR:
+ pbuf[0] = 128;
+ break;
+ case UVC_GET_MAX:
+ pbuf[0] = 255;
+ break;
+ case UVC_GET_RES:
+ pbuf[0] = 1;
+ break;
+ case UVC_GET_LEN:
+ pbuf[0] = 2;
+ break;
+ case UVC_GET_INFO:
+ pbuf[0] = UVC_CONTROL_CAP_GET | UVC_CONTROL_CAP_DISABLED;
+ break;
+ default:
+ return USBD_FAIL;
+ }
+
+ break;
+
+ default:
+ return USBD_FAIL;
+ }
+
+ return (USBD_OK);
+}
+
+static int8_t UVC_VC_ControlSet(VC_TERMINAL_ID entity_id, uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t idx, uint16_t value)
+{
+ uint8_t cs_value = (value >> 8) & 0xFF;
+ (void) cs_value;
+
+ switch (cmd) {
+ case UVC_SET_CUR:
+ break;
+ default:
+ return USBD_FAIL;
+ }
+
+ switch (entity_id) {
+ case VC_CONTROL_XU_LEP_AGC_ID:
+ case VC_CONTROL_XU_LEP_OEM_ID:
+ case VC_CONTROL_XU_LEP_RAD_ID:
+ case VC_CONTROL_XU_LEP_RAD_2_ID:
+ case VC_CONTROL_XU_LEP_SYS_ID:
+ case VC_CONTROL_XU_LEP_VID_ID:
+ case VC_CONTROL_XU_LEP_CUST_ID:
+ if (length == 1) {
+ //VC_LEP_RunCommand(entity_id, (cs_value - 1) << 2);
+ } else {
+ //VC_LEP_SetAttribute(entity_id, (cs_value - 1) << 2, pbuf, length);
+ }
+ break;
+ case VC_CONTROL_PU_ID:
+ break;
+ default:
+ return USBD_FAIL;
+ }
+
+ return (USBD_OK);
+}
+
+
+/**
+ * @brief UVC_Control_FS
+ * Manage the UVC class requests
+ * @param cmd: Command code
+ * @param pbuf: Buffer containing command data (request parameters)
+ * @param length: Number of data to be sent (in bytes)
+ * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
+ */
+static int8_t UVC_VS_ControlGet(uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t idx, uint16_t value)
+{
+ uint8_t cs_value = (value >> 8) & 0xFF;
+
+ switch (cmd) {
+ case UVC_GET_DEF:
+ case UVC_GET_CUR:
+ case UVC_GET_MIN:
+ case UVC_GET_MAX:
+ if(cs_value == UVC_VS_PROBE_CONTROL || cs_value == UVC_VS_STILL_PROBE_CONTROL) {
+ struct uvc_streaming_control *rtnBuf = (struct uvc_streaming_control*)pbuf;
+ memset(rtnBuf, 0, length);
+ rtnBuf->bFormatIndex = videoProbeControl.bFormatIndex;
+ rtnBuf->bFrameIndex = videoProbeControl.bFrameIndex;
+ rtnBuf->dwMaxPayloadTransferSize = VIDEO_PACKET_SIZE;
+ rtnBuf->dwFrameInterval = INTERVAL;
+
+ if (cmd == UVC_GET_DEF || cmd == UVC_GET_MIN || cmd == UVC_GET_MAX || cmd == UVC_GET_CUR) {
+ struct uvc_vs_frames_formats_descriptor *frames_formats;
+ struct UVC_FRAME_UNCOMPRESSED(1) *frame;
+ frames_formats = &USBD_UVC_CfgFSDesc.uvc_vs_frames_formats_desc;
+
+ switch (videoProbeControl.bFormatIndex) {
+ case VS_FMT_INDEX(YUYV):
+ frame = frames_formats->uvc_vs_frames_format_1.uvc_vs_frame;
+ break;
+ case VS_FMT_INDEX(GREY):
+ frame = frames_formats->uvc_vs_frames_format_2.uvc_vs_frame;
+ break;
+ case VS_FMT_INDEX(RGB565):
+ frame = frames_formats->uvc_vs_frames_format_3.uvc_vs_frame;
+ break;
+ default:
+ return USBD_FAIL;
+ }
+ rtnBuf->dwMaxVideoFrameSize = frame[videoProbeControl.bFrameIndex - 1].dwMaxVideoFrameBufferSize;
+ } else {
+ return USBD_FAIL;
+ }
+ } else if (cs_value == UVC_VS_COMMIT_CONTROL || cs_value == UVC_VS_STILL_COMMIT_CONTROL) {
+ // Commit Request
+ memcpy(pbuf, &videoCommitControl, MIN(sizeof(struct uvc_streaming_control), length));
+ } else {
+ return USBD_FAIL;
+ }
+ break;
+
+ default:
+ return USBD_FAIL;
+ }
+
+ return (USBD_OK);
+}
+
+static int8_t UVC_VS_ControlSet(uint8_t cmd, uint8_t* pbuf, uint16_t length, uint16_t idx, uint16_t value)
+{
+ uint8_t cs_value = (value >> 8) & 0xFF;
+
+ switch (cmd) {
+ case UVC_SET_CUR: {
+ struct uvc_streaming_control *rtnBuf = (struct uvc_streaming_control*)pbuf;
+ if (rtnBuf->bFormatIndex > VS_NUM_FORMATS) {
+ return USBD_FAIL;
+ }
+
+ if(cs_value == UVC_VS_PROBE_CONTROL || cs_value == UVC_VS_STILL_PROBE_CONTROL) {
+ memcpy(&videoProbeControl, pbuf, MIN(sizeof(struct uvc_streaming_control), length));
+ } else if (cs_value == UVC_VS_COMMIT_CONTROL || cs_value == UVC_VS_STILL_COMMIT_CONTROL) {
+ memcpy(&videoCommitControl, pbuf, MIN(sizeof(struct uvc_streaming_control), length));
+ } else {
+ return USBD_FAIL;
+ }
+ break;
+ }
+ default:
+ return USBD_FAIL;
+ }
+
+ return (USBD_OK);
+}
+
+/**
+ * @brief UVC_Receive_FS
+ * Data received over USB OUT endpoint are sent over UVC interface
+ * through this function.
+ *
+ * @note
+ * This function will block any OUT packet reception on USB endpoint
+ * untill exiting this function. If you exit this function before transfer
+ * is complete on UVC interface (ie. using DMA controller) it will result
+ * in receiving more data while previous ones are still not sent.
+ *
+ * @param Buf: Buffer of data to be received
+ * @param Len: Number of data received (in bytes)
+ * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
+ */
+static int8_t UVC_Receive_FS (uint8_t* Buf, uint32_t *Len)
+{
+ return (USBD_OK);
+}
+
+/**
+ * @brief UVC_Transmit_FS
+ * Data send over USB IN endpoint are sent over UVC interface
+ * through this function.
+ * @note
+ *
+ *
+ * @param Buf: Buffer of data to be send
+ * @param Len: Number of data to be send (in bytes)
+ * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
+ */
+uint8_t UVC_Transmit_FS(uint8_t* Buf, uint16_t Len)
+{
+ uint8_t result = USBD_OK;
+ HAL_NVIC_DisableIRQ(OTG_FS_IRQn);
+ USBD_UVC_SetTxBuffer(hUsbDevice_0, Buf, Len);
+ result = USBD_UVC_TransmitPacket(hUsbDevice_0);
+ HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
+ return result;
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/webcam/stm32fxxx.ld.S b/src/webcam/stm32fxxx.ld.S
new file mode 100755
index 000000000..b6c67c8d2
--- /dev/null
+++ b/src/webcam/stm32fxxx.ld.S
@@ -0,0 +1,172 @@
+/*
+ * This file is part of the OpenMV project.
+ * Copyright (c) 2013/2014 Ibrahim Abdelkader
+ * This work is licensed under the MIT license, see the file LICENSE for details.
+ *
+ * Linker script for STM32F4xx Devices.
+ *
+ */
+
+/* Entry Point */
+ENTRY(Reset_Handler)
+
+#include "omv_boardconfig.h"
+
+/* Specify the memory areas */
+MEMORY
+{
+ CCM (xrw) : ORIGIN = OMV_CCM_ORIGIN, LENGTH = OMV_CCM_LENGTH
+ SRAM1 (xrw) : ORIGIN = OMV_SRAM1_ORIGIN, LENGTH = OMV_SRAM1_LENGTH
+ #if defined(OMV_SRAM2_ORIGIN)
+ SRAM2 (xrw) : ORIGIN = OMV_SRAM2_ORIGIN, LENGTH = OMV_SRAM2_LENGTH
+ #endif
+ #if defined(OMV_SRAM3_ORIGIN)
+ SRAM3 (xrw) : ORIGIN = OMV_SRAM3_ORIGIN, LENGTH = OMV_SRAM3_LENGTH
+ #endif
+ #if defined(OMV_SRAM4_ORIGIN)
+ SRAM4 (xrw) : ORIGIN = OMV_SRAM4_ORIGIN, LENGTH = OMV_SRAM4_LENGTH
+ #endif
+ #if defined(OMV_AXI_SRAM_ORIGIN)
+ AXI_SRAM (xrw) : ORIGIN = OMV_AXI_SRAM_ORIGIN, LENGTH = OMV_AXI_SRAM_LENGTH
+ #endif
+ FLASH_TEXT (rx) : ORIGIN = OMV_TEXT_ORIGIN, LENGTH = OMV_TEXT_LENGTH
+}
+
+_estack = ORIGIN(OMV_MAIN_MEMORY) + LENGTH(OMV_MAIN_MEMORY);
+_ram_end = ORIGIN(OMV_MAIN_MEMORY) + LENGTH(OMV_MAIN_MEMORY);
+
+#if defined(OMV_FFS_MEMORY)
+_ffs_cache = ORIGIN(OMV_FFS_MEMORY);
+#endif
+
+#if defined(OMV_JPEG_MEMORY)
+_jpeg_buf = ORIGIN(OMV_JPEG_MEMORY);
+#endif
+
+_heap_size = OMV_HEAP_SIZE; /* required amount of heap */
+_stack_size = OMV_STACK_SIZE; /* minimum amount of stack */
+
+/* Define output sections */
+SECTIONS
+{
+ /* The program code and other data goes into FLASH */
+ .text :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector))// ISR table
+ . = ALIGN(4);
+ *(.text) // .text sections (code)
+ . = ALIGN(4);
+ *(.text*) // .text* sections (code)
+ . = ALIGN(4);
+ *(.rodata) // .rodata sections (constants, strings, etc.)
+ . = ALIGN(4);
+ *(.rodata*) // .rodata* sections (constants, strings, etc.)
+ . = ALIGN(4);
+ _etext = .; // define a global symbols at end of code
+ } >FLASH_TEXT
+
+ /* used by the startup to initialize data */
+ _sidata = .;
+
+ /* Main framebuffer memory */
+ .fb_memory (NOLOAD) :
+ {
+ . = ALIGN(4);
+ _fb_base = .;
+ . = . + OMV_FB_SIZE + OMV_FB_ALLOC_SIZE;
+
+ . = ALIGN(4);
+ _fballoc = .;
+
+ } >OMV_FB_MEMORY
+
+ /* Misc DMA buffers kept in uncachable region */
+ /* NOTE: on H7 DMA buffers are kept in cached AXI RAM and cache maintenance is performed */
+ .dma_memory (NOLOAD) :
+ {
+ . = ALIGN(4);
+ _line_buf = .; // Image line buffer.
+ . = . + OMV_LINE_BUF_SIZE;
+
+ . = ALIGN(4);
+ _msc_buf = .; // USB MSC bot data (2K)
+ . = . + OMV_MSC_BUF_SIZE;
+
+ . = ALIGN(4);
+ _vfs_buf = .; // VFS sturct + FATFS file buffer (around 624 bytes)
+ . = . + OMV_VFS_BUF_SIZE;
+
+ #if !defined(OMV_FFS_MEMORY)
+ . = ALIGN(4);
+ _ffs_cache = .; // Flash filesystem cache
+ . = . + OMV_FFS_BUF_SIZE;
+ #endif
+
+ #if !defined(OMV_JPEG_MEMORY)
+ . = ALIGN(4);
+ _jpeg_buf = .; // IDE JPEG buffer
+ . = . + OMV_JPEG_BUF_SIZE;
+ #endif
+
+ . = ALIGN(4);
+ *(.dma_buffer)
+
+ } >OMV_DMA_MEMORY
+
+ /* Initialized data sections */
+ .data : AT ( _sidata )
+ {
+ . = ALIGN(4);
+ _sdata = .; // Create a global symbol at data start
+ _ram_start = .;
+ *(.data) // .data sections
+
+ . = ALIGN(4);
+ *(.data*) // .data* sections
+
+ . = ALIGN(4);
+ _edata = .; // define a global symbol at data end
+ } >OMV_MAIN_MEMORY
+
+ /* Uninitialized data section */
+ . = ALIGN(4);
+ .bss (NOLOAD) :
+ {
+ . = ALIGN(4);
+ _sbss = .; // Used by the startup to initialize the .bss secion
+ __bss_start__ = _sbss;
+ *(.bss)
+
+ . = ALIGN(4);
+ *(.bss*)
+
+ . = ALIGN(4);
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .; // define a global symbol at bss end
+ _bss_end = .; // Used by gccollect
+ __bss_end__ = .;
+ } >OMV_MAIN_MEMORY
+
+ ._heap (NOLOAD) :
+ {
+ . = ALIGN(4);
+ _heap_start = .;
+ . = . + _heap_size;
+
+ . = ALIGN(4);
+ _heap_end = .;
+
+ } >OMV_MAIN_MEMORY
+
+ /* Make sure there is enough ram for the stack */
+ ._stack (NOLOAD) :
+ {
+ . = ALIGN(4);
+ . = . + _stack_size;
+ } >OMV_MAIN_MEMORY
+
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}