From e0c1928fde94387f0fc819eda16004c68ce164a6 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Wed, 6 Oct 2021 12:24:09 +0300 Subject: [PATCH] [FL-1857] New USB stack (#735) * libusb_stm32 USB stack test * USB: Add dual CDC mode * USB HID demo, added libusb_stm32 as submodule * Target F6/F7: remomve unused ll_usb Co-authored-by: n.minaylov Co-authored-by: Aleksandr Kutuzov --- .gitmodules | 3 + applications/applications.c | 5 + applications/applications.mk | 9 + applications/debug_tools/usb_test.c | 102 ++++ firmware/targets/f6/Inc/stm32.h | 52 ++ firmware/targets/f6/Src/stm32wbxx_it.c | 5 +- .../targets/f6/furi-hal/furi-hal-usb-cdc.c | 555 ++++++++++++++++++ .../targets/f6/furi-hal/furi-hal-usb-cdc_i.h | 7 + .../targets/f6/furi-hal/furi-hal-usb-hid.c | 264 +++++++++ firmware/targets/f6/furi-hal/furi-hal-usb.c | 164 ++++++ firmware/targets/f6/furi-hal/furi-hal-usb_i.h | 28 + firmware/targets/f6/furi-hal/furi-hal-vcp.c | 63 +- firmware/targets/f6/furi-hal/furi-hal-vcp_i.h | 4 +- .../targets/f6/furi-hal/furi-hal-version.c | 4 - firmware/targets/f6/furi-hal/furi-hal.c | 4 +- firmware/targets/f6/target.mk | 15 +- firmware/targets/f6/usb-glue/usb_device.c | 34 -- firmware/targets/f6/usb-glue/usb_device.h | 11 - firmware/targets/f6/usb-glue/usbd_cdc_if.c | 142 ----- firmware/targets/f6/usb-glue/usbd_cdc_if.h | 22 - firmware/targets/f6/usb-glue/usbd_conf.c | 506 ---------------- firmware/targets/f6/usb-glue/usbd_conf.h | 73 --- firmware/targets/f6/usb-glue/usbd_desc.c | 206 ------- firmware/targets/f6/usb-glue/usbd_desc.h | 19 - firmware/targets/f7/Inc/stm32.h | 52 ++ firmware/targets/f7/Src/stm32wbxx_it.c | 5 +- .../targets/f7/furi-hal/furi-hal-usb-cdc.c | 555 ++++++++++++++++++ .../targets/f7/furi-hal/furi-hal-usb-cdc_i.h | 7 + .../targets/f7/furi-hal/furi-hal-usb-hid.c | 264 +++++++++ firmware/targets/f7/furi-hal/furi-hal-usb.c | 164 ++++++ firmware/targets/f7/furi-hal/furi-hal-usb_i.h | 28 + firmware/targets/f7/furi-hal/furi-hal-vcp.c | 63 +- firmware/targets/f7/furi-hal/furi-hal-vcp_i.h | 4 +- .../targets/f7/furi-hal/furi-hal-version.c | 4 - firmware/targets/f7/furi-hal/furi-hal.c | 4 +- firmware/targets/f7/target.mk | 15 +- firmware/targets/f7/usb-glue/usb_device.c | 34 -- firmware/targets/f7/usb-glue/usb_device.h | 11 - firmware/targets/f7/usb-glue/usbd_cdc_if.c | 142 ----- firmware/targets/f7/usb-glue/usbd_cdc_if.h | 22 - firmware/targets/f7/usb-glue/usbd_conf.c | 506 ---------------- firmware/targets/f7/usb-glue/usbd_conf.h | 73 --- firmware/targets/f7/usb-glue/usbd_desc.c | 206 ------- firmware/targets/f7/usb-glue/usbd_desc.h | 19 - .../targets/furi-hal-include/furi-hal-usb.h | 21 + .../furi-hal-include/furi-hal-version.h | 5 + firmware/targets/furi-hal-include/furi-hal.h | 1 + lib/lib.mk | 4 + lib/libusb_stm32 | 1 + 49 files changed, 2387 insertions(+), 2120 deletions(-) mode change 100755 => 100644 applications/applications.c create mode 100644 applications/debug_tools/usb_test.c create mode 100644 firmware/targets/f6/Inc/stm32.h create mode 100644 firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c create mode 100644 firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h create mode 100644 firmware/targets/f6/furi-hal/furi-hal-usb-hid.c create mode 100644 firmware/targets/f6/furi-hal/furi-hal-usb.c create mode 100644 firmware/targets/f6/furi-hal/furi-hal-usb_i.h delete mode 100644 firmware/targets/f6/usb-glue/usb_device.c delete mode 100644 firmware/targets/f6/usb-glue/usb_device.h delete mode 100644 firmware/targets/f6/usb-glue/usbd_cdc_if.c delete mode 100644 firmware/targets/f6/usb-glue/usbd_cdc_if.h delete mode 100644 firmware/targets/f6/usb-glue/usbd_conf.c delete mode 100644 firmware/targets/f6/usb-glue/usbd_conf.h delete mode 100644 firmware/targets/f6/usb-glue/usbd_desc.c delete mode 100644 firmware/targets/f6/usb-glue/usbd_desc.h create mode 100644 firmware/targets/f7/Inc/stm32.h create mode 100644 firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c create mode 100644 firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h create mode 100644 firmware/targets/f7/furi-hal/furi-hal-usb-hid.c create mode 100644 firmware/targets/f7/furi-hal/furi-hal-usb.c create mode 100644 firmware/targets/f7/furi-hal/furi-hal-usb_i.h delete mode 100644 firmware/targets/f7/usb-glue/usb_device.c delete mode 100644 firmware/targets/f7/usb-glue/usb_device.h delete mode 100644 firmware/targets/f7/usb-glue/usbd_cdc_if.c delete mode 100644 firmware/targets/f7/usb-glue/usbd_cdc_if.h delete mode 100644 firmware/targets/f7/usb-glue/usbd_conf.c delete mode 100644 firmware/targets/f7/usb-glue/usbd_conf.h delete mode 100644 firmware/targets/f7/usb-glue/usbd_desc.c delete mode 100644 firmware/targets/f7/usb-glue/usbd_desc.h create mode 100644 firmware/targets/furi-hal-include/furi-hal-usb.h create mode 160000 lib/libusb_stm32 diff --git a/.gitmodules b/.gitmodules index 02edf6062..5004f4157 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/littlefs"] path = lib/littlefs url = https://github.com/littlefs-project/littlefs.git +[submodule "lib/libusb_stm32"] + path = lib/libusb_stm32 + url = https://github.com/flipperdevices/libusb_stm32.git diff --git a/applications/applications.c b/applications/applications.c old mode 100755 new mode 100644 index 1050ff7e4..4e19ef879 --- a/applications/applications.c +++ b/applications/applications.c @@ -33,6 +33,7 @@ extern int32_t storage_test_app(void* p); extern int32_t subghz_app(void* p); extern int32_t vibro_test_app(void* p); extern int32_t bt_debug_app(void* p); +extern int32_t usb_test_app(void* p); // Plugins extern int32_t music_player_app(void* p); @@ -210,6 +211,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { {.app = accessor_app, .name = "Accessor", .stack_size = 4096, .icon = &A_Plugins_14}, #endif +#ifdef APP_USB_TEST + {.app = usb_test_app, .name = "USB Test", .stack_size = 1024, .icon = &A_Plugins_14}, +#endif + #ifdef APP_UNIT_TESTS {.app = flipper_test_app, .name = "Unit Tests", .stack_size = 1024, .icon = &A_Plugins_14}, #endif diff --git a/applications/applications.mk b/applications/applications.mk index 2d6820b59..b5cf772c9 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -43,6 +43,7 @@ APP_KEYPAD_TEST = 1 APP_SD_TEST = 1 APP_UNIT_TESTS = 0 APP_VIBRO_DEMO = 1 +APP_USB_TEST = 1 endif @@ -121,6 +122,14 @@ SRV_GUI = 1 endif +APP_USB_TEST ?= 0 +ifeq ($(APP_USB_TEST), 1) +CFLAGS += -DAPP_USB_TEST +SRV_INPUT = 1 +SRV_GUI = 1 +endif + + APP_KEYPAD_TEST ?= 0 ifeq ($(APP_KEYPAD_TEST), 1) CFLAGS += -DAPP_KEYPAD_TEST diff --git a/applications/debug_tools/usb_test.c b/applications/debug_tools/usb_test.c new file mode 100644 index 000000000..e921d8b38 --- /dev/null +++ b/applications/debug_tools/usb_test.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include + +typedef struct { + Gui* gui; + ViewDispatcher* view_dispatcher; + Submenu* submenu; +} UsbTestApp; + +typedef enum { + UsbTestSubmenuIndexEnable, + UsbTestSubmenuIndexDisable, + UsbTestSubmenuIndexVcpSingle, + UsbTestSubmenuIndexVcpDual, + UsbTestSubmenuIndexHid, + UsbTestSubmenuIndexHidU2F, +} SubmenuIndex; + +void usb_test_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + //UsbTestApp* app = context; + if(index == UsbTestSubmenuIndexEnable) { + furi_hal_usb_enable(); + } else if(index == UsbTestSubmenuIndexDisable) { + furi_hal_usb_disable(); + } else if(index == UsbTestSubmenuIndexVcpSingle) { + furi_hal_usb_set_config(UsbModeVcpSingle); + } else if(index == UsbTestSubmenuIndexVcpDual) { + furi_hal_usb_set_config(UsbModeVcpDual); + } else if(index == UsbTestSubmenuIndexHid) { + furi_hal_usb_set_config(UsbModeHid); + } else if(index == UsbTestSubmenuIndexHidU2F) { + //furi_hal_usb_set_config(UsbModeU2F); + } +} + +uint32_t usb_test_exit(void* context) { + return VIEW_NONE; +} + +UsbTestApp* usb_test_app_alloc() { + UsbTestApp* app = furi_alloc(sizeof(UsbTestApp)); + + // Gui + app->gui = furi_record_open("gui"); + + // View dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Views + app->submenu = submenu_alloc(); + submenu_add_item( + app->submenu, "Enable", UsbTestSubmenuIndexEnable, usb_test_submenu_callback, app); + submenu_add_item( + app->submenu, "Disable", UsbTestSubmenuIndexDisable, usb_test_submenu_callback, app); + submenu_add_item( + app->submenu, "Single VCP", UsbTestSubmenuIndexVcpSingle, usb_test_submenu_callback, app); + submenu_add_item( + app->submenu, "Dual VCP", UsbTestSubmenuIndexVcpDual, usb_test_submenu_callback, app); + submenu_add_item( + app->submenu, "HID KB+Mouse", UsbTestSubmenuIndexHid, usb_test_submenu_callback, app); + submenu_add_item( + app->submenu, "TODO: HID U2F", UsbTestSubmenuIndexHidU2F, usb_test_submenu_callback, app); + view_set_previous_callback(submenu_get_view(app->submenu), usb_test_exit); + view_dispatcher_add_view(app->view_dispatcher, 0, submenu_get_view(app->submenu)); + + // Switch to menu + view_dispatcher_switch_to_view(app->view_dispatcher, 0); + + return app; +} + +void usb_test_app_free(UsbTestApp* app) { + furi_assert(app); + + // Free views + view_dispatcher_remove_view(app->view_dispatcher, 0); + submenu_free(app->submenu); + view_dispatcher_free(app->view_dispatcher); + + // Close gui record + furi_record_close("gui"); + app->gui = NULL; + + // Free rest + free(app); +} + +int32_t usb_test_app(void* p) { + UsbTestApp* app = usb_test_app_alloc(); + + view_dispatcher_run(app->view_dispatcher); + + usb_test_app_free(app); + return 0; +} diff --git a/firmware/targets/f6/Inc/stm32.h b/firmware/targets/f6/Inc/stm32.h new file mode 100644 index 000000000..45344fe3c --- /dev/null +++ b/firmware/targets/f6/Inc/stm32.h @@ -0,0 +1,52 @@ +#ifndef _STM32_H_ +#define _STM32_H_ + +/* modify bitfield */ +#define _BMD(reg, msk, val) (reg) = (((reg) & ~(msk)) | (val)) +/* set bitfield */ +#define _BST(reg, bits) (reg) = ((reg) | (bits)) +/* clear bitfield */ +#define _BCL(reg, bits) (reg) = ((reg) & ~(bits)) +/* wait until bitfield set */ +#define _WBS(reg, bits) while(((reg) & (bits)) == 0) +/* wait until bitfield clear */ +#define _WBC(reg, bits) while(((reg) & (bits)) != 0) +/* wait for bitfield value */ +#define _WVL(reg, msk, val) while(((reg) & (msk)) != (val)) +/* bit value */ +#define _BV(bit) (0x01 << (bit)) + +#if defined(STM32F0) + #include "STM32F0xx/Include/stm32f0xx.h" +#elif defined(STM32F1) + #include "STM32F1xx/Include/stm32f1xx.h" +#elif defined(STM32F2) + #include "STM32F2xx/Include/stm32f2xx.h" +#elif defined(STM32F3) + #include "STM32F3xx/Include/stm32f3xx.h" +#elif defined(STM32F4) + #include "STM32F4xx/Include/stm32f4xx.h" +#elif defined(STM32F7) + #include "STM32F7xx/Include/stm32f7xx.h" +#elif defined(STM32H7) + #include "STM32H7xx/Include/stm32h7xx.h" +#elif defined(STM32L0) + #include "STM32L0xx/Include/stm32l0xx.h" +#elif defined(STM32L1) + #include "STM32L1xx/Include/stm32l1xx.h" +#elif defined(STM32L4) + #include "STM32L4xx/Include/stm32l4xx.h" +#elif defined(STM32L5) + #include "STM32L5xx/Include/stm32l5xx.h" +#elif defined(STM32G0) + #include "STM32G0xx/Include/stm32g0xx.h" +#elif defined(STM32G4) + #include "STM32G4xx/Include/stm32g4xx.h" +#elif defined(STM32WB) + #include "STM32WBxx/Include/stm32wbxx.h" +#else + #error "STM32 family not defined" +#endif + + +#endif // _STM32_H_ diff --git a/firmware/targets/f6/Src/stm32wbxx_it.c b/firmware/targets/f6/Src/stm32wbxx_it.c index 01fbdc1d2..6f70fb5eb 100644 --- a/firmware/targets/f6/Src/stm32wbxx_it.c +++ b/firmware/targets/f6/Src/stm32wbxx_it.c @@ -2,8 +2,9 @@ #include "stm32wbxx_it.h" #include "FreeRTOS.h" #include "task.h" +#include "usbd_core.h" -extern PCD_HandleTypeDef hpcd_USB_FS; +extern usbd_device udev; extern COMP_HandleTypeDef hcomp1; extern RTC_HandleTypeDef hrtc; extern TIM_HandleTypeDef htim1; @@ -20,7 +21,7 @@ void SysTick_Handler(void) { } void USB_LP_IRQHandler(void) { - HAL_PCD_IRQHandler(&hpcd_USB_FS); + usbd_poll(&udev); } void COMP_IRQHandler(void) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c new file mode 100644 index 000000000..09efbec38 --- /dev/null +++ b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c @@ -0,0 +1,555 @@ +#include "furi-hal-version.h" +#include "furi-hal-usb_i.h" +#include "furi-hal-vcp_i.h" +#include "furi-hal-usb-cdc_i.h" +#include + +#include "usb.h" +#include "usb_cdc.h" + +#define CDC0_RXD_EP 0x01 +#define CDC0_TXD_EP 0x82 +#define CDC0_NTF_EP 0x83 + +#define CDC1_RXD_EP 0x04 +#define CDC1_TXD_EP 0x85 +#define CDC1_NTF_EP 0x86 + +#define CDC_NTF_SZ 0x08 + +struct CdcIadDescriptor { + struct usb_iad_descriptor comm_iad; + struct usb_interface_descriptor comm; + struct usb_cdc_header_desc cdc_hdr; + struct usb_cdc_call_mgmt_desc cdc_mgmt; + struct usb_cdc_acm_desc cdc_acm; + struct usb_cdc_union_desc cdc_union; + struct usb_endpoint_descriptor comm_ep; + struct usb_interface_descriptor data; + struct usb_endpoint_descriptor data_eprx; + struct usb_endpoint_descriptor data_eptx; +}; + +struct CdcConfigDescriptorSingle { + struct usb_config_descriptor config; + struct CdcIadDescriptor iad_0; +} __attribute__((packed)); + +struct CdcConfigDescriptorDual { + struct usb_config_descriptor config; + struct CdcIadDescriptor iad_0; + struct CdcIadDescriptor iad_1; +} __attribute__((packed)); + +static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Flipper Devices Inc."); + +/* Device descriptor */ +static const struct usb_device_descriptor cdc_device_desc = { + .bLength = sizeof(struct usb_device_descriptor), + .bDescriptorType = USB_DTYPE_DEVICE, + .bcdUSB = VERSION_BCD(2,0,0), + .bDeviceClass = USB_CLASS_IAD, + .bDeviceSubClass = USB_SUBCLASS_IAD, + .bDeviceProtocol = USB_PROTO_IAD, + .bMaxPacketSize0 = USB_EP0_SIZE, + .idVendor = 0x0483, + .idProduct = 0x5740, + .bcdDevice = VERSION_BCD(1,0,0), + .iManufacturer = UsbDevManuf, + .iProduct = UsbDevProduct, + .iSerialNumber = UsbDevSerial, + .bNumConfigurations = 1, +}; + +/* Device configuration descriptor - single mode*/ +static const struct CdcConfigDescriptorSingle cdc_cfg_desc_single = { + .config = { + .bLength = sizeof(struct usb_config_descriptor), + .bDescriptorType = USB_DTYPE_CONFIGURATION, + .wTotalLength = sizeof(struct CdcConfigDescriptorSingle), + .bNumInterfaces = 2, + + .bConfigurationValue = 1, + .iConfiguration = NO_DESCRIPTOR, + .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED, + .bMaxPower = USB_CFG_POWER_MA(100), + }, + .iad_0 = { + .comm_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 0, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .comm = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .cdc_hdr = { + .bFunctionLength = sizeof(struct usb_cdc_header_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_HEADER, + .bcdCDC = VERSION_BCD(1,1,0), + }, + .cdc_mgmt = { + .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .cdc_acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_UNION, + .bMasterInterface0 = 0, + .bSlaveInterface0 = 1, + }, + .comm_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_NTF_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = CDC_NTF_SZ, + .bInterval = 0xFF, + }, + .data = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = USB_SUBCLASS_NONE, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .data_eprx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_RXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + .data_eptx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_TXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + }, +}; + +/* Device configuration descriptor - dual mode*/ +static const struct CdcConfigDescriptorDual cdc_cfg_desc_dual = { + .config = { + .bLength = sizeof(struct usb_config_descriptor), + .bDescriptorType = USB_DTYPE_CONFIGURATION, + .wTotalLength = sizeof(struct CdcConfigDescriptorDual), + .bNumInterfaces = 4, + + .bConfigurationValue = 1, + .iConfiguration = NO_DESCRIPTOR, + .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED, + .bMaxPower = USB_CFG_POWER_MA(100), + }, + .iad_0 = { + .comm_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 0, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .comm = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .cdc_hdr = { + .bFunctionLength = sizeof(struct usb_cdc_header_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_HEADER, + .bcdCDC = VERSION_BCD(1,1,0), + }, + .cdc_mgmt = { + .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .cdc_acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_UNION, + .bMasterInterface0 = 0, + .bSlaveInterface0 = 1, + }, + .comm_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_NTF_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = CDC_NTF_SZ, + .bInterval = 0xFF, + }, + .data = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = USB_SUBCLASS_NONE, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .data_eprx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_RXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + .data_eptx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_TXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + }, + .iad_1 = { + .comm_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 2, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .comm = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 2+0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .cdc_hdr = { + .bFunctionLength = sizeof(struct usb_cdc_header_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_HEADER, + .bcdCDC = VERSION_BCD(1,1,0), + }, + .cdc_mgmt = { + .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 2+1, + }, + .cdc_acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_UNION, + .bMasterInterface0 = 2+0, + .bSlaveInterface0 = 2+1, + }, + .comm_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC1_NTF_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = CDC_NTF_SZ, + .bInterval = 0xFF, + }, + .data = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 2+1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = USB_SUBCLASS_NONE, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .data_eprx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC1_RXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + .data_eptx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC1_TXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + }, +}; + +static struct usb_cdc_line_coding cdc_line = { + .dwDTERate = 38400, + .bCharFormat = USB_CDC_1_STOP_BITS, + .bParityType = USB_CDC_NO_PARITY, + .bDataBits = 8, +}; +static void cdc_init(usbd_device* dev, struct UsbInterface* intf); +static void cdc_deinit(usbd_device *dev); +static void cdc_on_wakeup(usbd_device *dev); +static void cdc_on_suspend(usbd_device *dev); + +static usbd_respond cdc_ep_config (usbd_device *dev, uint8_t cfg); +static usbd_respond cdc_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback); +static usbd_device* usb_dev; +static struct UsbInterface* cdc_if_cur = NULL; + +struct UsbInterface usb_cdc_single = { + .init = cdc_init, + .deinit = cdc_deinit, + .wakeup = cdc_on_wakeup, + .suspend = cdc_on_suspend, + + .dev_descr = (struct usb_device_descriptor*)&cdc_device_desc, + + .str_manuf_descr = (void*)&dev_manuf_desc, + .str_prod_descr = NULL, + .str_serial_descr = NULL, + + .cfg_descr = (void*)&cdc_cfg_desc_single, +}; + +struct UsbInterface usb_cdc_dual = { + .init = cdc_init, + .deinit = cdc_deinit, + .wakeup = cdc_on_wakeup, + .suspend = cdc_on_suspend, + + .dev_descr = (struct usb_device_descriptor*)&cdc_device_desc, + + .str_manuf_descr = (void*)&dev_manuf_desc, + .str_prod_descr = NULL, + .str_serial_descr = NULL, + + .cfg_descr = (void*)&cdc_cfg_desc_dual, +}; + +static void cdc_init(usbd_device* dev, struct UsbInterface* intf) { + usb_dev = dev; + cdc_if_cur = intf; + + char* name = (char*)furi_hal_version_get_device_name_ptr(); + uint8_t len = (name == NULL) ? (0) : (strlen(name)); + struct usb_string_descriptor* dev_prod_desc = furi_alloc(len * 2 + 2); + dev_prod_desc->bLength = len * 2 + 2; + dev_prod_desc->bDescriptorType = USB_DTYPE_STRING; + for (uint8_t i = 0; i < len; i++) + dev_prod_desc->wString[i] = name[i]; + + name = (char*)furi_hal_version_get_name_ptr(); + len = (name == NULL) ? (0) : (strlen(name)); + struct usb_string_descriptor* dev_serial_desc = furi_alloc((len + 5) * 2 + 2); + dev_serial_desc->bLength = (len + 5) * 2 + 2; + dev_serial_desc->bDescriptorType = USB_DTYPE_STRING; + memcpy(dev_serial_desc->wString, "f\0l\0i\0p\0_\0", 5*2); + for (uint8_t i = 0; i < len; i++) + dev_serial_desc->wString[i+5] = name[i]; + + cdc_if_cur->str_prod_descr = dev_prod_desc; + cdc_if_cur->str_serial_descr = dev_serial_desc; + + usbd_reg_config(dev, cdc_ep_config); + usbd_reg_control(dev, cdc_control); + + usbd_connect(dev, true); +} + +static void cdc_deinit(usbd_device *dev) { + usbd_reg_config(dev, NULL); + usbd_reg_control(dev, NULL); + + free(cdc_if_cur->str_prod_descr); + free(cdc_if_cur->str_serial_descr); + + cdc_if_cur = NULL; +} + +void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { + if (if_num == 0) + usbd_ep_write(usb_dev, CDC0_TXD_EP, buf, len); + else + usbd_ep_write(usb_dev, CDC1_TXD_EP, buf, len); +} + +int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) { + if (if_num == 0) + return usbd_ep_read(usb_dev, CDC0_RXD_EP, buf, max_len); + else + return usbd_ep_read(usb_dev, CDC1_RXD_EP, buf, max_len); +} + +static void cdc_on_wakeup(usbd_device *dev) { + furi_hal_vcp_on_usb_resume(); +} + +static void cdc_on_suspend(usbd_device *dev) { + furi_hal_vcp_on_usb_suspend(); +} + +static void cdc_rx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) { + if (ep == CDC0_RXD_EP) + furi_hal_vcp_on_cdc_rx(0); + else + furi_hal_vcp_on_cdc_rx(1); +} + +static void cdc_tx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) { + if (ep == CDC0_TXD_EP) + furi_hal_vcp_on_cdc_tx_complete(0); + else + furi_hal_vcp_on_cdc_tx_complete(1); +} + +static void cdc_txrx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) { + if (event == usbd_evt_eptx) { + cdc_tx_ep_callback(dev, event, ep); + } else { + cdc_rx_ep_callback(dev, event, ep); + } +} + +/* Configure endpoints */ +static usbd_respond cdc_ep_config (usbd_device *dev, uint8_t cfg) { + uint8_t if_cnt = ((struct usb_config_descriptor*)(cdc_if_cur->cfg_descr))->bNumInterfaces; + switch (cfg) { + case 0: + /* deconfiguring device */ + usbd_ep_deconfig(dev, CDC0_NTF_EP); + usbd_ep_deconfig(dev, CDC0_TXD_EP); + usbd_ep_deconfig(dev, CDC0_RXD_EP); + usbd_reg_endpoint(dev, CDC0_RXD_EP, 0); + usbd_reg_endpoint(dev, CDC0_TXD_EP, 0); + if (if_cnt == 4) { + usbd_ep_deconfig(dev, CDC1_NTF_EP); + usbd_ep_deconfig(dev, CDC1_TXD_EP); + usbd_ep_deconfig(dev, CDC1_RXD_EP); + usbd_reg_endpoint(dev, CDC1_RXD_EP, 0); + usbd_reg_endpoint(dev, CDC1_TXD_EP, 0); + } + return usbd_ack; + case 1: + /* configuring device */ + if ((CDC0_TXD_EP & 0x7F) != (CDC0_RXD_EP & 0x7F)) { + usbd_ep_config(dev, CDC0_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC0_RXD_EP, cdc_rx_ep_callback); + usbd_reg_endpoint(dev, CDC0_TXD_EP, cdc_tx_ep_callback); + } else { + usbd_ep_config(dev, CDC0_RXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_TXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC0_RXD_EP, cdc_txrx_ep_callback); + usbd_reg_endpoint(dev, CDC0_TXD_EP, cdc_txrx_ep_callback); + } + usbd_ep_write(dev, CDC0_TXD_EP, 0, 0); + + if (if_cnt == 4) { + if ((CDC1_TXD_EP & 0x7F) != (CDC1_RXD_EP & 0x7F)) { + usbd_ep_config(dev, CDC1_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC1_RXD_EP, cdc_rx_ep_callback); + usbd_reg_endpoint(dev, CDC1_TXD_EP, cdc_tx_ep_callback); + } else { + usbd_ep_config(dev, CDC1_RXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_TXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC1_RXD_EP, cdc_txrx_ep_callback); + usbd_reg_endpoint(dev, CDC1_TXD_EP, cdc_txrx_ep_callback); + } + usbd_ep_write(dev, CDC1_TXD_EP, 0, 0); + } + return usbd_ack; + default: + return usbd_fail; + } +} + +/* Control requests handler */ +static usbd_respond cdc_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) { + /* CDC control requests */ + if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS) + && req->wIndex == 0 ) { + switch (req->bRequest) { + case USB_CDC_SET_CONTROL_LINE_STATE: + furi_hal_vcp_on_cdc_control_line(req->wValue); + return usbd_ack; + case USB_CDC_SET_LINE_CODING: + memcpy(&cdc_line, req->data, sizeof(cdc_line)); + return usbd_ack; + case USB_CDC_GET_LINE_CODING: + dev->status.data_ptr = &cdc_line; + dev->status.data_count = sizeof(cdc_line); + return usbd_ack; + default: + return usbd_fail; + } + } + return usbd_fail; +} diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h new file mode 100644 index 000000000..636b3c046 --- /dev/null +++ b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h @@ -0,0 +1,7 @@ +#pragma once + +#define CDC_DATA_SZ 0x40 + +void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len); + +int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len); diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb-hid.c b/firmware/targets/f6/furi-hal/furi-hal-usb-hid.c new file mode 100644 index 000000000..384236107 --- /dev/null +++ b/firmware/targets/f6/furi-hal/furi-hal-usb-hid.c @@ -0,0 +1,264 @@ +#include "furi-hal-version.h" +#include "furi-hal-usb_i.h" +#include + +#include "usb.h" +#include "usb_hid.h" +#include "hid_usage_desktop.h" +#include "hid_usage_button.h" + +#define HID_RIN_EP 0x81 +#define HID_RIN_SZ 0x10 + +struct HidIadDescriptor { + struct usb_iad_descriptor hid_iad; + struct usb_interface_descriptor hid; + struct usb_hid_descriptor hid_desc; + struct usb_endpoint_descriptor hid_ep; +}; + +struct HidConfigDescriptor { + struct usb_config_descriptor config; + struct HidIadDescriptor iad_0; +} __attribute__((packed)); + +/* HID mouse report desscriptor. 2 axis 5 buttons */ +static const uint8_t hid_report_desc[] = { + HID_USAGE_PAGE(HID_PAGE_DESKTOP), + HID_USAGE(HID_DESKTOP_MOUSE), + HID_COLLECTION(HID_APPLICATION_COLLECTION), + HID_USAGE(HID_DESKTOP_POINTER), + HID_COLLECTION(HID_PHYSICAL_COLLECTION), + HID_USAGE(HID_DESKTOP_X), + HID_USAGE(HID_DESKTOP_Y), + HID_LOGICAL_MINIMUM(-127), + HID_LOGICAL_MAXIMUM(127), + HID_REPORT_SIZE(8), + HID_REPORT_COUNT(2), + HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE ), + HID_USAGE_PAGE(HID_PAGE_BUTTON), + HID_USAGE_MINIMUM(1), + HID_USAGE_MAXIMUM(5), + HID_LOGICAL_MINIMUM(0), + HID_LOGICAL_MAXIMUM(1), + HID_REPORT_SIZE(1), + HID_REPORT_COUNT(5), + HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE ), + HID_REPORT_SIZE(1), + HID_REPORT_COUNT(3), + HID_INPUT(HID_IOF_CONSTANT), + HID_END_COLLECTION, + HID_END_COLLECTION, +}; + +static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Logitech"); +static const struct usb_string_descriptor dev_prod_desc = USB_STRING_DESC("USB Receiver"); +static const struct usb_string_descriptor dev_serial_desc = USB_STRING_DESC("1234567890"); + +/* Device descriptor */ +static const struct usb_device_descriptor hid_device_desc = { + .bLength = sizeof(struct usb_device_descriptor), + .bDescriptorType = USB_DTYPE_DEVICE, + .bcdUSB = VERSION_BCD(2,0,0), + .bDeviceClass = USB_CLASS_IAD, + .bDeviceSubClass = USB_SUBCLASS_IAD, + .bDeviceProtocol = USB_PROTO_IAD, + .bMaxPacketSize0 = USB_EP0_SIZE, + .idVendor = 0x046d, + .idProduct = 0xc529, + .bcdDevice = VERSION_BCD(1,0,0), + .iManufacturer = UsbDevManuf, + .iProduct = UsbDevProduct, + .iSerialNumber = UsbDevSerial, + .bNumConfigurations = 1, +}; + +/* Device configuration descriptor */ +static const struct HidConfigDescriptor hid_cfg_desc = { + .config = { + .bLength = sizeof(struct usb_config_descriptor), + .bDescriptorType = USB_DTYPE_CONFIGURATION, + .wTotalLength = sizeof(struct HidConfigDescriptor), + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = NO_DESCRIPTOR, + .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED, + .bMaxPower = USB_CFG_POWER_MA(100), + }, + .iad_0 = { + .hid_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 0, + .bInterfaceCount = 1, + .bFunctionClass = USB_CLASS_PER_INTERFACE, + .bFunctionSubClass = USB_SUBCLASS_NONE, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .hid = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT, + .bInterfaceProtocol = USB_HID_PROTO_NONBOOT, + .iInterface = NO_DESCRIPTOR, + }, + .hid_desc = { + .bLength = sizeof(struct usb_hid_descriptor), + .bDescriptorType = USB_DTYPE_HID, + .bcdHID = VERSION_BCD(1,0,0), + .bCountryCode = USB_HID_COUNTRY_NONE, + .bNumDescriptors = 1, + .bDescriptorType0 = USB_DTYPE_HID_REPORT, + .wDescriptorLength0 = sizeof(hid_report_desc), + }, + .hid_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = HID_RIN_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = HID_RIN_SZ, + .bInterval = 50, + }, + }, +}; + +static struct { + int8_t x; + int8_t y; + uint8_t buttons; +} __attribute__((packed)) hid_report_data; + +static void hid_init(usbd_device* dev, struct UsbInterface* intf); +static void hid_deinit(usbd_device *dev); +static void hid_on_wakeup(usbd_device *dev); +static void hid_on_suspend(usbd_device *dev); + +static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg); +static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback); +static usbd_device* usb_dev; + +struct UsbInterface usb_hid = { + .init = hid_init, + .deinit = hid_deinit, + .wakeup = hid_on_wakeup, + .suspend = hid_on_suspend, + + .dev_descr = (struct usb_device_descriptor*)&hid_device_desc, + + .str_manuf_descr = (void*)&dev_manuf_desc, + .str_prod_descr = (void*)&dev_prod_desc, + .str_serial_descr = (void*)&dev_serial_desc, + + .cfg_descr = (void*)&hid_cfg_desc, +}; + +static void hid_init(usbd_device* dev, struct UsbInterface* intf) { + usb_dev = dev; + + usbd_reg_config(dev, hid_ep_config); + usbd_reg_control(dev, hid_control); + + usbd_connect(dev, true); +} + +static void hid_deinit(usbd_device *dev) { + usbd_reg_config(dev, NULL); + usbd_reg_control(dev, NULL); +} + +static void hid_on_wakeup(usbd_device *dev) { +} + +static void hid_on_suspend(usbd_device *dev) { +} + +/* HID mouse IN endpoint callback */ +static void hid_mouse_move(usbd_device *dev, uint8_t event, uint8_t ep) { + static uint8_t t = 0; + if (t < 0x10) { + hid_report_data.x = 1; + hid_report_data.y = 0; + } else if (t < 0x20) { + hid_report_data.x = 1; + hid_report_data.y = 1; + } else if (t < 0x30) { + hid_report_data.x = 0; + hid_report_data.y = 1; + } else if (t < 0x40) { + hid_report_data.x = -1; + hid_report_data.y = 1; + } else if (t < 0x50) { + hid_report_data.x = -1; + hid_report_data.y = 0; + } else if (t < 0x60) { + hid_report_data.x = -1; + hid_report_data.y = -1; + } else if (t < 0x70) { + hid_report_data.x = 0; + hid_report_data.y = -1; + } else { + hid_report_data.x = 1; + hid_report_data.y = -1; + } + t = (t + 1) & 0x7F; + usbd_ep_write(dev, ep, &hid_report_data, sizeof(hid_report_data)); +} + +/* Configure endpoints */ +static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg) { + switch (cfg) { + case 0: + /* deconfiguring device */ + usbd_ep_deconfig(dev, HID_RIN_EP); + usbd_reg_endpoint(dev, HID_RIN_EP, 0); + return usbd_ack; + case 1: + /* configuring device */ + usbd_ep_config(dev, HID_RIN_EP, USB_EPTYPE_INTERRUPT, HID_RIN_SZ); + usbd_reg_endpoint(dev, HID_RIN_EP, hid_mouse_move); + usbd_ep_write(dev, HID_RIN_EP, 0, 0); + return usbd_ack; + default: + return usbd_fail; + } +} + +/* Control requests handler */ +static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) { + /* HID control requests */ + if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS) + && req->wIndex == 0 ) { + switch (req->bRequest) { + case USB_HID_SETIDLE: + return usbd_ack; + case USB_HID_GETREPORT: + dev->status.data_ptr = &hid_report_data; + dev->status.data_count = sizeof(hid_report_data); + return usbd_ack; + default: + return usbd_fail; + } + } + if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_STANDARD) + && req->wIndex == 0 + && req->bRequest == USB_STD_GET_DESCRIPTOR) { + switch (req->wValue >> 8) { + case USB_DTYPE_HID: + dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.iad_0.hid_desc); + dev->status.data_count = sizeof(hid_cfg_desc.iad_0.hid_desc); + return usbd_ack; + case USB_DTYPE_HID_REPORT: + dev->status.data_ptr = (uint8_t*)hid_report_desc; + dev->status.data_count = sizeof(hid_report_desc); + return usbd_ack; + default: + return usbd_fail; + } + } + return usbd_fail; +} diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb.c b/firmware/targets/f6/furi-hal/furi-hal-usb.c new file mode 100644 index 000000000..fc5add2e7 --- /dev/null +++ b/firmware/targets/f6/furi-hal/furi-hal-usb.c @@ -0,0 +1,164 @@ +#include "furi-hal-version.h" +#include "furi-hal-usb_i.h" +#include "furi-hal-usb.h" +#include "furi-hal-vcp_i.h" +#include + +#include "usb.h" + +#define USB_RECONNECT_DELAY 500 + +extern struct UsbInterface usb_cdc_single; +extern struct UsbInterface usb_cdc_dual; +extern struct UsbInterface usb_hid; + +static struct UsbInterface* const usb_if_modes[UsbModesNum] = { + NULL, + &usb_cdc_single, + &usb_cdc_dual, + &usb_hid, + NULL,//&usb_hid_u2f, +}; + +static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US); + +static uint32_t ubuf[0x20]; +usbd_device udev; + +static usbd_respond usb_descriptor_get (usbd_ctlreq *req, void **address, uint16_t *length); +static void susp_evt(usbd_device *dev, uint8_t event, uint8_t ep); +static void wkup_evt(usbd_device *dev, uint8_t event, uint8_t ep); + +struct UsbCfg{ + osTimerId_t reconnect_tmr; + UsbMode mode_cur; + UsbMode mode_next; + bool enabled; +} usb_config; + +static void furi_hal_usb_tmr_cb(void* context); + +/* Low-level init */ +void furi_hal_usb_init(void) { + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + LL_PWR_EnableVddUSB(); + + GPIO_InitStruct.Pin = LL_GPIO_PIN_11 | LL_GPIO_PIN_12; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_10; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + usbd_init(&udev, &usbd_hw, USB_EP0_SIZE, ubuf, sizeof(ubuf)); + usbd_enable(&udev, true); + + usbd_reg_descr(&udev, usb_descriptor_get); + usbd_reg_event(&udev, usbd_evt_susp, susp_evt); + usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt); + + usb_config.enabled = false; + usb_config.reconnect_tmr = NULL; + HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); + NVIC_EnableIRQ(USB_LP_IRQn); + + FURI_LOG_I("FuriHalUsb", "Init OK"); +} + +void furi_hal_usb_set_config(UsbMode new_mode) { + if (new_mode != usb_config.mode_cur) { + if (usb_config.enabled) { + usb_config.mode_next = new_mode; + if (usb_config.reconnect_tmr == NULL) + usb_config.reconnect_tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL); + furi_hal_usb_disable(); + osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY); + } + else { + if (usb_if_modes[usb_config.mode_cur] != NULL) + usb_if_modes[usb_config.mode_cur]->deinit(&udev); + if (usb_if_modes[new_mode] != NULL) { + usb_if_modes[new_mode]->init(&udev, usb_if_modes[new_mode]); + FURI_LOG_I("FuriHalUsb", "USB mode change %u -> %u", usb_config.mode_cur, new_mode); + usb_config.enabled = true; + usb_config.mode_cur = new_mode; + } + } + } +} + +void furi_hal_usb_disable() { + if (usb_config.enabled) { + susp_evt(&udev, 0, 0); + usbd_connect(&udev, false); + usb_config.enabled = false; + FURI_LOG_I("FuriHalUsb", "USB Disable"); + } +} + +void furi_hal_usb_enable() { + if ((!usb_config.enabled) && (usb_if_modes[usb_config.mode_cur] != NULL)) { + usbd_connect(&udev, true); + usb_config.enabled = true; + FURI_LOG_I("FuriHalUsb", "USB Enable"); + } +} + +static void furi_hal_usb_tmr_cb(void* context) { + furi_hal_usb_set_config(usb_config.mode_next); +} + +/* Get device / configuration descriptors */ +static usbd_respond usb_descriptor_get (usbd_ctlreq *req, void **address, uint16_t *length) { + const uint8_t dtype = req->wValue >> 8; + const uint8_t dnumber = req->wValue & 0xFF; + const void* desc; + uint16_t len = 0; + if (usb_if_modes[usb_config.mode_cur] == NULL) + return usbd_fail; + + switch (dtype) { + case USB_DTYPE_DEVICE: + desc = usb_if_modes[usb_config.mode_cur]->dev_descr; + break; + case USB_DTYPE_CONFIGURATION: + desc = usb_if_modes[usb_config.mode_cur]->cfg_descr; + len = ((struct usb_string_descriptor*)(usb_if_modes[usb_config.mode_cur]->cfg_descr))->wString[0]; + break; + case USB_DTYPE_STRING: + if (dnumber == UsbDevLang) { + desc = &dev_lang_desc; + } else if (dnumber == UsbDevManuf) { + desc = usb_if_modes[usb_config.mode_cur]->str_manuf_descr; + } else if (dnumber == UsbDevProduct) { + desc = usb_if_modes[usb_config.mode_cur]->str_prod_descr; + } else if (dnumber == UsbDevSerial) { + desc = usb_if_modes[usb_config.mode_cur]->str_serial_descr; + } else + return usbd_fail; + break; + default: + return usbd_fail; + } + if (desc == NULL) + return usbd_fail; + + if (len == 0) { + len = ((struct usb_header_descriptor*)desc)->bLength; + } + *address = (void*)desc; + *length = len; + return usbd_ack; +} + +static void susp_evt(usbd_device *dev, uint8_t event, uint8_t ep) { + if (usb_if_modes[usb_config.mode_cur] != NULL) + usb_if_modes[usb_config.mode_cur]->suspend(&udev); +} + +static void wkup_evt(usbd_device *dev, uint8_t event, uint8_t ep) { + if (usb_if_modes[usb_config.mode_cur] != NULL) + usb_if_modes[usb_config.mode_cur]->wakeup(&udev); +} diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb_i.h b/firmware/targets/f6/furi-hal/furi-hal-usb_i.h new file mode 100644 index 000000000..b329c51f7 --- /dev/null +++ b/firmware/targets/f6/furi-hal/furi-hal-usb_i.h @@ -0,0 +1,28 @@ +#pragma once + +#include "usb.h" + +#define USB_EP0_SIZE 8 + +/* String descriptors */ +enum UsbDevDescStr{ + UsbDevLang = 0, + UsbDevManuf = 1, + UsbDevProduct = 2, + UsbDevSerial = 3, +}; + +struct UsbInterface { + void (*init)(usbd_device *dev, struct UsbInterface* intf); + void (*deinit)(usbd_device *dev); + void (*wakeup)(usbd_device *dev); + void (*suspend)(usbd_device *dev); + + struct usb_device_descriptor* dev_descr; + + void* str_manuf_descr; + void* str_prod_descr; + void* str_serial_descr; + + void* cfg_descr; +}; diff --git a/firmware/targets/f6/furi-hal/furi-hal-vcp.c b/firmware/targets/f6/furi-hal/furi-hal-vcp.c index 88de32b56..e276c4a30 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-vcp.c +++ b/firmware/targets/f6/furi-hal/furi-hal-vcp.c @@ -1,12 +1,12 @@ #include +#include #include -#include #include -#define FURI_HAL_VCP_RX_BUFFER_SIZE (APP_RX_DATA_SIZE * 5) - -extern USBD_HandleTypeDef hUsbDeviceFS; +#define APP_RX_DATA_SIZE CDC_DATA_SZ +#define APP_TX_DATA_SIZE CDC_DATA_SZ +#define FURI_HAL_VCP_RX_BUFFER_SIZE (APP_RX_DATA_SIZE * 16) typedef struct { volatile bool connected; @@ -22,8 +22,11 @@ static FuriHalVcp* furi_hal_vcp = NULL; static const uint8_t ascii_soh = 0x01; static const uint8_t ascii_eot = 0x04; +static uint8_t* vcp_rx_buf; + void furi_hal_vcp_init() { furi_hal_vcp = furi_alloc(sizeof(FuriHalVcp)); + vcp_rx_buf = furi_alloc(APP_RX_DATA_SIZE); furi_hal_vcp->connected = false; furi_hal_vcp->rx_stream = xStreamBufferCreate(FURI_HAL_VCP_RX_BUFFER_SIZE, 1); @@ -40,10 +43,8 @@ size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { size_t received = xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, portMAX_DELAY); if(furi_hal_vcp->rx_stream_full - &&xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { + && xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { furi_hal_vcp->rx_stream_full = false; - // data accepted, start waiting for next packet - USBD_CDC_ReceivePacket(&hUsbDeviceFS); } return received; @@ -67,13 +68,9 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { batch_size = APP_TX_DATA_SIZE; } - if (CDC_Transmit_FS((uint8_t*)buffer, batch_size) == USBD_OK) { - size -= batch_size; - buffer += batch_size; - } else { - FURI_LOG_E("FuriHalVcp", "CDC_Transmit_FS failed"); - osDelay(50); - } + furi_hal_cdc_send(0, (uint8_t*)buffer, batch_size); + size -= batch_size; + buffer += batch_size; } } @@ -89,6 +86,8 @@ void furi_hal_vcp_on_usb_suspend() { } void furi_hal_vcp_on_cdc_control_line(uint8_t state) { + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; // bit 0: DTR state, bit 1: RTS state // bool dtr = state & 0b01; bool dtr = state & 0b1; @@ -96,33 +95,45 @@ void furi_hal_vcp_on_cdc_control_line(uint8_t state) { if (dtr) { if (!furi_hal_vcp->connected) { furi_hal_vcp->connected = true; - furi_hal_vcp_on_cdc_rx(&ascii_soh, 1); // SOH + xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_soh, 1, &xHigherPriorityTaskWoken); // SOH + } } else { if (furi_hal_vcp->connected) { - furi_hal_vcp_on_cdc_rx(&ascii_eot, 1); // EOT + xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_eot, 1, &xHigherPriorityTaskWoken); // EOT furi_hal_vcp->connected = false; } } osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -void furi_hal_vcp_on_cdc_rx(const uint8_t* buffer, size_t size) { +void furi_hal_vcp_on_cdc_rx(uint8_t if_num) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; - size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, buffer, size, &xHigherPriorityTaskWoken); - furi_check(ret == size); - - if (xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { - USBD_CDC_ReceivePacket(&hUsbDeviceFS); - } else { - furi_hal_vcp->rx_stream_full = true; + + if (if_num == 0) { + uint16_t max_len = xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream); + if (max_len > 0) { + if (max_len > APP_RX_DATA_SIZE) + max_len = APP_RX_DATA_SIZE; + int32_t size = furi_hal_cdc_receive(0, vcp_rx_buf, max_len); + + if (size > 0) { + size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, vcp_rx_buf, size, &xHigherPriorityTaskWoken); + furi_check(ret == size); + } + } else { + furi_hal_vcp->rx_stream_full = true; + }; } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -void furi_hal_vcp_on_cdc_tx_complete(size_t size) { - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); +void furi_hal_vcp_on_cdc_tx_complete(uint8_t if_num) { + if (if_num == 0) + osSemaphoreRelease(furi_hal_vcp->tx_semaphore); } diff --git a/firmware/targets/f6/furi-hal/furi-hal-vcp_i.h b/firmware/targets/f6/furi-hal/furi-hal-vcp_i.h index 05ddc6ad3..9c8ccd73c 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-vcp_i.h +++ b/firmware/targets/f6/furi-hal/furi-hal-vcp_i.h @@ -8,6 +8,6 @@ void furi_hal_vcp_on_usb_suspend(); void furi_hal_vcp_on_cdc_control_line(uint8_t state); -void furi_hal_vcp_on_cdc_rx(const uint8_t* buffer, size_t size); +void furi_hal_vcp_on_cdc_rx(uint8_t if_num); -void furi_hal_vcp_on_cdc_tx_complete(size_t size); +void furi_hal_vcp_on_cdc_tx_complete(uint8_t if_num); diff --git a/firmware/targets/f6/furi-hal/furi-hal-version.c b/firmware/targets/f6/furi-hal/furi-hal-version.c index 90a3d6c29..93166b164 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-version.c +++ b/firmware/targets/f6/furi-hal/furi-hal-version.c @@ -8,10 +8,6 @@ #include "ble.h" #define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE -#define FURI_HAL_VERSION_NAME_LENGTH 8 -#define FURI_HAL_VERSION_ARRAY_NAME_LENGTH (FURI_HAL_VERSION_NAME_LENGTH + 1) -/** BLE symbol + "Flipper " + name */ -#define FURI_HAL_VERSION_DEVICE_NAME_LENGTH (1 + 8 + FURI_HAL_VERSION_ARRAY_NAME_LENGTH) #define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE /** OTP Versions enum */ diff --git a/firmware/targets/f6/furi-hal/furi-hal.c b/firmware/targets/f6/furi-hal/furi-hal.c index 2ec06dd46..64b29ba73 100644 --- a/firmware/targets/f6/furi-hal/furi-hal.c +++ b/firmware/targets/f6/furi-hal/furi-hal.c @@ -3,7 +3,6 @@ #include #include #include -#include #include void furi_hal_init() { @@ -35,7 +34,8 @@ void furi_hal_init() { // VCP + USB furi_hal_vcp_init(); - MX_USB_Device_Init(); + furi_hal_usb_init(); + furi_hal_usb_set_config(UsbModeVcpSingle); FURI_LOG_I("HAL", "USB OK"); furi_hal_i2c_init(); diff --git a/firmware/targets/f6/target.mk b/firmware/targets/f6/target.mk index fe9501499..d8ab0d5de 100644 --- a/firmware/targets/f6/target.mk +++ b/firmware/targets/f6/target.mk @@ -38,6 +38,7 @@ CFLAGS += \ CFLAGS += \ -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc \ -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc/Legacy \ + -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST \ -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Include \ -I$(CUBE_DIR)/Drivers/CMSIS/Include C_SOURCES += \ @@ -69,7 +70,6 @@ C_SOURCES += \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usb.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_utils.c # FreeRTOS @@ -116,17 +116,10 @@ C_SOURCES += \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/shci_tl_if.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci/shci.c -# USB glue +# USB stack CFLAGS += \ - -I$(TARGET_DIR)/usb-glue \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Inc \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc -C_SOURCES += \ - $(wildcard $(TARGET_DIR)/usb-glue/*.c) \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c + -DSTM32WB \ + -DUSB_PMASIZE=0x400 # Furi HAL FURI_HAL_OS_DEBUG ?= 0 diff --git a/firmware/targets/f6/usb-glue/usb_device.c b/firmware/targets/f6/usb-glue/usb_device.c deleted file mode 100644 index 84e9143d9..000000000 --- a/firmware/targets/f6/usb-glue/usb_device.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "usb_device.h" - -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" - -#include "usbd_def.h" -#include "usbd_core.h" -#include "usbd_desc.h" -#include "usbd_cdc.h" -#include "usbd_cdc_if.h" - -extern void Error_Handler(void); - -/* USB Device Core handle declaration. */ -USBD_HandleTypeDef hUsbDeviceFS; - -extern USBD_DescriptorsTypeDef CDC_Desc; - -/** Init USB device Library, add supported class and start the library */ -void MX_USB_Device_Init(void) { - /* Init Device Library, add supported class and start the library. */ - if (USBD_Init(&hUsbDeviceFS, &CDC_Desc, DEVICE_FS) != USBD_OK) { - Error_Handler(); - } - if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { - Error_Handler(); - } - if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { - Error_Handler(); - } - if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { - Error_Handler(); - } -} diff --git a/firmware/targets/f6/usb-glue/usb_device.h b/firmware/targets/f6/usb-glue/usb_device.h deleted file mode 100644 index 7d80e3480..000000000 --- a/firmware/targets/f6/usb-glue/usb_device.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef __cplusplus - extern "C" { -#endif - -void MX_USB_Device_Init(); - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f6/usb-glue/usbd_cdc_if.c b/firmware/targets/f6/usb-glue/usbd_cdc_if.c deleted file mode 100644 index 6b905c84f..000000000 --- a/firmware/targets/f6/usb-glue/usbd_cdc_if.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "usbd_cdc_if.h" -#include - -extern USBD_HandleTypeDef hUsbDeviceFS; - -static int8_t CDC_Init_FS(void); -static int8_t CDC_DeInit_FS(void); -static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); -static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len); -static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum); - -USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = -{ - CDC_Init_FS, - CDC_DeInit_FS, - CDC_Control_FS, - CDC_Receive_FS, - CDC_TransmitCplt_FS -}; - -uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; -uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; - -/** Initializes the CDC media low layer over the FS USB IP - * @retval USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Init_FS(void) { - /* Set Application Buffers */ - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); - USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); - return (USBD_OK); -} - -/** - * @brief DeInitializes the CDC media low layer - * @retval USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_DeInit_FS(void) { - return (USBD_OK); -} - -/** Manage the CDC 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 CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) { - if (cmd == CDC_SEND_ENCAPSULATED_COMMAND) { - } else if (cmd == CDC_GET_ENCAPSULATED_RESPONSE) { - } else if (cmd == CDC_SET_COMM_FEATURE) { - } else if (cmd == CDC_GET_COMM_FEATURE) { - } else if (cmd == CDC_CLEAR_COMM_FEATURE) { - } else if (cmd == CDC_SET_LINE_CODING) { - /*******************************************************************************/ - /* Line Coding Structure */ - /*-----------------------------------------------------------------------------*/ - /* Offset | Field | Size | Value | Description */ - /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ - /* 4 | bCharFormat | 1 | Number | Stop bits */ - /* 0 - 1 Stop bit */ - /* 1 - 1.5 Stop bits */ - /* 2 - 2 Stop bits */ - /* 5 | bParityType | 1 | Number | Parity */ - /* 0 - None */ - /* 1 - Odd */ - /* 2 - Even */ - /* 3 - Mark */ - /* 4 - Space */ - /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ - /*******************************************************************************/ - } else if (cmd == CDC_GET_LINE_CODING) { - } else if (cmd == CDC_SET_CONTROL_LINE_STATE) { - furi_hal_vcp_on_cdc_control_line(((USBD_SetupReqTypedef*)pbuf)->wValue); - } else if (cmd == CDC_SEND_BREAK) { - } else { - } - - return (USBD_OK); -} - -/** Data received over USB OUT endpoint are sent over CDC interface through this function. - * - * @note - * This function will issue a NAK packet on any OUT packet received on - * USB endpoint until exiting this function. If you exit this function - * before transfer is complete on CDC 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 CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { - if (*Len) { - furi_hal_vcp_on_cdc_rx(Buf, *Len); - } else { - USBD_CDC_ReceivePacket(&hUsbDeviceFS); - } - - return (USBD_OK); -} - -/** CDC_Transmit_FS Data to send over USB IN endpoint are sent over CDC interface - * through this function. - * @param Buf: Buffer of data to be sent - * @param Len: Number of data to be sent (in bytes) - * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY - */ -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) -{ - uint8_t result = USBD_OK; - - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; - if (hcdc->TxState != 0){ - return USBD_BUSY; - } - memcpy(UserTxBufferFS, Buf, Len); - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, Len); - result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); - - return result; -} - -/** CDC_TransmitCplt_FS Data transmited callback - * - * @note - * This function is IN transfer complete callback used to inform user that - * the submitted Data is successfully sent over USB. - * - * @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 CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum) { - uint8_t result = USBD_OK; - - furi_hal_vcp_on_cdc_tx_complete(*Len); - - return result; -} diff --git a/firmware/targets/f6/usb-glue/usbd_cdc_if.h b/firmware/targets/f6/usb-glue/usbd_cdc_if.h deleted file mode 100644 index fc0aefbe3..000000000 --- a/firmware/targets/f6/usb-glue/usbd_cdc_if.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_cdc.h" - -/* Define size for the receive and transmit buffer over CDC */ -/* It's up to user to redefine and/or remove those define */ -#define APP_RX_DATA_SIZE CDC_DATA_FS_MAX_PACKET_SIZE -#define APP_TX_DATA_SIZE CDC_DATA_FS_MAX_PACKET_SIZE - -/** CDC Interface callback. */ -extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; - -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f6/usb-glue/usbd_conf.c b/firmware/targets/f6/usb-glue/usbd_conf.c deleted file mode 100644 index cbc137e51..000000000 --- a/firmware/targets/f6/usb-glue/usbd_conf.c +++ /dev/null @@ -1,506 +0,0 @@ -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" - -#include - -#include "usbd_def.h" -#include "usbd_core.h" -#include "usbd_cdc.h" - -PCD_HandleTypeDef hpcd_USB_FS; -void Error_Handler(void); - -static USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status); - -static void SystemClockConfig_Resume(void); - -void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle) { - GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(pcdHandle->Instance==USB) { - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB GPIO Configuration - PA11 ------> USB_DM - PA12 ------> USB_DP - */ - 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_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF10_USB; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* Peripheral clock enable */ - __HAL_RCC_USB_CLK_ENABLE(); - - /* Peripheral interrupt init */ - HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(USB_LP_IRQn); - } -} - -void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) { - if(pcdHandle->Instance==USB) { - /* Peripheral clock disable */ - __HAL_RCC_USB_CLK_DISABLE(); - - /**USB GPIO Configuration - PA11 ------> USB_DM - PA12 ------> USB_DP - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); - - /* Peripheral interrupt Deinit*/ - HAL_NVIC_DisableIRQ(USB_LP_IRQn); - } -} - -/** Setup stage callback - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup); -} - -/** 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((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); -} - -/** 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((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); -} - -/** SOF callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Reset callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { - USBD_SpeedTypeDef speed = USBD_SPEED_FULL; - - if ( hpcd->Init.speed != PCD_SPEED_FULL) { - Error_Handler(); - } - - /* Set Speed. */ - USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed); - - /* Reset Device. */ - USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Suspend callback. - * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData); - - furi_hal_vcp_on_usb_suspend(); - - if (hpcd->Init.low_power_enable) { - /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ - SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } -} - -/** Resume callback. - * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) { - if (hpcd->Init.low_power_enable) { - /* Reset SLEEPDEEP bit of Cortex System Control Register. */ - SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - SystemClockConfig_Resume(); - } - - furi_hal_vcp_on_usb_resume(); - - USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData); -} - -/** ISOOUTIncomplete callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { - USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); -} - -/** ISOINIncomplete callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { - USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); -} - -/** Connect callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Disconnect callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Initializes the low level portion of the device driver. - * @param pdev: Device handle - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) { - /* Init USB Ip. */ - hpcd_USB_FS.pData = pdev; - - /* Link the driver to the stack. */ - pdev->pData = &hpcd_USB_FS; - - /* Enable USB power on Pwrctrl CR2 register. */ - HAL_PWREx_EnableVddUSB(); - - hpcd_USB_FS.Instance = USB; - hpcd_USB_FS.Init.dev_endpoints = 8; - hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; - hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd_USB_FS.Init.Sof_enable = DISABLE; - hpcd_USB_FS.Init.low_power_enable = DISABLE; - hpcd_USB_FS.Init.lpm_enable = DISABLE; - hpcd_USB_FS.Init.battery_charging_enable = DISABLE; - - if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK) { - Error_Handler(); - } - - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); - - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xC0); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x110); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0x100); - - return USBD_OK; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_DeInit(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_Start(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_Stop(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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 = (PCD_HandleTypeDef*) 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; - } -} - -/** Assigns a USB address to the device. - * @param pdev: Device handle - * @param dev_addr: Device address - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) { - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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, uint32_t size) { - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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, uint32_t size) { - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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((PCD_HandleTypeDef*) pdev->pData, ep_addr); -} - -/** Send LPM message to user layer - * @param hpcd: PCD handle - * @param msg: LPM message - * @retval None - */ -void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) { - switch (msg) { - case PCD_LPM_L0_ACTIVE: - if (hpcd->Init.low_power_enable) { - SystemClockConfig_Resume(); - /* Reset SLEEPDEEP bit of Cortex System Control Register. */ - SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } - USBD_LL_Resume(hpcd->pData); - break; - - case PCD_LPM_L1_ACTIVE: - USBD_LL_Suspend(hpcd->pData); - - /* Enter in STOP mode. */ - if (hpcd->Init.low_power_enable) { - /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ - SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } - break; - } -} - -/** Delays routine for the USB Device Library. - * @param Delay: Delay in ms - * @retval None - */ -void USBD_LL_Delay(uint32_t Delay) { - HAL_Delay(Delay); -} - -/** Static single allocation. - * @param size: Size of allocated memory - * @retval None - */ -void *USBD_static_malloc(uint32_t size) { - static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */ - return mem; -} - -/** Dummy memory free - * @param p: Pointer to allocated memory address - * @retval None - */ -void USBD_static_free(void *p) { -} - -/** Configures system clock after wake-up from USB resume callBack: - * enable HSI, PLL and select PLL as system clock source. - * @retval None - */ -static void SystemClockConfig_Resume(void) { -} - -/** Retuns the USB status depending on the HAL status: - * @param hal_status: HAL status - * @retval USB status - */ -USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status) { - USBD_StatusTypeDef usb_status = USBD_OK; - - switch (hal_status) - { - case HAL_OK : - usb_status = USBD_OK; - break; - case HAL_ERROR : - usb_status = USBD_FAIL; - break; - case HAL_BUSY : - usb_status = USBD_BUSY; - break; - case HAL_TIMEOUT : - usb_status = USBD_FAIL; - break; - default : - usb_status = USBD_FAIL; - break; - } - return usb_status; -} diff --git a/firmware/targets/f6/usb-glue/usbd_conf.h b/firmware/targets/f6/usb-glue/usbd_conf.h deleted file mode 100644 index 9e2a86f21..000000000 --- a/firmware/targets/f6/usb-glue/usbd_conf.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include -#include -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#define USBD_MAX_NUM_INTERFACES 1U -#define USBD_MAX_NUM_CONFIGURATION 1U -#define USBD_MAX_STR_DESC_SIZ 512U -#define USBD_DEBUG_LEVEL 0U -#define USBD_LPM_ENABLED 0U -#define USBD_SELF_POWERED 0U - -/****************************************/ -/* #define for FS and HS identification */ -#define DEVICE_FS 0 - -/* Memory management macros */ - -/** Alias for memory allocation. */ -#define USBD_malloc (void *)USBD_static_malloc - -/** Alias for memory release. */ -#define USBD_free USBD_static_free - -/** Alias for memory set. */ -#define USBD_memset memset - -/** Alias for memory copy. */ -#define USBD_memcpy memcpy - -/** Alias for delay. */ -#define USBD_Delay HAL_Delay - -/* 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 - -void *USBD_static_malloc(uint32_t size); -void USBD_static_free(void *p); - - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f6/usb-glue/usbd_desc.c b/firmware/targets/f6/usb-glue/usbd_desc.c deleted file mode 100644 index 96cc2cda5..000000000 --- a/firmware/targets/f6/usb-glue/usbd_desc.c +++ /dev/null @@ -1,206 +0,0 @@ -#include "usbd_core.h" -#include "usbd_desc.h" -#include "usbd_conf.h" -#include "furi-hal-version.h" - -#define USBD_VID 1155 -#define USBD_LANGID_STRING 1033 -#define USBD_MANUFACTURER_STRING "Flipper Devices Inc." -#define USBD_PID 22336 -#define USBD_CONFIGURATION_STRING "CDC Config" -#define USBD_INTERFACE_STRING "CDC Interface" - -static void Get_SerialNum(void); -static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len); - -uint8_t* USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); - -USBD_DescriptorsTypeDef CDC_Desc = { - USBD_CDC_DeviceDescriptor, - USBD_CDC_LangIDStrDescriptor, - USBD_CDC_ManufacturerStrDescriptor, - USBD_CDC_ProductStrDescriptor, - USBD_CDC_SerialStrDescriptor, - USBD_CDC_ConfigStrDescriptor, - USBD_CDC_InterfaceStrDescriptor -}; - -/** USB standard device descriptor. */ -__ALIGN_BEGIN uint8_t USBD_CDC_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { - 0x12, /*bLength */ - USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ - 0x00, /*bcdUSB */ - 0x02, - 0x02, /*bDeviceClass*/ - 0x02, /*bDeviceSubClass*/ - 0x00, /*bDeviceProtocol*/ - USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ - LOBYTE(USBD_VID), /*idVendor*/ - HIBYTE(USBD_VID), /*idVendor*/ - LOBYTE(USBD_PID), /*idProduct*/ - HIBYTE(USBD_PID), /*idProduct*/ - 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 lang indentifier descriptor. */ -__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) -}; - -/* Internal string descriptor. */ -__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; - -__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = { - USB_SIZ_STRING_SERIAL, - USB_DESC_TYPE_STRING, -}; - -/** Return the device descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_CDC_DeviceDesc); - return USBD_CDC_DeviceDesc; -} - -/** Return the LangID string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_LangIDDesc); - return USBD_LangIDDesc; -} - -/** Return the product string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString((uint8_t*)furi_hal_version_get_device_name_ptr(), USBD_StrDesc, length); - return USBD_StrDesc; -} - -/** Return the manufacturer string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); - return USBD_StrDesc; -} - -/** Return 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_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = USB_SIZ_STRING_SERIAL; - - /* Update the serial number string descriptor with the data from the unique - * ID */ - if(furi_hal_version_get_name_ptr()){ - char buffer[14] = "flip_"; - strncat(buffer, furi_hal_version_get_name_ptr(), 8); - USBD_GetString((uint8_t*) buffer, USBD_StringSerial, length); - } else { - Get_SerialNum(); - } - - return (uint8_t *) USBD_StringSerial; -} - -/** Return the configuration string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - if(speed == USBD_SPEED_HIGH) { - USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); - } else { - USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); - } - return USBD_StrDesc; -} - -/** Return the interface string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - if(speed == 0) { - USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); - } else { - USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); - } - return USBD_StrDesc; -} - -/** Create the serial number string descriptor - * @param None - * @retval None - */ -static void Get_SerialNum(void) { - uint32_t deviceserial0, deviceserial1, deviceserial2; - - deviceserial0 = *(uint32_t *) DEVICE_ID1; - deviceserial1 = *(uint32_t *) DEVICE_ID2; - deviceserial2 = *(uint32_t *) DEVICE_ID3; - - deviceserial0 += deviceserial2; - - if (deviceserial0 != 0) { - IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8); - IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); - } -} - -/** Convert Hex 32Bits value into char - * @param value: value to convert - * @param pbuf: pointer to the buffer - * @param len: buffer length - * @retval None - */ -static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len) { - uint8_t idx = 0; - - for (idx = 0; idx < len; idx++) { - if (((value >> 28)) < 0xA) { - pbuf[2 * idx] = (value >> 28) + '0'; - } else { - pbuf[2 * idx] = (value >> 28) + 'A' - 10; - } - - value = value << 4; - - pbuf[2 * idx + 1] = 0; - } -} diff --git a/firmware/targets/f6/usb-glue/usbd_desc.h b/firmware/targets/f6/usb-glue/usbd_desc.h deleted file mode 100644 index 795b33e4a..000000000 --- a/firmware/targets/f6/usb-glue/usbd_desc.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "usbd_def.h" - -#define DEVICE_ID1 (UID_BASE) -#define DEVICE_ID2 (UID_BASE + 0x4) -#define DEVICE_ID3 (UID_BASE + 0x8) - -#define USB_SIZ_STRING_SERIAL 0x1E - -extern USBD_DescriptorsTypeDef CDC_Desc; - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f7/Inc/stm32.h b/firmware/targets/f7/Inc/stm32.h new file mode 100644 index 000000000..45344fe3c --- /dev/null +++ b/firmware/targets/f7/Inc/stm32.h @@ -0,0 +1,52 @@ +#ifndef _STM32_H_ +#define _STM32_H_ + +/* modify bitfield */ +#define _BMD(reg, msk, val) (reg) = (((reg) & ~(msk)) | (val)) +/* set bitfield */ +#define _BST(reg, bits) (reg) = ((reg) | (bits)) +/* clear bitfield */ +#define _BCL(reg, bits) (reg) = ((reg) & ~(bits)) +/* wait until bitfield set */ +#define _WBS(reg, bits) while(((reg) & (bits)) == 0) +/* wait until bitfield clear */ +#define _WBC(reg, bits) while(((reg) & (bits)) != 0) +/* wait for bitfield value */ +#define _WVL(reg, msk, val) while(((reg) & (msk)) != (val)) +/* bit value */ +#define _BV(bit) (0x01 << (bit)) + +#if defined(STM32F0) + #include "STM32F0xx/Include/stm32f0xx.h" +#elif defined(STM32F1) + #include "STM32F1xx/Include/stm32f1xx.h" +#elif defined(STM32F2) + #include "STM32F2xx/Include/stm32f2xx.h" +#elif defined(STM32F3) + #include "STM32F3xx/Include/stm32f3xx.h" +#elif defined(STM32F4) + #include "STM32F4xx/Include/stm32f4xx.h" +#elif defined(STM32F7) + #include "STM32F7xx/Include/stm32f7xx.h" +#elif defined(STM32H7) + #include "STM32H7xx/Include/stm32h7xx.h" +#elif defined(STM32L0) + #include "STM32L0xx/Include/stm32l0xx.h" +#elif defined(STM32L1) + #include "STM32L1xx/Include/stm32l1xx.h" +#elif defined(STM32L4) + #include "STM32L4xx/Include/stm32l4xx.h" +#elif defined(STM32L5) + #include "STM32L5xx/Include/stm32l5xx.h" +#elif defined(STM32G0) + #include "STM32G0xx/Include/stm32g0xx.h" +#elif defined(STM32G4) + #include "STM32G4xx/Include/stm32g4xx.h" +#elif defined(STM32WB) + #include "STM32WBxx/Include/stm32wbxx.h" +#else + #error "STM32 family not defined" +#endif + + +#endif // _STM32_H_ diff --git a/firmware/targets/f7/Src/stm32wbxx_it.c b/firmware/targets/f7/Src/stm32wbxx_it.c index 01fbdc1d2..6f70fb5eb 100644 --- a/firmware/targets/f7/Src/stm32wbxx_it.c +++ b/firmware/targets/f7/Src/stm32wbxx_it.c @@ -2,8 +2,9 @@ #include "stm32wbxx_it.h" #include "FreeRTOS.h" #include "task.h" +#include "usbd_core.h" -extern PCD_HandleTypeDef hpcd_USB_FS; +extern usbd_device udev; extern COMP_HandleTypeDef hcomp1; extern RTC_HandleTypeDef hrtc; extern TIM_HandleTypeDef htim1; @@ -20,7 +21,7 @@ void SysTick_Handler(void) { } void USB_LP_IRQHandler(void) { - HAL_PCD_IRQHandler(&hpcd_USB_FS); + usbd_poll(&udev); } void COMP_IRQHandler(void) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c new file mode 100644 index 000000000..09efbec38 --- /dev/null +++ b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c @@ -0,0 +1,555 @@ +#include "furi-hal-version.h" +#include "furi-hal-usb_i.h" +#include "furi-hal-vcp_i.h" +#include "furi-hal-usb-cdc_i.h" +#include + +#include "usb.h" +#include "usb_cdc.h" + +#define CDC0_RXD_EP 0x01 +#define CDC0_TXD_EP 0x82 +#define CDC0_NTF_EP 0x83 + +#define CDC1_RXD_EP 0x04 +#define CDC1_TXD_EP 0x85 +#define CDC1_NTF_EP 0x86 + +#define CDC_NTF_SZ 0x08 + +struct CdcIadDescriptor { + struct usb_iad_descriptor comm_iad; + struct usb_interface_descriptor comm; + struct usb_cdc_header_desc cdc_hdr; + struct usb_cdc_call_mgmt_desc cdc_mgmt; + struct usb_cdc_acm_desc cdc_acm; + struct usb_cdc_union_desc cdc_union; + struct usb_endpoint_descriptor comm_ep; + struct usb_interface_descriptor data; + struct usb_endpoint_descriptor data_eprx; + struct usb_endpoint_descriptor data_eptx; +}; + +struct CdcConfigDescriptorSingle { + struct usb_config_descriptor config; + struct CdcIadDescriptor iad_0; +} __attribute__((packed)); + +struct CdcConfigDescriptorDual { + struct usb_config_descriptor config; + struct CdcIadDescriptor iad_0; + struct CdcIadDescriptor iad_1; +} __attribute__((packed)); + +static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Flipper Devices Inc."); + +/* Device descriptor */ +static const struct usb_device_descriptor cdc_device_desc = { + .bLength = sizeof(struct usb_device_descriptor), + .bDescriptorType = USB_DTYPE_DEVICE, + .bcdUSB = VERSION_BCD(2,0,0), + .bDeviceClass = USB_CLASS_IAD, + .bDeviceSubClass = USB_SUBCLASS_IAD, + .bDeviceProtocol = USB_PROTO_IAD, + .bMaxPacketSize0 = USB_EP0_SIZE, + .idVendor = 0x0483, + .idProduct = 0x5740, + .bcdDevice = VERSION_BCD(1,0,0), + .iManufacturer = UsbDevManuf, + .iProduct = UsbDevProduct, + .iSerialNumber = UsbDevSerial, + .bNumConfigurations = 1, +}; + +/* Device configuration descriptor - single mode*/ +static const struct CdcConfigDescriptorSingle cdc_cfg_desc_single = { + .config = { + .bLength = sizeof(struct usb_config_descriptor), + .bDescriptorType = USB_DTYPE_CONFIGURATION, + .wTotalLength = sizeof(struct CdcConfigDescriptorSingle), + .bNumInterfaces = 2, + + .bConfigurationValue = 1, + .iConfiguration = NO_DESCRIPTOR, + .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED, + .bMaxPower = USB_CFG_POWER_MA(100), + }, + .iad_0 = { + .comm_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 0, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .comm = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .cdc_hdr = { + .bFunctionLength = sizeof(struct usb_cdc_header_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_HEADER, + .bcdCDC = VERSION_BCD(1,1,0), + }, + .cdc_mgmt = { + .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .cdc_acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_UNION, + .bMasterInterface0 = 0, + .bSlaveInterface0 = 1, + }, + .comm_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_NTF_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = CDC_NTF_SZ, + .bInterval = 0xFF, + }, + .data = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = USB_SUBCLASS_NONE, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .data_eprx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_RXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + .data_eptx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_TXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + }, +}; + +/* Device configuration descriptor - dual mode*/ +static const struct CdcConfigDescriptorDual cdc_cfg_desc_dual = { + .config = { + .bLength = sizeof(struct usb_config_descriptor), + .bDescriptorType = USB_DTYPE_CONFIGURATION, + .wTotalLength = sizeof(struct CdcConfigDescriptorDual), + .bNumInterfaces = 4, + + .bConfigurationValue = 1, + .iConfiguration = NO_DESCRIPTOR, + .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED, + .bMaxPower = USB_CFG_POWER_MA(100), + }, + .iad_0 = { + .comm_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 0, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .comm = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .cdc_hdr = { + .bFunctionLength = sizeof(struct usb_cdc_header_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_HEADER, + .bcdCDC = VERSION_BCD(1,1,0), + }, + .cdc_mgmt = { + .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .cdc_acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_UNION, + .bMasterInterface0 = 0, + .bSlaveInterface0 = 1, + }, + .comm_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_NTF_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = CDC_NTF_SZ, + .bInterval = 0xFF, + }, + .data = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = USB_SUBCLASS_NONE, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .data_eprx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_RXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + .data_eptx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC0_TXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + }, + .iad_1 = { + .comm_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 2, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .comm = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 2+0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .cdc_hdr = { + .bFunctionLength = sizeof(struct usb_cdc_header_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_HEADER, + .bcdCDC = VERSION_BCD(1,1,0), + }, + .cdc_mgmt = { + .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 2+1, + }, + .cdc_acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_desc), + .bDescriptorType = USB_DTYPE_CS_INTERFACE, + .bDescriptorSubType = USB_DTYPE_CDC_UNION, + .bMasterInterface0 = 2+0, + .bSlaveInterface0 = 2+1, + }, + .comm_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC1_NTF_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = CDC_NTF_SZ, + .bInterval = 0xFF, + }, + .data = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 2+1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = USB_SUBCLASS_NONE, + .bInterfaceProtocol = USB_PROTO_NONE, + .iInterface = NO_DESCRIPTOR, + }, + .data_eprx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC1_RXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + .data_eptx = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = CDC1_TXD_EP, + .bmAttributes = USB_EPTYPE_BULK, + .wMaxPacketSize = CDC_DATA_SZ, + .bInterval = 0x01, + }, + }, +}; + +static struct usb_cdc_line_coding cdc_line = { + .dwDTERate = 38400, + .bCharFormat = USB_CDC_1_STOP_BITS, + .bParityType = USB_CDC_NO_PARITY, + .bDataBits = 8, +}; +static void cdc_init(usbd_device* dev, struct UsbInterface* intf); +static void cdc_deinit(usbd_device *dev); +static void cdc_on_wakeup(usbd_device *dev); +static void cdc_on_suspend(usbd_device *dev); + +static usbd_respond cdc_ep_config (usbd_device *dev, uint8_t cfg); +static usbd_respond cdc_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback); +static usbd_device* usb_dev; +static struct UsbInterface* cdc_if_cur = NULL; + +struct UsbInterface usb_cdc_single = { + .init = cdc_init, + .deinit = cdc_deinit, + .wakeup = cdc_on_wakeup, + .suspend = cdc_on_suspend, + + .dev_descr = (struct usb_device_descriptor*)&cdc_device_desc, + + .str_manuf_descr = (void*)&dev_manuf_desc, + .str_prod_descr = NULL, + .str_serial_descr = NULL, + + .cfg_descr = (void*)&cdc_cfg_desc_single, +}; + +struct UsbInterface usb_cdc_dual = { + .init = cdc_init, + .deinit = cdc_deinit, + .wakeup = cdc_on_wakeup, + .suspend = cdc_on_suspend, + + .dev_descr = (struct usb_device_descriptor*)&cdc_device_desc, + + .str_manuf_descr = (void*)&dev_manuf_desc, + .str_prod_descr = NULL, + .str_serial_descr = NULL, + + .cfg_descr = (void*)&cdc_cfg_desc_dual, +}; + +static void cdc_init(usbd_device* dev, struct UsbInterface* intf) { + usb_dev = dev; + cdc_if_cur = intf; + + char* name = (char*)furi_hal_version_get_device_name_ptr(); + uint8_t len = (name == NULL) ? (0) : (strlen(name)); + struct usb_string_descriptor* dev_prod_desc = furi_alloc(len * 2 + 2); + dev_prod_desc->bLength = len * 2 + 2; + dev_prod_desc->bDescriptorType = USB_DTYPE_STRING; + for (uint8_t i = 0; i < len; i++) + dev_prod_desc->wString[i] = name[i]; + + name = (char*)furi_hal_version_get_name_ptr(); + len = (name == NULL) ? (0) : (strlen(name)); + struct usb_string_descriptor* dev_serial_desc = furi_alloc((len + 5) * 2 + 2); + dev_serial_desc->bLength = (len + 5) * 2 + 2; + dev_serial_desc->bDescriptorType = USB_DTYPE_STRING; + memcpy(dev_serial_desc->wString, "f\0l\0i\0p\0_\0", 5*2); + for (uint8_t i = 0; i < len; i++) + dev_serial_desc->wString[i+5] = name[i]; + + cdc_if_cur->str_prod_descr = dev_prod_desc; + cdc_if_cur->str_serial_descr = dev_serial_desc; + + usbd_reg_config(dev, cdc_ep_config); + usbd_reg_control(dev, cdc_control); + + usbd_connect(dev, true); +} + +static void cdc_deinit(usbd_device *dev) { + usbd_reg_config(dev, NULL); + usbd_reg_control(dev, NULL); + + free(cdc_if_cur->str_prod_descr); + free(cdc_if_cur->str_serial_descr); + + cdc_if_cur = NULL; +} + +void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { + if (if_num == 0) + usbd_ep_write(usb_dev, CDC0_TXD_EP, buf, len); + else + usbd_ep_write(usb_dev, CDC1_TXD_EP, buf, len); +} + +int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) { + if (if_num == 0) + return usbd_ep_read(usb_dev, CDC0_RXD_EP, buf, max_len); + else + return usbd_ep_read(usb_dev, CDC1_RXD_EP, buf, max_len); +} + +static void cdc_on_wakeup(usbd_device *dev) { + furi_hal_vcp_on_usb_resume(); +} + +static void cdc_on_suspend(usbd_device *dev) { + furi_hal_vcp_on_usb_suspend(); +} + +static void cdc_rx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) { + if (ep == CDC0_RXD_EP) + furi_hal_vcp_on_cdc_rx(0); + else + furi_hal_vcp_on_cdc_rx(1); +} + +static void cdc_tx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) { + if (ep == CDC0_TXD_EP) + furi_hal_vcp_on_cdc_tx_complete(0); + else + furi_hal_vcp_on_cdc_tx_complete(1); +} + +static void cdc_txrx_ep_callback (usbd_device *dev, uint8_t event, uint8_t ep) { + if (event == usbd_evt_eptx) { + cdc_tx_ep_callback(dev, event, ep); + } else { + cdc_rx_ep_callback(dev, event, ep); + } +} + +/* Configure endpoints */ +static usbd_respond cdc_ep_config (usbd_device *dev, uint8_t cfg) { + uint8_t if_cnt = ((struct usb_config_descriptor*)(cdc_if_cur->cfg_descr))->bNumInterfaces; + switch (cfg) { + case 0: + /* deconfiguring device */ + usbd_ep_deconfig(dev, CDC0_NTF_EP); + usbd_ep_deconfig(dev, CDC0_TXD_EP); + usbd_ep_deconfig(dev, CDC0_RXD_EP); + usbd_reg_endpoint(dev, CDC0_RXD_EP, 0); + usbd_reg_endpoint(dev, CDC0_TXD_EP, 0); + if (if_cnt == 4) { + usbd_ep_deconfig(dev, CDC1_NTF_EP); + usbd_ep_deconfig(dev, CDC1_TXD_EP); + usbd_ep_deconfig(dev, CDC1_RXD_EP); + usbd_reg_endpoint(dev, CDC1_RXD_EP, 0); + usbd_reg_endpoint(dev, CDC1_TXD_EP, 0); + } + return usbd_ack; + case 1: + /* configuring device */ + if ((CDC0_TXD_EP & 0x7F) != (CDC0_RXD_EP & 0x7F)) { + usbd_ep_config(dev, CDC0_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC0_RXD_EP, cdc_rx_ep_callback); + usbd_reg_endpoint(dev, CDC0_TXD_EP, cdc_tx_ep_callback); + } else { + usbd_ep_config(dev, CDC0_RXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_TXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC0_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC0_RXD_EP, cdc_txrx_ep_callback); + usbd_reg_endpoint(dev, CDC0_TXD_EP, cdc_txrx_ep_callback); + } + usbd_ep_write(dev, CDC0_TXD_EP, 0, 0); + + if (if_cnt == 4) { + if ((CDC1_TXD_EP & 0x7F) != (CDC1_RXD_EP & 0x7F)) { + usbd_ep_config(dev, CDC1_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC1_RXD_EP, cdc_rx_ep_callback); + usbd_reg_endpoint(dev, CDC1_TXD_EP, cdc_tx_ep_callback); + } else { + usbd_ep_config(dev, CDC1_RXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_TXD_EP, USB_EPTYPE_BULK, CDC_DATA_SZ); + usbd_ep_config(dev, CDC1_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ); + usbd_reg_endpoint(dev, CDC1_RXD_EP, cdc_txrx_ep_callback); + usbd_reg_endpoint(dev, CDC1_TXD_EP, cdc_txrx_ep_callback); + } + usbd_ep_write(dev, CDC1_TXD_EP, 0, 0); + } + return usbd_ack; + default: + return usbd_fail; + } +} + +/* Control requests handler */ +static usbd_respond cdc_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) { + /* CDC control requests */ + if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS) + && req->wIndex == 0 ) { + switch (req->bRequest) { + case USB_CDC_SET_CONTROL_LINE_STATE: + furi_hal_vcp_on_cdc_control_line(req->wValue); + return usbd_ack; + case USB_CDC_SET_LINE_CODING: + memcpy(&cdc_line, req->data, sizeof(cdc_line)); + return usbd_ack; + case USB_CDC_GET_LINE_CODING: + dev->status.data_ptr = &cdc_line; + dev->status.data_count = sizeof(cdc_line); + return usbd_ack; + default: + return usbd_fail; + } + } + return usbd_fail; +} diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h new file mode 100644 index 000000000..636b3c046 --- /dev/null +++ b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h @@ -0,0 +1,7 @@ +#pragma once + +#define CDC_DATA_SZ 0x40 + +void furi_hal_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len); + +int32_t furi_hal_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len); diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb-hid.c b/firmware/targets/f7/furi-hal/furi-hal-usb-hid.c new file mode 100644 index 000000000..384236107 --- /dev/null +++ b/firmware/targets/f7/furi-hal/furi-hal-usb-hid.c @@ -0,0 +1,264 @@ +#include "furi-hal-version.h" +#include "furi-hal-usb_i.h" +#include + +#include "usb.h" +#include "usb_hid.h" +#include "hid_usage_desktop.h" +#include "hid_usage_button.h" + +#define HID_RIN_EP 0x81 +#define HID_RIN_SZ 0x10 + +struct HidIadDescriptor { + struct usb_iad_descriptor hid_iad; + struct usb_interface_descriptor hid; + struct usb_hid_descriptor hid_desc; + struct usb_endpoint_descriptor hid_ep; +}; + +struct HidConfigDescriptor { + struct usb_config_descriptor config; + struct HidIadDescriptor iad_0; +} __attribute__((packed)); + +/* HID mouse report desscriptor. 2 axis 5 buttons */ +static const uint8_t hid_report_desc[] = { + HID_USAGE_PAGE(HID_PAGE_DESKTOP), + HID_USAGE(HID_DESKTOP_MOUSE), + HID_COLLECTION(HID_APPLICATION_COLLECTION), + HID_USAGE(HID_DESKTOP_POINTER), + HID_COLLECTION(HID_PHYSICAL_COLLECTION), + HID_USAGE(HID_DESKTOP_X), + HID_USAGE(HID_DESKTOP_Y), + HID_LOGICAL_MINIMUM(-127), + HID_LOGICAL_MAXIMUM(127), + HID_REPORT_SIZE(8), + HID_REPORT_COUNT(2), + HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE ), + HID_USAGE_PAGE(HID_PAGE_BUTTON), + HID_USAGE_MINIMUM(1), + HID_USAGE_MAXIMUM(5), + HID_LOGICAL_MINIMUM(0), + HID_LOGICAL_MAXIMUM(1), + HID_REPORT_SIZE(1), + HID_REPORT_COUNT(5), + HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE ), + HID_REPORT_SIZE(1), + HID_REPORT_COUNT(3), + HID_INPUT(HID_IOF_CONSTANT), + HID_END_COLLECTION, + HID_END_COLLECTION, +}; + +static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Logitech"); +static const struct usb_string_descriptor dev_prod_desc = USB_STRING_DESC("USB Receiver"); +static const struct usb_string_descriptor dev_serial_desc = USB_STRING_DESC("1234567890"); + +/* Device descriptor */ +static const struct usb_device_descriptor hid_device_desc = { + .bLength = sizeof(struct usb_device_descriptor), + .bDescriptorType = USB_DTYPE_DEVICE, + .bcdUSB = VERSION_BCD(2,0,0), + .bDeviceClass = USB_CLASS_IAD, + .bDeviceSubClass = USB_SUBCLASS_IAD, + .bDeviceProtocol = USB_PROTO_IAD, + .bMaxPacketSize0 = USB_EP0_SIZE, + .idVendor = 0x046d, + .idProduct = 0xc529, + .bcdDevice = VERSION_BCD(1,0,0), + .iManufacturer = UsbDevManuf, + .iProduct = UsbDevProduct, + .iSerialNumber = UsbDevSerial, + .bNumConfigurations = 1, +}; + +/* Device configuration descriptor */ +static const struct HidConfigDescriptor hid_cfg_desc = { + .config = { + .bLength = sizeof(struct usb_config_descriptor), + .bDescriptorType = USB_DTYPE_CONFIGURATION, + .wTotalLength = sizeof(struct HidConfigDescriptor), + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = NO_DESCRIPTOR, + .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED, + .bMaxPower = USB_CFG_POWER_MA(100), + }, + .iad_0 = { + .hid_iad = { + .bLength = sizeof(struct usb_iad_descriptor), + .bDescriptorType = USB_DTYPE_INTERFASEASSOC, + .bFirstInterface = 0, + .bInterfaceCount = 1, + .bFunctionClass = USB_CLASS_PER_INTERFACE, + .bFunctionSubClass = USB_SUBCLASS_NONE, + .bFunctionProtocol = USB_PROTO_NONE, + .iFunction = NO_DESCRIPTOR, + }, + .hid = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DTYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT, + .bInterfaceProtocol = USB_HID_PROTO_NONBOOT, + .iInterface = NO_DESCRIPTOR, + }, + .hid_desc = { + .bLength = sizeof(struct usb_hid_descriptor), + .bDescriptorType = USB_DTYPE_HID, + .bcdHID = VERSION_BCD(1,0,0), + .bCountryCode = USB_HID_COUNTRY_NONE, + .bNumDescriptors = 1, + .bDescriptorType0 = USB_DTYPE_HID_REPORT, + .wDescriptorLength0 = sizeof(hid_report_desc), + }, + .hid_ep = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DTYPE_ENDPOINT, + .bEndpointAddress = HID_RIN_EP, + .bmAttributes = USB_EPTYPE_INTERRUPT, + .wMaxPacketSize = HID_RIN_SZ, + .bInterval = 50, + }, + }, +}; + +static struct { + int8_t x; + int8_t y; + uint8_t buttons; +} __attribute__((packed)) hid_report_data; + +static void hid_init(usbd_device* dev, struct UsbInterface* intf); +static void hid_deinit(usbd_device *dev); +static void hid_on_wakeup(usbd_device *dev); +static void hid_on_suspend(usbd_device *dev); + +static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg); +static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback); +static usbd_device* usb_dev; + +struct UsbInterface usb_hid = { + .init = hid_init, + .deinit = hid_deinit, + .wakeup = hid_on_wakeup, + .suspend = hid_on_suspend, + + .dev_descr = (struct usb_device_descriptor*)&hid_device_desc, + + .str_manuf_descr = (void*)&dev_manuf_desc, + .str_prod_descr = (void*)&dev_prod_desc, + .str_serial_descr = (void*)&dev_serial_desc, + + .cfg_descr = (void*)&hid_cfg_desc, +}; + +static void hid_init(usbd_device* dev, struct UsbInterface* intf) { + usb_dev = dev; + + usbd_reg_config(dev, hid_ep_config); + usbd_reg_control(dev, hid_control); + + usbd_connect(dev, true); +} + +static void hid_deinit(usbd_device *dev) { + usbd_reg_config(dev, NULL); + usbd_reg_control(dev, NULL); +} + +static void hid_on_wakeup(usbd_device *dev) { +} + +static void hid_on_suspend(usbd_device *dev) { +} + +/* HID mouse IN endpoint callback */ +static void hid_mouse_move(usbd_device *dev, uint8_t event, uint8_t ep) { + static uint8_t t = 0; + if (t < 0x10) { + hid_report_data.x = 1; + hid_report_data.y = 0; + } else if (t < 0x20) { + hid_report_data.x = 1; + hid_report_data.y = 1; + } else if (t < 0x30) { + hid_report_data.x = 0; + hid_report_data.y = 1; + } else if (t < 0x40) { + hid_report_data.x = -1; + hid_report_data.y = 1; + } else if (t < 0x50) { + hid_report_data.x = -1; + hid_report_data.y = 0; + } else if (t < 0x60) { + hid_report_data.x = -1; + hid_report_data.y = -1; + } else if (t < 0x70) { + hid_report_data.x = 0; + hid_report_data.y = -1; + } else { + hid_report_data.x = 1; + hid_report_data.y = -1; + } + t = (t + 1) & 0x7F; + usbd_ep_write(dev, ep, &hid_report_data, sizeof(hid_report_data)); +} + +/* Configure endpoints */ +static usbd_respond hid_ep_config (usbd_device *dev, uint8_t cfg) { + switch (cfg) { + case 0: + /* deconfiguring device */ + usbd_ep_deconfig(dev, HID_RIN_EP); + usbd_reg_endpoint(dev, HID_RIN_EP, 0); + return usbd_ack; + case 1: + /* configuring device */ + usbd_ep_config(dev, HID_RIN_EP, USB_EPTYPE_INTERRUPT, HID_RIN_SZ); + usbd_reg_endpoint(dev, HID_RIN_EP, hid_mouse_move); + usbd_ep_write(dev, HID_RIN_EP, 0, 0); + return usbd_ack; + default: + return usbd_fail; + } +} + +/* Control requests handler */ +static usbd_respond hid_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) { + /* HID control requests */ + if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS) + && req->wIndex == 0 ) { + switch (req->bRequest) { + case USB_HID_SETIDLE: + return usbd_ack; + case USB_HID_GETREPORT: + dev->status.data_ptr = &hid_report_data; + dev->status.data_count = sizeof(hid_report_data); + return usbd_ack; + default: + return usbd_fail; + } + } + if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_STANDARD) + && req->wIndex == 0 + && req->bRequest == USB_STD_GET_DESCRIPTOR) { + switch (req->wValue >> 8) { + case USB_DTYPE_HID: + dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.iad_0.hid_desc); + dev->status.data_count = sizeof(hid_cfg_desc.iad_0.hid_desc); + return usbd_ack; + case USB_DTYPE_HID_REPORT: + dev->status.data_ptr = (uint8_t*)hid_report_desc; + dev->status.data_count = sizeof(hid_report_desc); + return usbd_ack; + default: + return usbd_fail; + } + } + return usbd_fail; +} diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb.c b/firmware/targets/f7/furi-hal/furi-hal-usb.c new file mode 100644 index 000000000..fc5add2e7 --- /dev/null +++ b/firmware/targets/f7/furi-hal/furi-hal-usb.c @@ -0,0 +1,164 @@ +#include "furi-hal-version.h" +#include "furi-hal-usb_i.h" +#include "furi-hal-usb.h" +#include "furi-hal-vcp_i.h" +#include + +#include "usb.h" + +#define USB_RECONNECT_DELAY 500 + +extern struct UsbInterface usb_cdc_single; +extern struct UsbInterface usb_cdc_dual; +extern struct UsbInterface usb_hid; + +static struct UsbInterface* const usb_if_modes[UsbModesNum] = { + NULL, + &usb_cdc_single, + &usb_cdc_dual, + &usb_hid, + NULL,//&usb_hid_u2f, +}; + +static const struct usb_string_descriptor dev_lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US); + +static uint32_t ubuf[0x20]; +usbd_device udev; + +static usbd_respond usb_descriptor_get (usbd_ctlreq *req, void **address, uint16_t *length); +static void susp_evt(usbd_device *dev, uint8_t event, uint8_t ep); +static void wkup_evt(usbd_device *dev, uint8_t event, uint8_t ep); + +struct UsbCfg{ + osTimerId_t reconnect_tmr; + UsbMode mode_cur; + UsbMode mode_next; + bool enabled; +} usb_config; + +static void furi_hal_usb_tmr_cb(void* context); + +/* Low-level init */ +void furi_hal_usb_init(void) { + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + LL_PWR_EnableVddUSB(); + + GPIO_InitStruct.Pin = LL_GPIO_PIN_11 | LL_GPIO_PIN_12; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_10; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + usbd_init(&udev, &usbd_hw, USB_EP0_SIZE, ubuf, sizeof(ubuf)); + usbd_enable(&udev, true); + + usbd_reg_descr(&udev, usb_descriptor_get); + usbd_reg_event(&udev, usbd_evt_susp, susp_evt); + usbd_reg_event(&udev, usbd_evt_wkup, wkup_evt); + + usb_config.enabled = false; + usb_config.reconnect_tmr = NULL; + HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); + NVIC_EnableIRQ(USB_LP_IRQn); + + FURI_LOG_I("FuriHalUsb", "Init OK"); +} + +void furi_hal_usb_set_config(UsbMode new_mode) { + if (new_mode != usb_config.mode_cur) { + if (usb_config.enabled) { + usb_config.mode_next = new_mode; + if (usb_config.reconnect_tmr == NULL) + usb_config.reconnect_tmr = osTimerNew(furi_hal_usb_tmr_cb, osTimerOnce, NULL, NULL); + furi_hal_usb_disable(); + osTimerStart(usb_config.reconnect_tmr, USB_RECONNECT_DELAY); + } + else { + if (usb_if_modes[usb_config.mode_cur] != NULL) + usb_if_modes[usb_config.mode_cur]->deinit(&udev); + if (usb_if_modes[new_mode] != NULL) { + usb_if_modes[new_mode]->init(&udev, usb_if_modes[new_mode]); + FURI_LOG_I("FuriHalUsb", "USB mode change %u -> %u", usb_config.mode_cur, new_mode); + usb_config.enabled = true; + usb_config.mode_cur = new_mode; + } + } + } +} + +void furi_hal_usb_disable() { + if (usb_config.enabled) { + susp_evt(&udev, 0, 0); + usbd_connect(&udev, false); + usb_config.enabled = false; + FURI_LOG_I("FuriHalUsb", "USB Disable"); + } +} + +void furi_hal_usb_enable() { + if ((!usb_config.enabled) && (usb_if_modes[usb_config.mode_cur] != NULL)) { + usbd_connect(&udev, true); + usb_config.enabled = true; + FURI_LOG_I("FuriHalUsb", "USB Enable"); + } +} + +static void furi_hal_usb_tmr_cb(void* context) { + furi_hal_usb_set_config(usb_config.mode_next); +} + +/* Get device / configuration descriptors */ +static usbd_respond usb_descriptor_get (usbd_ctlreq *req, void **address, uint16_t *length) { + const uint8_t dtype = req->wValue >> 8; + const uint8_t dnumber = req->wValue & 0xFF; + const void* desc; + uint16_t len = 0; + if (usb_if_modes[usb_config.mode_cur] == NULL) + return usbd_fail; + + switch (dtype) { + case USB_DTYPE_DEVICE: + desc = usb_if_modes[usb_config.mode_cur]->dev_descr; + break; + case USB_DTYPE_CONFIGURATION: + desc = usb_if_modes[usb_config.mode_cur]->cfg_descr; + len = ((struct usb_string_descriptor*)(usb_if_modes[usb_config.mode_cur]->cfg_descr))->wString[0]; + break; + case USB_DTYPE_STRING: + if (dnumber == UsbDevLang) { + desc = &dev_lang_desc; + } else if (dnumber == UsbDevManuf) { + desc = usb_if_modes[usb_config.mode_cur]->str_manuf_descr; + } else if (dnumber == UsbDevProduct) { + desc = usb_if_modes[usb_config.mode_cur]->str_prod_descr; + } else if (dnumber == UsbDevSerial) { + desc = usb_if_modes[usb_config.mode_cur]->str_serial_descr; + } else + return usbd_fail; + break; + default: + return usbd_fail; + } + if (desc == NULL) + return usbd_fail; + + if (len == 0) { + len = ((struct usb_header_descriptor*)desc)->bLength; + } + *address = (void*)desc; + *length = len; + return usbd_ack; +} + +static void susp_evt(usbd_device *dev, uint8_t event, uint8_t ep) { + if (usb_if_modes[usb_config.mode_cur] != NULL) + usb_if_modes[usb_config.mode_cur]->suspend(&udev); +} + +static void wkup_evt(usbd_device *dev, uint8_t event, uint8_t ep) { + if (usb_if_modes[usb_config.mode_cur] != NULL) + usb_if_modes[usb_config.mode_cur]->wakeup(&udev); +} diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb_i.h b/firmware/targets/f7/furi-hal/furi-hal-usb_i.h new file mode 100644 index 000000000..b329c51f7 --- /dev/null +++ b/firmware/targets/f7/furi-hal/furi-hal-usb_i.h @@ -0,0 +1,28 @@ +#pragma once + +#include "usb.h" + +#define USB_EP0_SIZE 8 + +/* String descriptors */ +enum UsbDevDescStr{ + UsbDevLang = 0, + UsbDevManuf = 1, + UsbDevProduct = 2, + UsbDevSerial = 3, +}; + +struct UsbInterface { + void (*init)(usbd_device *dev, struct UsbInterface* intf); + void (*deinit)(usbd_device *dev); + void (*wakeup)(usbd_device *dev); + void (*suspend)(usbd_device *dev); + + struct usb_device_descriptor* dev_descr; + + void* str_manuf_descr; + void* str_prod_descr; + void* str_serial_descr; + + void* cfg_descr; +}; diff --git a/firmware/targets/f7/furi-hal/furi-hal-vcp.c b/firmware/targets/f7/furi-hal/furi-hal-vcp.c index 88de32b56..e276c4a30 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-vcp.c +++ b/firmware/targets/f7/furi-hal/furi-hal-vcp.c @@ -1,12 +1,12 @@ #include +#include #include -#include #include -#define FURI_HAL_VCP_RX_BUFFER_SIZE (APP_RX_DATA_SIZE * 5) - -extern USBD_HandleTypeDef hUsbDeviceFS; +#define APP_RX_DATA_SIZE CDC_DATA_SZ +#define APP_TX_DATA_SIZE CDC_DATA_SZ +#define FURI_HAL_VCP_RX_BUFFER_SIZE (APP_RX_DATA_SIZE * 16) typedef struct { volatile bool connected; @@ -22,8 +22,11 @@ static FuriHalVcp* furi_hal_vcp = NULL; static const uint8_t ascii_soh = 0x01; static const uint8_t ascii_eot = 0x04; +static uint8_t* vcp_rx_buf; + void furi_hal_vcp_init() { furi_hal_vcp = furi_alloc(sizeof(FuriHalVcp)); + vcp_rx_buf = furi_alloc(APP_RX_DATA_SIZE); furi_hal_vcp->connected = false; furi_hal_vcp->rx_stream = xStreamBufferCreate(FURI_HAL_VCP_RX_BUFFER_SIZE, 1); @@ -40,10 +43,8 @@ size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { size_t received = xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, portMAX_DELAY); if(furi_hal_vcp->rx_stream_full - &&xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { + && xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { furi_hal_vcp->rx_stream_full = false; - // data accepted, start waiting for next packet - USBD_CDC_ReceivePacket(&hUsbDeviceFS); } return received; @@ -67,13 +68,9 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { batch_size = APP_TX_DATA_SIZE; } - if (CDC_Transmit_FS((uint8_t*)buffer, batch_size) == USBD_OK) { - size -= batch_size; - buffer += batch_size; - } else { - FURI_LOG_E("FuriHalVcp", "CDC_Transmit_FS failed"); - osDelay(50); - } + furi_hal_cdc_send(0, (uint8_t*)buffer, batch_size); + size -= batch_size; + buffer += batch_size; } } @@ -89,6 +86,8 @@ void furi_hal_vcp_on_usb_suspend() { } void furi_hal_vcp_on_cdc_control_line(uint8_t state) { + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; // bit 0: DTR state, bit 1: RTS state // bool dtr = state & 0b01; bool dtr = state & 0b1; @@ -96,33 +95,45 @@ void furi_hal_vcp_on_cdc_control_line(uint8_t state) { if (dtr) { if (!furi_hal_vcp->connected) { furi_hal_vcp->connected = true; - furi_hal_vcp_on_cdc_rx(&ascii_soh, 1); // SOH + xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_soh, 1, &xHigherPriorityTaskWoken); // SOH + } } else { if (furi_hal_vcp->connected) { - furi_hal_vcp_on_cdc_rx(&ascii_eot, 1); // EOT + xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, &ascii_eot, 1, &xHigherPriorityTaskWoken); // EOT furi_hal_vcp->connected = false; } } osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -void furi_hal_vcp_on_cdc_rx(const uint8_t* buffer, size_t size) { +void furi_hal_vcp_on_cdc_rx(uint8_t if_num) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; - size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, buffer, size, &xHigherPriorityTaskWoken); - furi_check(ret == size); - - if (xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { - USBD_CDC_ReceivePacket(&hUsbDeviceFS); - } else { - furi_hal_vcp->rx_stream_full = true; + + if (if_num == 0) { + uint16_t max_len = xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream); + if (max_len > 0) { + if (max_len > APP_RX_DATA_SIZE) + max_len = APP_RX_DATA_SIZE; + int32_t size = furi_hal_cdc_receive(0, vcp_rx_buf, max_len); + + if (size > 0) { + size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, vcp_rx_buf, size, &xHigherPriorityTaskWoken); + furi_check(ret == size); + } + } else { + furi_hal_vcp->rx_stream_full = true; + }; } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -void furi_hal_vcp_on_cdc_tx_complete(size_t size) { - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); +void furi_hal_vcp_on_cdc_tx_complete(uint8_t if_num) { + if (if_num == 0) + osSemaphoreRelease(furi_hal_vcp->tx_semaphore); } diff --git a/firmware/targets/f7/furi-hal/furi-hal-vcp_i.h b/firmware/targets/f7/furi-hal/furi-hal-vcp_i.h index 05ddc6ad3..9c8ccd73c 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-vcp_i.h +++ b/firmware/targets/f7/furi-hal/furi-hal-vcp_i.h @@ -8,6 +8,6 @@ void furi_hal_vcp_on_usb_suspend(); void furi_hal_vcp_on_cdc_control_line(uint8_t state); -void furi_hal_vcp_on_cdc_rx(const uint8_t* buffer, size_t size); +void furi_hal_vcp_on_cdc_rx(uint8_t if_num); -void furi_hal_vcp_on_cdc_tx_complete(size_t size); +void furi_hal_vcp_on_cdc_tx_complete(uint8_t if_num); diff --git a/firmware/targets/f7/furi-hal/furi-hal-version.c b/firmware/targets/f7/furi-hal/furi-hal-version.c index b0c3c3504..5a98ab5ef 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-version.c +++ b/firmware/targets/f7/furi-hal/furi-hal-version.c @@ -8,10 +8,6 @@ #include "ble.h" #define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE -#define FURI_HAL_VERSION_NAME_LENGTH 8 -#define FURI_HAL_VERSION_ARRAY_NAME_LENGTH (FURI_HAL_VERSION_NAME_LENGTH + 1) -/** BLE symbol + "Flipper " + name */ -#define FURI_HAL_VERSION_DEVICE_NAME_LENGTH (1 + 8 + FURI_HAL_VERSION_ARRAY_NAME_LENGTH) #define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE /** OTP Versions enum */ diff --git a/firmware/targets/f7/furi-hal/furi-hal.c b/firmware/targets/f7/furi-hal/furi-hal.c index 2ec06dd46..64b29ba73 100644 --- a/firmware/targets/f7/furi-hal/furi-hal.c +++ b/firmware/targets/f7/furi-hal/furi-hal.c @@ -3,7 +3,6 @@ #include #include #include -#include #include void furi_hal_init() { @@ -35,7 +34,8 @@ void furi_hal_init() { // VCP + USB furi_hal_vcp_init(); - MX_USB_Device_Init(); + furi_hal_usb_init(); + furi_hal_usb_set_config(UsbModeVcpSingle); FURI_LOG_I("HAL", "USB OK"); furi_hal_i2c_init(); diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index fe9501499..d8ab0d5de 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -38,6 +38,7 @@ CFLAGS += \ CFLAGS += \ -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc \ -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc/Legacy \ + -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST \ -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Include \ -I$(CUBE_DIR)/Drivers/CMSIS/Include C_SOURCES += \ @@ -69,7 +70,6 @@ C_SOURCES += \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usb.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_utils.c # FreeRTOS @@ -116,17 +116,10 @@ C_SOURCES += \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/shci_tl_if.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci/shci.c -# USB glue +# USB stack CFLAGS += \ - -I$(TARGET_DIR)/usb-glue \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Inc \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc -C_SOURCES += \ - $(wildcard $(TARGET_DIR)/usb-glue/*.c) \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c + -DSTM32WB \ + -DUSB_PMASIZE=0x400 # Furi HAL FURI_HAL_OS_DEBUG ?= 0 diff --git a/firmware/targets/f7/usb-glue/usb_device.c b/firmware/targets/f7/usb-glue/usb_device.c deleted file mode 100644 index 84e9143d9..000000000 --- a/firmware/targets/f7/usb-glue/usb_device.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "usb_device.h" - -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" - -#include "usbd_def.h" -#include "usbd_core.h" -#include "usbd_desc.h" -#include "usbd_cdc.h" -#include "usbd_cdc_if.h" - -extern void Error_Handler(void); - -/* USB Device Core handle declaration. */ -USBD_HandleTypeDef hUsbDeviceFS; - -extern USBD_DescriptorsTypeDef CDC_Desc; - -/** Init USB device Library, add supported class and start the library */ -void MX_USB_Device_Init(void) { - /* Init Device Library, add supported class and start the library. */ - if (USBD_Init(&hUsbDeviceFS, &CDC_Desc, DEVICE_FS) != USBD_OK) { - Error_Handler(); - } - if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { - Error_Handler(); - } - if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { - Error_Handler(); - } - if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { - Error_Handler(); - } -} diff --git a/firmware/targets/f7/usb-glue/usb_device.h b/firmware/targets/f7/usb-glue/usb_device.h deleted file mode 100644 index 7d80e3480..000000000 --- a/firmware/targets/f7/usb-glue/usb_device.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef __cplusplus - extern "C" { -#endif - -void MX_USB_Device_Init(); - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f7/usb-glue/usbd_cdc_if.c b/firmware/targets/f7/usb-glue/usbd_cdc_if.c deleted file mode 100644 index 6b905c84f..000000000 --- a/firmware/targets/f7/usb-glue/usbd_cdc_if.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "usbd_cdc_if.h" -#include - -extern USBD_HandleTypeDef hUsbDeviceFS; - -static int8_t CDC_Init_FS(void); -static int8_t CDC_DeInit_FS(void); -static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); -static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len); -static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum); - -USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = -{ - CDC_Init_FS, - CDC_DeInit_FS, - CDC_Control_FS, - CDC_Receive_FS, - CDC_TransmitCplt_FS -}; - -uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; -uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; - -/** Initializes the CDC media low layer over the FS USB IP - * @retval USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Init_FS(void) { - /* Set Application Buffers */ - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); - USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); - return (USBD_OK); -} - -/** - * @brief DeInitializes the CDC media low layer - * @retval USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_DeInit_FS(void) { - return (USBD_OK); -} - -/** Manage the CDC 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 CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) { - if (cmd == CDC_SEND_ENCAPSULATED_COMMAND) { - } else if (cmd == CDC_GET_ENCAPSULATED_RESPONSE) { - } else if (cmd == CDC_SET_COMM_FEATURE) { - } else if (cmd == CDC_GET_COMM_FEATURE) { - } else if (cmd == CDC_CLEAR_COMM_FEATURE) { - } else if (cmd == CDC_SET_LINE_CODING) { - /*******************************************************************************/ - /* Line Coding Structure */ - /*-----------------------------------------------------------------------------*/ - /* Offset | Field | Size | Value | Description */ - /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ - /* 4 | bCharFormat | 1 | Number | Stop bits */ - /* 0 - 1 Stop bit */ - /* 1 - 1.5 Stop bits */ - /* 2 - 2 Stop bits */ - /* 5 | bParityType | 1 | Number | Parity */ - /* 0 - None */ - /* 1 - Odd */ - /* 2 - Even */ - /* 3 - Mark */ - /* 4 - Space */ - /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ - /*******************************************************************************/ - } else if (cmd == CDC_GET_LINE_CODING) { - } else if (cmd == CDC_SET_CONTROL_LINE_STATE) { - furi_hal_vcp_on_cdc_control_line(((USBD_SetupReqTypedef*)pbuf)->wValue); - } else if (cmd == CDC_SEND_BREAK) { - } else { - } - - return (USBD_OK); -} - -/** Data received over USB OUT endpoint are sent over CDC interface through this function. - * - * @note - * This function will issue a NAK packet on any OUT packet received on - * USB endpoint until exiting this function. If you exit this function - * before transfer is complete on CDC 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 CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { - if (*Len) { - furi_hal_vcp_on_cdc_rx(Buf, *Len); - } else { - USBD_CDC_ReceivePacket(&hUsbDeviceFS); - } - - return (USBD_OK); -} - -/** CDC_Transmit_FS Data to send over USB IN endpoint are sent over CDC interface - * through this function. - * @param Buf: Buffer of data to be sent - * @param Len: Number of data to be sent (in bytes) - * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY - */ -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) -{ - uint8_t result = USBD_OK; - - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; - if (hcdc->TxState != 0){ - return USBD_BUSY; - } - memcpy(UserTxBufferFS, Buf, Len); - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, Len); - result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); - - return result; -} - -/** CDC_TransmitCplt_FS Data transmited callback - * - * @note - * This function is IN transfer complete callback used to inform user that - * the submitted Data is successfully sent over USB. - * - * @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 CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum) { - uint8_t result = USBD_OK; - - furi_hal_vcp_on_cdc_tx_complete(*Len); - - return result; -} diff --git a/firmware/targets/f7/usb-glue/usbd_cdc_if.h b/firmware/targets/f7/usb-glue/usbd_cdc_if.h deleted file mode 100644 index fc0aefbe3..000000000 --- a/firmware/targets/f7/usb-glue/usbd_cdc_if.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_cdc.h" - -/* Define size for the receive and transmit buffer over CDC */ -/* It's up to user to redefine and/or remove those define */ -#define APP_RX_DATA_SIZE CDC_DATA_FS_MAX_PACKET_SIZE -#define APP_TX_DATA_SIZE CDC_DATA_FS_MAX_PACKET_SIZE - -/** CDC Interface callback. */ -extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; - -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f7/usb-glue/usbd_conf.c b/firmware/targets/f7/usb-glue/usbd_conf.c deleted file mode 100644 index cbc137e51..000000000 --- a/firmware/targets/f7/usb-glue/usbd_conf.c +++ /dev/null @@ -1,506 +0,0 @@ -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" - -#include - -#include "usbd_def.h" -#include "usbd_core.h" -#include "usbd_cdc.h" - -PCD_HandleTypeDef hpcd_USB_FS; -void Error_Handler(void); - -static USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status); - -static void SystemClockConfig_Resume(void); - -void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle) { - GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(pcdHandle->Instance==USB) { - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB GPIO Configuration - PA11 ------> USB_DM - PA12 ------> USB_DP - */ - 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_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF10_USB; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* Peripheral clock enable */ - __HAL_RCC_USB_CLK_ENABLE(); - - /* Peripheral interrupt init */ - HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(USB_LP_IRQn); - } -} - -void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) { - if(pcdHandle->Instance==USB) { - /* Peripheral clock disable */ - __HAL_RCC_USB_CLK_DISABLE(); - - /**USB GPIO Configuration - PA11 ------> USB_DM - PA12 ------> USB_DP - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); - - /* Peripheral interrupt Deinit*/ - HAL_NVIC_DisableIRQ(USB_LP_IRQn); - } -} - -/** Setup stage callback - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup); -} - -/** 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((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); -} - -/** 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((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); -} - -/** SOF callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Reset callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { - USBD_SpeedTypeDef speed = USBD_SPEED_FULL; - - if ( hpcd->Init.speed != PCD_SPEED_FULL) { - Error_Handler(); - } - - /* Set Speed. */ - USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed); - - /* Reset Device. */ - USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Suspend callback. - * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData); - - furi_hal_vcp_on_usb_suspend(); - - if (hpcd->Init.low_power_enable) { - /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ - SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } -} - -/** Resume callback. - * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) { - if (hpcd->Init.low_power_enable) { - /* Reset SLEEPDEEP bit of Cortex System Control Register. */ - SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - SystemClockConfig_Resume(); - } - - furi_hal_vcp_on_usb_resume(); - - USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData); -} - -/** ISOOUTIncomplete callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { - USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); -} - -/** ISOINIncomplete callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { - USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); -} - -/** Connect callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Disconnect callback. - * @param hpcd: PCD handle - * @retval None - */ -void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { - USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData); -} - -/** Initializes the low level portion of the device driver. - * @param pdev: Device handle - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) { - /* Init USB Ip. */ - hpcd_USB_FS.pData = pdev; - - /* Link the driver to the stack. */ - pdev->pData = &hpcd_USB_FS; - - /* Enable USB power on Pwrctrl CR2 register. */ - HAL_PWREx_EnableVddUSB(); - - hpcd_USB_FS.Instance = USB; - hpcd_USB_FS.Init.dev_endpoints = 8; - hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; - hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd_USB_FS.Init.Sof_enable = DISABLE; - hpcd_USB_FS.Init.low_power_enable = DISABLE; - hpcd_USB_FS.Init.lpm_enable = DISABLE; - hpcd_USB_FS.Init.battery_charging_enable = DISABLE; - - if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK) { - Error_Handler(); - } - - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); - - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xC0); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x110); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0x100); - - return USBD_OK; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_DeInit(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_Start(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_Stop(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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 = (PCD_HandleTypeDef*) 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; - } -} - -/** Assigns a USB address to the device. - * @param pdev: Device handle - * @param dev_addr: Device address - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) { - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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, uint32_t size) { - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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, uint32_t size) { - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** 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((PCD_HandleTypeDef*) pdev->pData, ep_addr); -} - -/** Send LPM message to user layer - * @param hpcd: PCD handle - * @param msg: LPM message - * @retval None - */ -void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) { - switch (msg) { - case PCD_LPM_L0_ACTIVE: - if (hpcd->Init.low_power_enable) { - SystemClockConfig_Resume(); - /* Reset SLEEPDEEP bit of Cortex System Control Register. */ - SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } - USBD_LL_Resume(hpcd->pData); - break; - - case PCD_LPM_L1_ACTIVE: - USBD_LL_Suspend(hpcd->pData); - - /* Enter in STOP mode. */ - if (hpcd->Init.low_power_enable) { - /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ - SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } - break; - } -} - -/** Delays routine for the USB Device Library. - * @param Delay: Delay in ms - * @retval None - */ -void USBD_LL_Delay(uint32_t Delay) { - HAL_Delay(Delay); -} - -/** Static single allocation. - * @param size: Size of allocated memory - * @retval None - */ -void *USBD_static_malloc(uint32_t size) { - static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */ - return mem; -} - -/** Dummy memory free - * @param p: Pointer to allocated memory address - * @retval None - */ -void USBD_static_free(void *p) { -} - -/** Configures system clock after wake-up from USB resume callBack: - * enable HSI, PLL and select PLL as system clock source. - * @retval None - */ -static void SystemClockConfig_Resume(void) { -} - -/** Retuns the USB status depending on the HAL status: - * @param hal_status: HAL status - * @retval USB status - */ -USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status) { - USBD_StatusTypeDef usb_status = USBD_OK; - - switch (hal_status) - { - case HAL_OK : - usb_status = USBD_OK; - break; - case HAL_ERROR : - usb_status = USBD_FAIL; - break; - case HAL_BUSY : - usb_status = USBD_BUSY; - break; - case HAL_TIMEOUT : - usb_status = USBD_FAIL; - break; - default : - usb_status = USBD_FAIL; - break; - } - return usb_status; -} diff --git a/firmware/targets/f7/usb-glue/usbd_conf.h b/firmware/targets/f7/usb-glue/usbd_conf.h deleted file mode 100644 index 9e2a86f21..000000000 --- a/firmware/targets/f7/usb-glue/usbd_conf.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include -#include -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#define USBD_MAX_NUM_INTERFACES 1U -#define USBD_MAX_NUM_CONFIGURATION 1U -#define USBD_MAX_STR_DESC_SIZ 512U -#define USBD_DEBUG_LEVEL 0U -#define USBD_LPM_ENABLED 0U -#define USBD_SELF_POWERED 0U - -/****************************************/ -/* #define for FS and HS identification */ -#define DEVICE_FS 0 - -/* Memory management macros */ - -/** Alias for memory allocation. */ -#define USBD_malloc (void *)USBD_static_malloc - -/** Alias for memory release. */ -#define USBD_free USBD_static_free - -/** Alias for memory set. */ -#define USBD_memset memset - -/** Alias for memory copy. */ -#define USBD_memcpy memcpy - -/** Alias for delay. */ -#define USBD_Delay HAL_Delay - -/* 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 - -void *USBD_static_malloc(uint32_t size); -void USBD_static_free(void *p); - - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f7/usb-glue/usbd_desc.c b/firmware/targets/f7/usb-glue/usbd_desc.c deleted file mode 100644 index 96cc2cda5..000000000 --- a/firmware/targets/f7/usb-glue/usbd_desc.c +++ /dev/null @@ -1,206 +0,0 @@ -#include "usbd_core.h" -#include "usbd_desc.h" -#include "usbd_conf.h" -#include "furi-hal-version.h" - -#define USBD_VID 1155 -#define USBD_LANGID_STRING 1033 -#define USBD_MANUFACTURER_STRING "Flipper Devices Inc." -#define USBD_PID 22336 -#define USBD_CONFIGURATION_STRING "CDC Config" -#define USBD_INTERFACE_STRING "CDC Interface" - -static void Get_SerialNum(void); -static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len); - -uint8_t* USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t* USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); - -USBD_DescriptorsTypeDef CDC_Desc = { - USBD_CDC_DeviceDescriptor, - USBD_CDC_LangIDStrDescriptor, - USBD_CDC_ManufacturerStrDescriptor, - USBD_CDC_ProductStrDescriptor, - USBD_CDC_SerialStrDescriptor, - USBD_CDC_ConfigStrDescriptor, - USBD_CDC_InterfaceStrDescriptor -}; - -/** USB standard device descriptor. */ -__ALIGN_BEGIN uint8_t USBD_CDC_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { - 0x12, /*bLength */ - USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ - 0x00, /*bcdUSB */ - 0x02, - 0x02, /*bDeviceClass*/ - 0x02, /*bDeviceSubClass*/ - 0x00, /*bDeviceProtocol*/ - USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ - LOBYTE(USBD_VID), /*idVendor*/ - HIBYTE(USBD_VID), /*idVendor*/ - LOBYTE(USBD_PID), /*idProduct*/ - HIBYTE(USBD_PID), /*idProduct*/ - 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 lang indentifier descriptor. */ -__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) -}; - -/* Internal string descriptor. */ -__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; - -__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = { - USB_SIZ_STRING_SERIAL, - USB_DESC_TYPE_STRING, -}; - -/** Return the device descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_CDC_DeviceDesc); - return USBD_CDC_DeviceDesc; -} - -/** Return the LangID string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = sizeof(USBD_LangIDDesc); - return USBD_LangIDDesc; -} - -/** Return the product string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString((uint8_t*)furi_hal_version_get_device_name_ptr(), USBD_StrDesc, length); - return USBD_StrDesc; -} - -/** Return the manufacturer string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); - return USBD_StrDesc; -} - -/** Return 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_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - UNUSED(speed); - *length = USB_SIZ_STRING_SERIAL; - - /* Update the serial number string descriptor with the data from the unique - * ID */ - if(furi_hal_version_get_name_ptr()){ - char buffer[14] = "flip_"; - strncat(buffer, furi_hal_version_get_name_ptr(), 8); - USBD_GetString((uint8_t*) buffer, USBD_StringSerial, length); - } else { - Get_SerialNum(); - } - - return (uint8_t *) USBD_StringSerial; -} - -/** Return the configuration string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - if(speed == USBD_SPEED_HIGH) { - USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); - } else { - USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); - } - return USBD_StrDesc; -} - -/** Return the interface string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - if(speed == 0) { - USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); - } else { - USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); - } - return USBD_StrDesc; -} - -/** Create the serial number string descriptor - * @param None - * @retval None - */ -static void Get_SerialNum(void) { - uint32_t deviceserial0, deviceserial1, deviceserial2; - - deviceserial0 = *(uint32_t *) DEVICE_ID1; - deviceserial1 = *(uint32_t *) DEVICE_ID2; - deviceserial2 = *(uint32_t *) DEVICE_ID3; - - deviceserial0 += deviceserial2; - - if (deviceserial0 != 0) { - IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8); - IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); - } -} - -/** Convert Hex 32Bits value into char - * @param value: value to convert - * @param pbuf: pointer to the buffer - * @param len: buffer length - * @retval None - */ -static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len) { - uint8_t idx = 0; - - for (idx = 0; idx < len; idx++) { - if (((value >> 28)) < 0xA) { - pbuf[2 * idx] = (value >> 28) + '0'; - } else { - pbuf[2 * idx] = (value >> 28) + 'A' - 10; - } - - value = value << 4; - - pbuf[2 * idx + 1] = 0; - } -} diff --git a/firmware/targets/f7/usb-glue/usbd_desc.h b/firmware/targets/f7/usb-glue/usbd_desc.h deleted file mode 100644 index 795b33e4a..000000000 --- a/firmware/targets/f7/usb-glue/usbd_desc.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "usbd_def.h" - -#define DEVICE_ID1 (UID_BASE) -#define DEVICE_ID2 (UID_BASE + 0x4) -#define DEVICE_ID3 (UID_BASE + 0x8) - -#define USB_SIZ_STRING_SERIAL 0x1E - -extern USBD_DescriptorsTypeDef CDC_Desc; - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/furi-hal-include/furi-hal-usb.h b/firmware/targets/furi-hal-include/furi-hal-usb.h new file mode 100644 index 000000000..8e70a5976 --- /dev/null +++ b/firmware/targets/furi-hal-include/furi-hal-usb.h @@ -0,0 +1,21 @@ +#pragma once + +#include "usb.h" + +typedef enum { + UsbModeNone, + UsbModeVcpSingle, + UsbModeVcpDual, + UsbModeHid, + UsbModeU2F, + + UsbModesNum, +} UsbMode; + +void furi_hal_usb_init(); + +void furi_hal_usb_set_config(UsbMode mode); + +void furi_hal_usb_disable(); + +void furi_hal_usb_enable(); diff --git a/firmware/targets/furi-hal-include/furi-hal-version.h b/firmware/targets/furi-hal-include/furi-hal-version.h index 12b2e63c7..ac28188ef 100644 --- a/firmware/targets/furi-hal-include/furi-hal-version.h +++ b/firmware/targets/furi-hal-include/furi-hal-version.h @@ -14,6 +14,11 @@ extern "C" { #endif +#define FURI_HAL_VERSION_NAME_LENGTH 8 +#define FURI_HAL_VERSION_ARRAY_NAME_LENGTH (FURI_HAL_VERSION_NAME_LENGTH + 1) +/** BLE symbol + "Flipper " + name */ +#define FURI_HAL_VERSION_DEVICE_NAME_LENGTH (1 + 8 + FURI_HAL_VERSION_ARRAY_NAME_LENGTH) + /** Device Colors */ typedef enum { FuriHalVersionColorUnknown=0x00, diff --git a/firmware/targets/furi-hal-include/furi-hal.h b/firmware/targets/furi-hal-include/furi-hal.h index 1318c6146..7f344f871 100644 --- a/firmware/targets/furi-hal-include/furi-hal.h +++ b/firmware/targets/furi-hal-include/furi-hal.h @@ -33,6 +33,7 @@ template struct STOP_EXTERNING_ME {}; #include "furi-hal-ibutton.h" #include "furi-hal-rfid.h" #include "furi-hal-nfc.h" +#include "furi-hal-usb.h" /** Init furi-hal */ void furi_hal_init(); diff --git a/lib/lib.mk b/lib/lib.mk index 52061e42d..4b4b6b8e3 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -108,3 +108,7 @@ CPP_SOURCES += $(wildcard $(LIB_DIR)/app-scened-template/*/*.cpp) # Toolbox C_SOURCES += $(wildcard $(LIB_DIR)/toolbox/*.c) + +# USB Stack +CFLAGS += -I$(LIB_DIR)/libusb_stm32/inc +C_SOURCES += $(wildcard $(LIB_DIR)/libusb_stm32/src/*.c) diff --git a/lib/libusb_stm32 b/lib/libusb_stm32 new file mode 160000 index 000000000..fe3890e10 --- /dev/null +++ b/lib/libusb_stm32 @@ -0,0 +1 @@ +Subproject commit fe3890e10e35a837184cb05f835ef6ab14bfd04f