| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985 |
- #include <furi.h>
- #include <usb.h>
- #include <usb_std.h>
- #include <usb_hid.h>
- #include <usb_cdc.h>
- #include <furi_hal_console.h>
- #include "dap_v2_usb.h"
- // #define DAP_USB_LOG
- #define HID_EP_IN 0x80
- #define HID_EP_OUT 0x00
- #define DAP_HID_EP_SEND 1
- #define DAP_HID_EP_RECV 2
- #define DAP_HID_EP_BULK_RECV 3
- #define DAP_HID_EP_BULK_SEND 4
- #define DAP_CDC_EP_COMM 5
- #define DAP_CDC_EP_SEND 6
- #define DAP_CDC_EP_RECV 7
- #define DAP_HID_EP_IN (HID_EP_IN | DAP_HID_EP_SEND)
- #define DAP_HID_EP_OUT (HID_EP_OUT | DAP_HID_EP_RECV)
- #define DAP_HID_EP_BULK_IN (HID_EP_IN | DAP_HID_EP_BULK_SEND)
- #define DAP_HID_EP_BULK_OUT (HID_EP_OUT | DAP_HID_EP_BULK_RECV)
- #define DAP_HID_EP_SIZE 64
- #define DAP_CDC_COMM_EP_SIZE 8
- #define DAP_CDC_EP_SIZE 64
- #define DAP_BULK_INTERVAL 0
- #define DAP_HID_INTERVAL 1
- #define DAP_CDC_INTERVAL 0
- #define DAP_CDC_COMM_INTERVAL 1
- #define DAP_HID_VID 0x0483
- #define DAP_HID_PID 0x5740
- #define DAP_USB_EP0_SIZE 8
- #define EP_CFG_DECONFIGURE 0
- #define EP_CFG_CONFIGURE 1
- enum {
- USB_INTF_HID,
- USB_INTF_BULK,
- USB_INTF_CDC_COMM,
- USB_INTF_CDC_DATA,
- USB_INTF_COUNT,
- };
- enum {
- USB_STR_ZERO,
- USB_STR_MANUFACTURER,
- USB_STR_PRODUCT,
- USB_STR_SERIAL_NUMBER,
- USB_STR_CMSIS_DAP_V1,
- USB_STR_CMSIS_DAP_V2,
- USB_STR_COM_PORT,
- USB_STR_COUNT,
- };
- // static const char* usb_str[] = {
- // [USB_STR_MANUFACTURER] = "Flipper Devices Inc.",
- // [USB_STR_PRODUCT] = "Combined VCP and CMSIS-DAP Adapter",
- // [USB_STR_COM_PORT] = "Virtual COM-Port",
- // [USB_STR_CMSIS_DAP_V1] = "CMSIS-DAP v1 Adapter",
- // [USB_STR_CMSIS_DAP_V2] = "CMSIS-DAP v2 Adapter",
- // [USB_STR_SERIAL_NUMBER] = "01234567890ABCDEF",
- // };
- static const struct usb_string_descriptor dev_manuf_descr =
- USB_STRING_DESC("Flipper Devices Inc.");
- static const struct usb_string_descriptor dev_prod_descr =
- USB_STRING_DESC("Combined VCP and CMSIS-DAP Adapter");
- static struct usb_string_descriptor* dev_serial_descr = NULL;
- static const struct usb_string_descriptor dev_dap_v1_descr =
- USB_STRING_DESC("CMSIS-DAP v1 Adapter");
- static const struct usb_string_descriptor dev_dap_v2_descr =
- USB_STRING_DESC("CMSIS-DAP v2 Adapter");
- static const struct usb_string_descriptor dev_com_descr = USB_STRING_DESC("Virtual COM-Port");
- struct HidConfigDescriptor {
- struct usb_config_descriptor configuration;
- // CMSIS-DAP v1
- struct usb_interface_descriptor hid_interface;
- struct usb_hid_descriptor hid;
- struct usb_endpoint_descriptor hid_ep_in;
- struct usb_endpoint_descriptor hid_ep_out;
- // CMSIS-DAP v2
- struct usb_interface_descriptor bulk_interface;
- struct usb_endpoint_descriptor bulk_ep_out;
- struct usb_endpoint_descriptor bulk_ep_in;
- // CDC
- struct usb_iad_descriptor iad;
- struct usb_interface_descriptor interface_comm;
- struct usb_cdc_header_desc cdc_header;
- struct usb_cdc_call_mgmt_desc cdc_acm;
- struct usb_cdc_acm_desc cdc_call_mgmt;
- struct usb_cdc_union_desc cdc_union;
- struct usb_endpoint_descriptor ep_comm;
- struct usb_interface_descriptor interface_data;
- struct usb_endpoint_descriptor ep_in;
- struct usb_endpoint_descriptor ep_out;
- } __attribute__((packed));
- static const struct usb_device_descriptor hid_device_desc = {
- .bLength = sizeof(struct usb_device_descriptor),
- .bDescriptorType = USB_DTYPE_DEVICE,
- .bcdUSB = VERSION_BCD(2, 1, 0),
- .bDeviceClass = USB_CLASS_MISC,
- .bDeviceSubClass = USB_SUBCLASS_IAD,
- .bDeviceProtocol = USB_PROTO_IAD,
- .bMaxPacketSize0 = DAP_USB_EP0_SIZE,
- .idVendor = DAP_HID_VID,
- .idProduct = DAP_HID_PID,
- .bcdDevice = VERSION_BCD(1, 0, 0),
- .iManufacturer = USB_STR_MANUFACTURER,
- .iProduct = USB_STR_PRODUCT,
- .iSerialNumber = USB_STR_SERIAL_NUMBER,
- .bNumConfigurations = 1,
- };
- static const uint8_t hid_report_desc[] = {
- 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
- 0x09, 0x00, // Usage (Undefined)
- 0xa1, 0x01, // Collection (Application)
- 0x15, 0x00, // Logical Minimum (0)
- 0x26, 0xff, 0x00, // Logical Maximum (255)
- 0x75, 0x08, // Report Size (8)
- 0x95, 0x40, // Report Count (64)
- 0x09, 0x00, // Usage (Undefined)
- 0x81, 0x82, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0x75, 0x08, // Report Size (8)
- 0x95, 0x40, // Report Count (64)
- 0x09, 0x00, // Usage (Undefined)
- 0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
- 0xc0, // End Collection
- };
- static const struct HidConfigDescriptor hid_cfg_desc = {
- .configuration =
- {
- .bLength = sizeof(struct usb_config_descriptor),
- .bDescriptorType = USB_DTYPE_CONFIGURATION,
- .wTotalLength = sizeof(struct HidConfigDescriptor),
- .bNumInterfaces = USB_INTF_COUNT,
- .bConfigurationValue = 1,
- .iConfiguration = NO_DESCRIPTOR,
- .bmAttributes = USB_CFG_ATTR_RESERVED,
- .bMaxPower = USB_CFG_POWER_MA(500),
- },
- // CMSIS-DAP v1
- .hid_interface =
- {
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DTYPE_INTERFACE,
- .bInterfaceNumber = USB_INTF_HID,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_HID,
- .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
- .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
- .iInterface = USB_STR_CMSIS_DAP_V1,
- },
- .hid =
- {
- .bLength = sizeof(struct usb_hid_descriptor),
- .bDescriptorType = USB_DTYPE_HID,
- .bcdHID = VERSION_BCD(1, 1, 1),
- .bCountryCode = USB_HID_COUNTRY_NONE,
- .bNumDescriptors = 1,
- .bDescriptorType0 = USB_DTYPE_HID_REPORT,
- .wDescriptorLength0 = sizeof(hid_report_desc),
- },
- .hid_ep_in =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = DAP_HID_EP_IN,
- .bmAttributes = USB_EPTYPE_INTERRUPT,
- .wMaxPacketSize = DAP_HID_EP_SIZE,
- .bInterval = DAP_HID_INTERVAL,
- },
- .hid_ep_out =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = DAP_HID_EP_OUT,
- .bmAttributes = USB_EPTYPE_INTERRUPT,
- .wMaxPacketSize = DAP_HID_EP_SIZE,
- .bInterval = DAP_HID_INTERVAL,
- },
- // CMSIS-DAP v2
- .bulk_interface =
- {
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DTYPE_INTERFACE,
- .bInterfaceNumber = USB_INTF_BULK,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_VENDOR,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = USB_STR_CMSIS_DAP_V2,
- },
- .bulk_ep_out =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = DAP_HID_EP_BULK_OUT,
- .bmAttributes = USB_EPTYPE_BULK,
- .wMaxPacketSize = DAP_HID_EP_SIZE,
- .bInterval = DAP_BULK_INTERVAL,
- },
- .bulk_ep_in =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = DAP_HID_EP_BULK_IN,
- .bmAttributes = USB_EPTYPE_BULK,
- .wMaxPacketSize = DAP_HID_EP_SIZE,
- .bInterval = DAP_BULK_INTERVAL,
- },
- // CDC
- .iad =
- {
- .bLength = sizeof(struct usb_iad_descriptor),
- .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
- .bFirstInterface = USB_INTF_CDC_COMM,
- .bInterfaceCount = 2,
- .bFunctionClass = USB_CLASS_CDC,
- .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
- .bFunctionProtocol = USB_PROTO_NONE,
- .iFunction = USB_STR_COM_PORT,
- },
- .interface_comm =
- {
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DTYPE_INTERFACE,
- .bInterfaceNumber = USB_INTF_CDC_COMM,
- .bAlternateSetting = 0,
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_CDC,
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
- .bInterfaceProtocol = USB_PROTO_NONE,
- .iInterface = 0,
- },
- .cdc_header =
- {
- .bFunctionLength = sizeof(struct usb_cdc_header_desc),
- .bDescriptorType = USB_DTYPE_CS_INTERFACE,
- .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
- .bcdCDC = VERSION_BCD(1, 1, 0),
- },
- .cdc_acm =
- {
- .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
- .bDescriptorType = USB_DTYPE_CS_INTERFACE,
- .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
- // .bmCapabilities = USB_CDC_CAP_LINE | USB_CDC_CAP_BRK,
- .bmCapabilities = 0,
- },
- .cdc_call_mgmt =
- {
- .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
- .bDescriptorType = USB_DTYPE_CS_INTERFACE,
- .bDescriptorSubType = USB_DTYPE_CDC_ACM,
- .bmCapabilities = USB_CDC_CALL_MGMT_CAP_DATA_INTF,
- // .bDataInterface = USB_INTF_CDC_DATA,
- },
- .cdc_union =
- {
- .bFunctionLength = sizeof(struct usb_cdc_union_desc),
- .bDescriptorType = USB_DTYPE_CS_INTERFACE,
- .bDescriptorSubType = USB_DTYPE_CDC_UNION,
- .bMasterInterface0 = USB_INTF_CDC_COMM,
- .bSlaveInterface0 = USB_INTF_CDC_DATA,
- },
- .ep_comm =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = HID_EP_IN | DAP_CDC_EP_COMM,
- .bmAttributes = USB_EPTYPE_INTERRUPT,
- .wMaxPacketSize = DAP_CDC_COMM_EP_SIZE,
- .bInterval = DAP_CDC_COMM_INTERVAL,
- },
- .interface_data =
- {
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DTYPE_INTERFACE,
- .bInterfaceNumber = USB_INTF_CDC_DATA,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = USB_SUBCLASS_NONE,
- .bInterfaceProtocol = USB_PROTO_NONE,
- .iInterface = NO_DESCRIPTOR,
- },
- .ep_in =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = HID_EP_IN | DAP_CDC_EP_SEND,
- .bmAttributes = USB_EPTYPE_BULK,
- .wMaxPacketSize = DAP_CDC_EP_SIZE,
- .bInterval = DAP_CDC_INTERVAL,
- },
- .ep_out =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = HID_EP_OUT | DAP_CDC_EP_RECV,
- .bmAttributes = USB_EPTYPE_BULK,
- .wMaxPacketSize = DAP_CDC_EP_SIZE,
- .bInterval = DAP_CDC_INTERVAL,
- },
- };
- // WinUSB
- #include "usb_winusb.h"
- typedef struct USB_PACK {
- usb_binary_object_store_descriptor_t bos;
- usb_winusb_capability_descriptor_t winusb;
- } usb_bos_hierarchy_t;
- typedef struct USB_PACK {
- usb_winusb_subset_header_function_t header;
- usb_winusb_feature_compatble_id_t comp_id;
- usb_winusb_feature_reg_property_guids_t property;
- } usb_msos_descriptor_subset_t;
- typedef struct USB_PACK {
- usb_winusb_set_header_descriptor_t header;
- usb_msos_descriptor_subset_t subset;
- } usb_msos_descriptor_set_t;
- #define USB_DTYPE_BINARY_OBJECT_STORE 15
- #define USB_DTYPE_DEVICE_CAPABILITY_DESCRIPTOR 16
- #define USB_DC_TYPE_PLATFORM 5
- const usb_bos_hierarchy_t usb_bos_hierarchy = {
- .bos =
- {
- .bLength = sizeof(usb_binary_object_store_descriptor_t),
- .bDescriptorType = USB_DTYPE_BINARY_OBJECT_STORE,
- .wTotalLength = sizeof(usb_bos_hierarchy_t),
- .bNumDeviceCaps = 1,
- },
- .winusb =
- {
- .bLength = sizeof(usb_winusb_capability_descriptor_t),
- .bDescriptorType = USB_DTYPE_DEVICE_CAPABILITY_DESCRIPTOR,
- .bDevCapabilityType = USB_DC_TYPE_PLATFORM,
- .bReserved = 0,
- .PlatformCapabilityUUID = USB_WINUSB_PLATFORM_CAPABILITY_ID,
- .dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION,
- .wMSOSDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t),
- .bMS_VendorCode = USB_WINUSB_VENDOR_CODE,
- .bAltEnumCode = 0,
- },
- };
- const usb_msos_descriptor_set_t usb_msos_descriptor_set = {
- .header =
- {
- .wLength = sizeof(usb_winusb_set_header_descriptor_t),
- .wDescriptorType = USB_WINUSB_SET_HEADER_DESCRIPTOR,
- .dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION,
- .wDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t),
- },
- .subset =
- {
- .header =
- {
- .wLength = sizeof(usb_winusb_subset_header_function_t),
- .wDescriptorType = USB_WINUSB_SUBSET_HEADER_FUNCTION,
- .bFirstInterface = USB_INTF_BULK,
- .bReserved = 0,
- .wSubsetLength = sizeof(usb_msos_descriptor_subset_t),
- },
- .comp_id =
- {
- .wLength = sizeof(usb_winusb_feature_compatble_id_t),
- .wDescriptorType = USB_WINUSB_FEATURE_COMPATBLE_ID,
- .CompatibleID = "WINUSB\0\0",
- .SubCompatibleID = {0},
- },
- .property =
- {
- .wLength = sizeof(usb_winusb_feature_reg_property_guids_t),
- .wDescriptorType = USB_WINUSB_FEATURE_REG_PROPERTY,
- .wPropertyDataType = USB_WINUSB_PROPERTY_DATA_TYPE_MULTI_SZ,
- .wPropertyNameLength =
- sizeof(usb_msos_descriptor_set.subset.property.PropertyName),
- .PropertyName = {'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, 'I', 0,
- 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0,
- 'e', 0, 'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0},
- .wPropertyDataLength =
- sizeof(usb_msos_descriptor_set.subset.property.PropertyData),
- .PropertyData = {'{', 0, 'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0,
- 'A', 0, 'D', 0, '-', 0, '2', 0, '9', 0, '3', 0, 'B', 0,
- '-', 0, '4', 0, '6', 0, '6', 0, '3', 0, '-', 0, 'A', 0,
- 'A', 0, '3', 0, '6', 0, '-', 0, '1', 0, 'A', 0, 'A', 0,
- 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0,
- '7', 0, '6', 0, '}', 0, 0, 0, 0, 0},
- },
- },
- };
- typedef struct {
- FuriSemaphore* semaphore_v1;
- FuriSemaphore* semaphore_v2;
- FuriSemaphore* semaphore_cdc;
- bool connected;
- usbd_device* usb_dev;
- DapStateCallback state_callback;
- DapRxCallback rx_callback_v1;
- DapRxCallback rx_callback_v2;
- DapRxCallback rx_callback_cdc;
- DapRxCallback tx_complete_cdc;
- DapCDCControlLineCallback control_line_callback_cdc;
- DapCDCConfigCallback config_callback_cdc;
- void* context;
- void* context_cdc;
- } DAPState;
- static DAPState dap_state = {
- .semaphore_v1 = NULL,
- .semaphore_v2 = NULL,
- .semaphore_cdc = NULL,
- .connected = false,
- .usb_dev = NULL,
- .state_callback = NULL,
- .rx_callback_v1 = NULL,
- .rx_callback_v2 = NULL,
- .rx_callback_cdc = NULL,
- .control_line_callback_cdc = NULL,
- .config_callback_cdc = NULL,
- .context = NULL,
- .context_cdc = NULL,
- };
- static struct usb_cdc_line_coding cdc_config = {0};
- static uint8_t cdc_ctrl_line_state = 0;
- #ifdef DAP_USB_LOG
- void furi_console_log_printf(const char* format, ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
- void furi_console_log_printf(const char* format, ...) {
- char buffer[256];
- va_list args;
- va_start(args, format);
- vsnprintf(buffer, sizeof(buffer), format, args);
- va_end(args);
- furi_hal_console_puts(buffer);
- furi_hal_console_puts("\r\n");
- UNUSED(format);
- }
- #else
- #define furi_console_log_printf(...)
- #endif
- int32_t dap_v1_usb_tx(uint8_t* buffer, uint8_t size) {
- if((dap_state.semaphore_v1 == NULL) || (dap_state.connected == false)) return 0;
- furi_check(furi_semaphore_acquire(dap_state.semaphore_v1, FuriWaitForever) == FuriStatusOk);
- if(dap_state.connected) {
- int32_t len = usbd_ep_write(dap_state.usb_dev, DAP_HID_EP_IN, buffer, size);
- furi_console_log_printf("v1 tx %ld", len);
- return len;
- } else {
- return 0;
- }
- }
- int32_t dap_v2_usb_tx(uint8_t* buffer, uint8_t size) {
- if((dap_state.semaphore_v2 == NULL) || (dap_state.connected == false)) return 0;
- furi_check(furi_semaphore_acquire(dap_state.semaphore_v2, FuriWaitForever) == FuriStatusOk);
- if(dap_state.connected) {
- int32_t len = usbd_ep_write(dap_state.usb_dev, DAP_HID_EP_BULK_IN, buffer, size);
- furi_console_log_printf("v2 tx %ld", len);
- return len;
- } else {
- return 0;
- }
- }
- int32_t dap_cdc_usb_tx(uint8_t* buffer, uint8_t size) {
- if((dap_state.semaphore_cdc == NULL) || (dap_state.connected == false)) return 0;
- if(furi_semaphore_acquire(dap_state.semaphore_cdc, 100) == FuriStatusOk) {
- if(dap_state.connected) {
- int32_t len =
- usbd_ep_write(dap_state.usb_dev, HID_EP_IN | DAP_CDC_EP_SEND, buffer, size);
- furi_console_log_printf("cdc tx %ld", len);
- return len;
- }
- }
- return 0;
- }
- void dap_v1_usb_set_rx_callback(DapRxCallback callback) {
- dap_state.rx_callback_v1 = callback;
- }
- void dap_v2_usb_set_rx_callback(DapRxCallback callback) {
- dap_state.rx_callback_v2 = callback;
- }
- void dap_cdc_usb_set_rx_callback(DapRxCallback callback) {
- dap_state.rx_callback_cdc = callback;
- }
- void dap_cdc_usb_set_tx_complete_callback(DapRxCallback callback) {
- dap_state.tx_complete_cdc = callback;
- }
- void dap_cdc_usb_set_control_line_callback(DapCDCControlLineCallback callback) {
- dap_state.control_line_callback_cdc = callback;
- }
- void dap_cdc_usb_set_config_callback(DapCDCConfigCallback callback) {
- dap_state.config_callback_cdc = callback;
- }
- void dap_cdc_usb_set_context(void* context) {
- dap_state.context_cdc = context;
- }
- void dap_common_usb_set_context(void* context) {
- dap_state.context = context;
- }
- void dap_common_usb_set_state_callback(DapStateCallback callback) {
- dap_state.state_callback = callback;
- }
- static void* dap_usb_alloc_string_descr(const char* str) {
- furi_assert(str);
- size_t len = strlen(str);
- size_t wlen = (len + 1) * sizeof(uint16_t);
- struct usb_string_descriptor* dev_str_desc = malloc(wlen);
- dev_str_desc->bLength = wlen;
- dev_str_desc->bDescriptorType = USB_DTYPE_STRING;
- for(size_t i = 0; i < len; i++) {
- dev_str_desc->wString[i] = str[i];
- }
- return dev_str_desc;
- }
- void dap_common_usb_alloc_name(const char* name) {
- dev_serial_descr = dap_usb_alloc_string_descr(name);
- }
- void dap_common_usb_free_name() {
- free(dev_serial_descr);
- }
- static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
- 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);
- FuriHalUsbInterface dap_v2_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,
- .cfg_descr = (void*)&hid_cfg_desc,
- };
- static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
- UNUSED(intf);
- UNUSED(ctx);
- dap_v2_usb_hid.str_manuf_descr = (void*)&dev_manuf_descr;
- dap_v2_usb_hid.str_prod_descr = (void*)&dev_prod_descr;
- dap_v2_usb_hid.str_serial_descr = (void*)dev_serial_descr;
- dap_state.usb_dev = dev;
- if(dap_state.semaphore_v1 == NULL) dap_state.semaphore_v1 = furi_semaphore_alloc(1, 1);
- if(dap_state.semaphore_v2 == NULL) dap_state.semaphore_v2 = furi_semaphore_alloc(1, 1);
- if(dap_state.semaphore_cdc == NULL) dap_state.semaphore_cdc = furi_semaphore_alloc(1, 1);
- usbd_reg_config(dev, hid_ep_config);
- usbd_reg_control(dev, hid_control);
- usbd_connect(dev, true);
- }
- static void hid_deinit(usbd_device* dev) {
- dap_state.usb_dev = NULL;
- furi_semaphore_free(dap_state.semaphore_v1);
- furi_semaphore_free(dap_state.semaphore_v2);
- furi_semaphore_free(dap_state.semaphore_cdc);
- dap_state.semaphore_v1 = NULL;
- dap_state.semaphore_v2 = NULL;
- dap_state.semaphore_cdc = NULL;
- usbd_reg_config(dev, NULL);
- usbd_reg_control(dev, NULL);
- }
- static void hid_on_wakeup(usbd_device* dev) {
- UNUSED(dev);
- if(!dap_state.connected) {
- dap_state.connected = true;
- if(dap_state.state_callback != NULL) {
- dap_state.state_callback(dap_state.connected, dap_state.context);
- }
- }
- }
- static void hid_on_suspend(usbd_device* dev) {
- UNUSED(dev);
- if(dap_state.connected) {
- dap_state.connected = false;
- if(dap_state.state_callback != NULL) {
- dap_state.state_callback(dap_state.connected, dap_state.context);
- }
- }
- }
- size_t dap_v1_usb_rx(uint8_t* buffer, size_t size) {
- size_t len = 0;
- if(dap_state.connected) {
- len = usbd_ep_read(dap_state.usb_dev, DAP_HID_EP_OUT, buffer, size);
- }
- return len;
- }
- size_t dap_v2_usb_rx(uint8_t* buffer, size_t size) {
- size_t len = 0;
- if(dap_state.connected) {
- len = usbd_ep_read(dap_state.usb_dev, DAP_HID_EP_BULK_OUT, buffer, size);
- }
- return len;
- }
- size_t dap_cdc_usb_rx(uint8_t* buffer, size_t size) {
- size_t len = 0;
- if(dap_state.connected) {
- len = usbd_ep_read(dap_state.usb_dev, HID_EP_OUT | DAP_CDC_EP_RECV, buffer, size);
- }
- return len;
- }
- static void hid_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
- UNUSED(dev);
- UNUSED(ep);
- switch(event) {
- case usbd_evt_eptx:
- furi_semaphore_release(dap_state.semaphore_v1);
- furi_console_log_printf("hid tx complete");
- break;
- case usbd_evt_eprx:
- if(dap_state.rx_callback_v1 != NULL) {
- dap_state.rx_callback_v1(dap_state.context);
- }
- break;
- default:
- furi_console_log_printf("hid %d, %d", event, ep);
- break;
- }
- }
- static void hid_txrx_ep_bulk_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
- UNUSED(dev);
- UNUSED(ep);
- switch(event) {
- case usbd_evt_eptx:
- furi_semaphore_release(dap_state.semaphore_v2);
- furi_console_log_printf("bulk tx complete");
- break;
- case usbd_evt_eprx:
- if(dap_state.rx_callback_v2 != NULL) {
- dap_state.rx_callback_v2(dap_state.context);
- }
- break;
- default:
- furi_console_log_printf("bulk %d, %d", event, ep);
- break;
- }
- }
- static void cdc_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
- UNUSED(dev);
- UNUSED(ep);
- switch(event) {
- case usbd_evt_eptx:
- furi_semaphore_release(dap_state.semaphore_cdc);
- if(dap_state.tx_complete_cdc != NULL) {
- dap_state.tx_complete_cdc(dap_state.context_cdc);
- }
- furi_console_log_printf("cdc tx complete");
- break;
- case usbd_evt_eprx:
- if(dap_state.rx_callback_cdc != NULL) {
- dap_state.rx_callback_cdc(dap_state.context_cdc);
- }
- break;
- default:
- furi_console_log_printf("cdc %d, %d", event, ep);
- break;
- }
- }
- static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg) {
- switch(cfg) {
- case EP_CFG_DECONFIGURE:
- usbd_ep_deconfig(dev, DAP_HID_EP_OUT);
- usbd_ep_deconfig(dev, DAP_HID_EP_IN);
- usbd_ep_deconfig(dev, DAP_HID_EP_BULK_IN);
- usbd_ep_deconfig(dev, DAP_HID_EP_BULK_OUT);
- usbd_ep_deconfig(dev, HID_EP_IN | DAP_CDC_EP_COMM);
- usbd_ep_deconfig(dev, HID_EP_IN | DAP_CDC_EP_SEND);
- usbd_ep_deconfig(dev, HID_EP_OUT | DAP_CDC_EP_RECV);
- usbd_reg_endpoint(dev, DAP_HID_EP_OUT, NULL);
- usbd_reg_endpoint(dev, DAP_HID_EP_IN, NULL);
- usbd_reg_endpoint(dev, DAP_HID_EP_BULK_IN, NULL);
- usbd_reg_endpoint(dev, DAP_HID_EP_BULK_OUT, NULL);
- usbd_reg_endpoint(dev, HID_EP_IN | DAP_CDC_EP_SEND, 0);
- usbd_reg_endpoint(dev, HID_EP_OUT | DAP_CDC_EP_RECV, 0);
- return usbd_ack;
- case EP_CFG_CONFIGURE:
- usbd_ep_config(dev, DAP_HID_EP_IN, USB_EPTYPE_INTERRUPT, DAP_HID_EP_SIZE);
- usbd_ep_config(dev, DAP_HID_EP_OUT, USB_EPTYPE_INTERRUPT, DAP_HID_EP_SIZE);
- usbd_ep_config(dev, DAP_HID_EP_BULK_OUT, USB_EPTYPE_BULK, DAP_HID_EP_SIZE);
- usbd_ep_config(dev, DAP_HID_EP_BULK_IN, USB_EPTYPE_BULK, DAP_HID_EP_SIZE);
- usbd_ep_config(dev, HID_EP_OUT | DAP_CDC_EP_RECV, USB_EPTYPE_BULK, DAP_CDC_EP_SIZE);
- usbd_ep_config(dev, HID_EP_IN | DAP_CDC_EP_SEND, USB_EPTYPE_BULK, DAP_CDC_EP_SIZE);
- usbd_ep_config(dev, HID_EP_IN | DAP_CDC_EP_COMM, USB_EPTYPE_INTERRUPT, DAP_CDC_EP_SIZE);
- usbd_reg_endpoint(dev, DAP_HID_EP_IN, hid_txrx_ep_callback);
- usbd_reg_endpoint(dev, DAP_HID_EP_OUT, hid_txrx_ep_callback);
- usbd_reg_endpoint(dev, DAP_HID_EP_BULK_OUT, hid_txrx_ep_bulk_callback);
- usbd_reg_endpoint(dev, DAP_HID_EP_BULK_IN, hid_txrx_ep_bulk_callback);
- usbd_reg_endpoint(dev, HID_EP_OUT | DAP_CDC_EP_RECV, cdc_txrx_ep_callback);
- usbd_reg_endpoint(dev, HID_EP_IN | DAP_CDC_EP_SEND, cdc_txrx_ep_callback);
- // usbd_ep_write(dev, DAP_HID_EP_IN, NULL, 0);
- // usbd_ep_write(dev, DAP_HID_EP_BULK_IN, NULL, 0);
- // usbd_ep_write(dev, HID_EP_IN | DAP_CDC_EP_SEND, NULL, 0);
- return usbd_ack;
- default:
- return usbd_fail;
- }
- }
- #ifdef DAP_USB_LOG
- static void dump_request_type(uint8_t type) {
- switch(type & USB_REQ_DIRECTION) {
- case USB_REQ_HOSTTODEV:
- furi_hal_console_puts("host to dev, ");
- break;
- case USB_REQ_DEVTOHOST:
- furi_hal_console_puts("dev to host, ");
- break;
- }
- switch(type & USB_REQ_TYPE) {
- case USB_REQ_STANDARD:
- furi_hal_console_puts("standard, ");
- break;
- case USB_REQ_CLASS:
- furi_hal_console_puts("class, ");
- break;
- case USB_REQ_VENDOR:
- furi_hal_console_puts("vendor, ");
- break;
- }
- switch(type & USB_REQ_RECIPIENT) {
- case USB_REQ_DEVICE:
- furi_hal_console_puts("device");
- break;
- case USB_REQ_INTERFACE:
- furi_hal_console_puts("interface");
- break;
- case USB_REQ_ENDPOINT:
- furi_hal_console_puts("endpoint");
- break;
- case USB_REQ_OTHER:
- furi_hal_console_puts("other");
- break;
- }
- furi_hal_console_puts("\r\n");
- }
- #else
- #define dump_request_type(...)
- #endif
- static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
- UNUSED(callback);
- dump_request_type(req->bmRequestType);
- furi_console_log_printf(
- "control: RT %02x, R %02x, V %04x, I %04x, L %04x",
- req->bmRequestType,
- req->bRequest,
- req->wValue,
- req->wIndex,
- req->wLength);
- if(((USB_REQ_RECIPIENT | USB_REQ_TYPE | USB_REQ_DIRECTION) & req->bmRequestType) ==
- (USB_REQ_STANDARD | USB_REQ_VENDOR | USB_REQ_DEVTOHOST)) {
- // vendor request, device to host
- furi_console_log_printf("vendor request");
- if(USB_WINUSB_VENDOR_CODE == req->bRequest) {
- // WINUSB request
- if(USB_WINUSB_DESCRIPTOR_INDEX == req->wIndex) {
- furi_console_log_printf("WINUSB descriptor");
- uint16_t length = req->wLength;
- if(length > sizeof(usb_msos_descriptor_set_t)) {
- length = sizeof(usb_msos_descriptor_set_t);
- }
- dev->status.data_ptr = (uint8_t*)&usb_msos_descriptor_set;
- dev->status.data_count = length;
- return usbd_ack;
- }
- }
- }
- if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
- (USB_REQ_STANDARD | USB_REQ_DEVICE)) {
- // device request
- if(req->bRequest == USB_STD_GET_DESCRIPTOR) {
- const uint8_t dtype = req->wValue >> 8;
- const uint8_t dnumber = req->wValue & 0xFF;
- // get string descriptor
- if(USB_DTYPE_STRING == dtype) {
- if(dnumber == USB_STR_CMSIS_DAP_V1) {
- furi_console_log_printf("str CMSIS-DAP v1");
- dev->status.data_ptr = (uint8_t*)&dev_dap_v1_descr;
- dev->status.data_count = dev_dap_v1_descr.bLength;
- return usbd_ack;
- } else if(dnumber == USB_STR_CMSIS_DAP_V2) {
- furi_console_log_printf("str CMSIS-DAP v2");
- dev->status.data_ptr = (uint8_t*)&dev_dap_v2_descr;
- dev->status.data_count = dev_dap_v2_descr.bLength;
- return usbd_ack;
- } else if(dnumber == USB_STR_COM_PORT) {
- furi_console_log_printf("str COM port");
- dev->status.data_ptr = (uint8_t*)&dev_com_descr;
- dev->status.data_count = dev_com_descr.bLength;
- return usbd_ack;
- }
- } else if(USB_DTYPE_BINARY_OBJECT_STORE == dtype) {
- furi_console_log_printf("BOS descriptor");
- uint16_t length = req->wLength;
- if(length > sizeof(usb_bos_hierarchy_t)) {
- length = sizeof(usb_bos_hierarchy_t);
- }
- dev->status.data_ptr = (uint8_t*)&usb_bos_hierarchy;
- dev->status.data_count = length;
- return usbd_ack;
- }
- }
- }
- if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
- (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
- req->wIndex == 0) {
- // class request
- switch(req->bRequest) {
- // get hid descriptor
- case USB_HID_GETREPORT:
- furi_console_log_printf("get report");
- return usbd_fail;
- // set hid idle
- case USB_HID_SETIDLE:
- furi_console_log_printf("set idle");
- return usbd_ack;
- default:
- break;
- }
- }
- if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
- (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
- req->wIndex == 2) {
- // class request
- switch(req->bRequest) {
- // control line state
- case USB_CDC_SET_CONTROL_LINE_STATE:
- furi_console_log_printf("set control line state");
- cdc_ctrl_line_state = req->wValue;
- if(dap_state.control_line_callback_cdc != NULL) {
- dap_state.control_line_callback_cdc(cdc_ctrl_line_state, dap_state.context_cdc);
- }
- return usbd_ack;
- // set cdc line coding
- case USB_CDC_SET_LINE_CODING:
- furi_console_log_printf("set line coding");
- memcpy(&cdc_config, req->data, sizeof(cdc_config));
- if(dap_state.config_callback_cdc != NULL) {
- dap_state.config_callback_cdc(&cdc_config, dap_state.context_cdc);
- }
- return usbd_ack;
- // get cdc line coding
- case USB_CDC_GET_LINE_CODING:
- furi_console_log_printf("get line coding");
- dev->status.data_ptr = &cdc_config;
- dev->status.data_count = sizeof(cdc_config);
- return usbd_ack;
- default:
- break;
- }
- }
- if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
- (USB_REQ_INTERFACE | USB_REQ_STANDARD) &&
- req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
- // standard request
- switch(req->wValue >> 8) {
- // get hid descriptor
- case USB_DTYPE_HID:
- furi_console_log_printf("get hid descriptor");
- dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.hid);
- dev->status.data_count = sizeof(hid_cfg_desc.hid);
- return usbd_ack;
- // get hid report descriptor
- case USB_DTYPE_HID_REPORT:
- furi_console_log_printf("get hid report descriptor");
- dev->status.data_ptr = (uint8_t*)hid_report_desc;
- dev->status.data_count = sizeof(hid_report_desc);
- return usbd_ack;
- default:
- break;
- }
- }
- return usbd_fail;
- }
|