Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolay Minaylov <nm29719@gmail.com>2021-10-06 12:24:09 +0300
committerGitHub <noreply@github.com>2021-10-06 12:24:09 +0300
commite0c1928fde94387f0fc819eda16004c68ce164a6 (patch)
treecd8dbf3e37d3fffa5d06c3f2108a9914004b4620 /firmware
parent42e553bad525a0ae159a4c4814267d5cca3ae5d8 (diff)
[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 <n.minaylov@flipperdevices.com> Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Diffstat (limited to 'firmware')
-rw-r--r--firmware/targets/f6/Inc/stm32.h52
-rw-r--r--firmware/targets/f6/Src/stm32wbxx_it.c5
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c555
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-usb-cdc_i.h7
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-usb-hid.c264
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-usb.c164
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-usb_i.h28
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-vcp.c63
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-vcp_i.h4
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-version.c4
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal.c4
-rw-r--r--firmware/targets/f6/target.mk15
-rw-r--r--firmware/targets/f6/usb-glue/usb_device.c34
-rw-r--r--firmware/targets/f6/usb-glue/usb_device.h11
-rw-r--r--firmware/targets/f6/usb-glue/usbd_cdc_if.c142
-rw-r--r--firmware/targets/f6/usb-glue/usbd_cdc_if.h22
-rw-r--r--firmware/targets/f6/usb-glue/usbd_conf.c506
-rw-r--r--firmware/targets/f6/usb-glue/usbd_conf.h73
-rw-r--r--firmware/targets/f6/usb-glue/usbd_desc.c206
-rw-r--r--firmware/targets/f6/usb-glue/usbd_desc.h19
-rw-r--r--firmware/targets/f7/Inc/stm32.h52
-rw-r--r--firmware/targets/f7/Src/stm32wbxx_it.c5
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c555
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-usb-cdc_i.h7
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-usb-hid.c264
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-usb.c164
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-usb_i.h28
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-vcp.c63
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-vcp_i.h4
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-version.c4
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal.c4
-rw-r--r--firmware/targets/f7/target.mk15
-rw-r--r--firmware/targets/f7/usb-glue/usb_device.c34
-rw-r--r--firmware/targets/f7/usb-glue/usb_device.h11
-rw-r--r--firmware/targets/f7/usb-glue/usbd_cdc_if.c142
-rw-r--r--firmware/targets/f7/usb-glue/usbd_cdc_if.h22
-rw-r--r--firmware/targets/f7/usb-glue/usbd_conf.c506
-rw-r--r--firmware/targets/f7/usb-glue/usbd_conf.h73
-rw-r--r--firmware/targets/f7/usb-glue/usbd_desc.c206
-rw-r--r--firmware/targets/f7/usb-glue/usbd_desc.h19
-rw-r--r--firmware/targets/furi-hal-include/furi-hal-usb.h21
-rw-r--r--firmware/targets/furi-hal-include/furi-hal-version.h5
-rw-r--r--firmware/targets/furi-hal-include/furi-hal.h1
43 files changed, 2263 insertions, 2120 deletions
diff --git a/firmware/targets/f6/Inc/stm32.h b/firmware/targets/f6/Inc/stm32.h
new file mode 100644
index 00000000..45344fe3
--- /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 01fbdc1d..6f70fb5e 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 00000000..09efbec3
--- /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 <furi.h>
+
+#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 00000000..636b3c04
--- /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 00000000..38423610
--- /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 <furi.h>
+
+#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 00000000..fc5add2e
--- /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 <furi.h>
+
+#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 00000000..b329c51f
--- /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 88de32b5..e276c4a3 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 <furi-hal-vcp_i.h>
+#include <furi-hal-usb-cdc_i.h>
#include <furi.h>
-#include <usbd_cdc_if.h>
#include <stream_buffer.h>
-#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 05ddc6ad..9c8ccd73 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 90a3d6c2..93166b16 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 2ec06dd4..64b29ba7 100644
--- a/firmware/targets/f6/furi-hal/furi-hal.c
+++ b/firmware/targets/f6/furi-hal/furi-hal.c
@@ -3,7 +3,6 @@
#include <comp.h>
#include <rtc.h>
#include <tim.h>
-#include <usb_device.h>
#include <gpio.h>
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 fe950149..d8ab0d5d 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 84e9143d..00000000
--- 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 7d80e348..00000000
--- 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 6b905c84..00000000
--- a/firmware/targets/f6/usb-glue/usbd_cdc_if.c
+++ /dev/null
@@ -1,142 +0,0 @@
-#include "usbd_cdc_if.h"
-#include <furi-hal-vcp_i.h>
-
-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 fc0aefbe..00000000
--- 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 cbc137e5..00000000
--- a/firmware/targets/f6/usb-glue/usbd_conf.c
+++ /dev/null
@@ -1,506 +0,0 @@
-#include "stm32wbxx.h"
-#include "stm32wbxx_hal.h"
-
-#include <furi-hal-vcp_i.h>
-
-#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 9e2a86f2..00000000
--- a/firmware/targets/f6/usb-glue/usbd_conf.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#pragma once
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#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 96cc2cda..00000000
--- 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 795b33e4..00000000
--- 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 00000000..45344fe3
--- /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 01fbdc1d..6f70fb5e 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 00000000..09efbec3
--- /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 <furi.h>
+
+#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 00000000..636b3c04
--- /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 00000000..38423610
--- /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 <furi.h>
+
+#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 00000000..fc5add2e
--- /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 <furi.h>
+
+#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 00000000..b329c51f
--- /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 88de32b5..e276c4a3 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 <furi-hal-vcp_i.h>
+#include <furi-hal-usb-cdc_i.h>
#include <furi.h>
-#include <usbd_cdc_if.h>
#include <stream_buffer.h>
-#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 05ddc6ad..9c8ccd73 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 b0c3c350..5a98ab5e 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 2ec06dd4..64b29ba7 100644
--- a/firmware/targets/f7/furi-hal/furi-hal.c
+++ b/firmware/targets/f7/furi-hal/furi-hal.c
@@ -3,7 +3,6 @@
#include <comp.h>
#include <rtc.h>
#include <tim.h>
-#include <usb_device.h>
#include <gpio.h>
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 fe950149..d8ab0d5d 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 84e9143d..00000000
--- 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 7d80e348..00000000
--- 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 6b905c84..00000000
--- a/firmware/targets/f7/usb-glue/usbd_cdc_if.c
+++ /dev/null
@@ -1,142 +0,0 @@
-#include "usbd_cdc_if.h"
-#include <furi-hal-vcp_i.h>
-
-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 fc0aefbe..00000000
--- 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 cbc137e5..00000000
--- a/firmware/targets/f7/usb-glue/usbd_conf.c
+++ /dev/null
@@ -1,506 +0,0 @@
-#include "stm32wbxx.h"
-#include "stm32wbxx_hal.h"
-
-#include <furi-hal-vcp_i.h>
-
-#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 9e2a86f2..00000000
--- a/firmware/targets/f7/usb-glue/usbd_conf.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#pragma once
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#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 96cc2cda..00000000
--- 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 795b33e4..00000000
--- 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 00000000..8e70a597
--- /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 12b2e63c..ac28188e 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 1318c614..7f344f87 100644
--- a/firmware/targets/furi-hal-include/furi-hal.h
+++ b/firmware/targets/furi-hal-include/furi-hal.h
@@ -33,6 +33,7 @@ template <unsigned int N> 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();