diff --git a/applications/bad_usb/bad_usb_app.c b/applications/bad_usb/bad_usb_app.c index adf9b7c8..8f806f9f 100644 --- a/applications/bad_usb/bad_usb_app.c +++ b/applications/bad_usb/bad_usb_app.c @@ -115,15 +115,10 @@ void bad_usb_app_free(BadUsbApp* app) { } int32_t bad_usb_app(void* p) { - FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); - furi_hal_usb_set_config(&usb_hid); - BadUsbApp* bad_usb_app = bad_usb_app_alloc((char*)p); view_dispatcher_run(bad_usb_app->view_dispatcher); - furi_hal_usb_set_config(usb_mode_prev); bad_usb_app_free(bad_usb_app); - return 0; } diff --git a/applications/bad_usb/bad_usb_script.c b/applications/bad_usb/bad_usb_script.c index a57a431b..593a7cc1 100644 --- a/applications/bad_usb/bad_usb_script.c +++ b/applications/bad_usb/bad_usb_script.c @@ -24,6 +24,7 @@ typedef enum { } WorkerEvtFlags; struct BadUsbScript { + FuriHalUsbHidConfig hid_cfg; BadUsbState st; string_t file_path; uint32_t defdelay; @@ -101,6 +102,7 @@ static const DuckyKey ducky_keys[] = { }; static const char ducky_cmd_comment[] = {"REM"}; +static const char ducky_cmd_id[] = {"ID"}; static const char ducky_cmd_delay[] = {"DELAY "}; static const char ducky_cmd_string[] = {"STRING "}; static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "}; @@ -240,12 +242,15 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) { if(i == line_len - 1) return SCRIPT_STATE_NEXT_LINE; // Skip empty lines } - FURI_LOG_I(WORKER_TAG, "line:%s", line_tmp); + FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp); // General commands if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) { // REM - comment line return (0); + } else if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) { + // ID - executed in ducky_script_preload + return (0); } else if(strncmp(line_tmp, ducky_cmd_delay, strlen(ducky_cmd_delay)) == 0) { // DELAY line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; @@ -302,10 +307,37 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) { return SCRIPT_STATE_ERROR; } +static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) { + if(sscanf(line, "%lX:%lX", &bad_usb->hid_cfg.vid, &bad_usb->hid_cfg.pid) == 2) { + bad_usb->hid_cfg.manuf[0] = '\0'; + bad_usb->hid_cfg.product[0] = '\0'; + + uint8_t id_len = ducky_get_command_len(line); + if(!ducky_is_line_end(line[id_len + 1])) { + sscanf( + &line[id_len + 1], + "%31[^\r\n:]:%31[^\r\n]", + bad_usb->hid_cfg.manuf, + bad_usb->hid_cfg.product); + } + FURI_LOG_D( + WORKER_TAG, + "set id: %04X:%04X mfr:%s product:%s", + bad_usb->hid_cfg.vid, + bad_usb->hid_cfg.pid, + bad_usb->hid_cfg.manuf, + bad_usb->hid_cfg.product); + return true; + } + return false; +} + static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) { uint8_t ret = 0; uint32_t line_len = 0; + string_reset(bad_usb->line); + do { ret = storage_file_read(script_file, bad_usb->file_buf, FILE_BUFFER_LEN); for(uint16_t i = 0; i < ret; i++) { @@ -313,6 +345,9 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) { bad_usb->st.line_nb++; line_len = 0; } else { + if(bad_usb->st.line_nb == 0) { // Save first line + string_push_back(bad_usb->line, bad_usb->file_buf[i]); + } line_len++; } } @@ -324,7 +359,20 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) { } } while(ret > 0); + const char* line_tmp = string_get_cstr(bad_usb->line); + bool id_set = false; // Looking for ID command at first line + if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) { + id_set = ducky_set_usb_id(bad_usb, &line_tmp[strlen(ducky_cmd_id) + 1]); + } + + if(id_set) { + furi_hal_usb_set_config(&usb_hid, &bad_usb->hid_cfg); + } else { + furi_hal_usb_set_config(&usb_hid, NULL); + } + storage_file_seek(script_file, 0, true); + string_reset(bad_usb->line); return true; } @@ -403,6 +451,8 @@ static int32_t bad_usb_worker(void* context) { BadUsbWorkerState worker_state = BadUsbStateInit; int32_t delay_val = 0; + FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); + FURI_LOG_I(WORKER_TAG, "Init"); File* script_file = storage_file_alloc(furi_record_open("storage")); string_init(bad_usb->line); @@ -522,6 +572,8 @@ static int32_t bad_usb_worker(void* context) { furi_hal_hid_set_state_callback(NULL, NULL); + furi_hal_usb_set_config(usb_mode_prev, NULL); + storage_file_close(script_file); storage_file_free(script_file); string_clear(bad_usb->line); diff --git a/applications/debug_tools/usb_mouse.c b/applications/debug_tools/usb_mouse.c index 9321b806..93550bec 100644 --- a/applications/debug_tools/usb_mouse.c +++ b/applications/debug_tools/usb_mouse.c @@ -42,7 +42,7 @@ int32_t usb_mouse_app(void* p) { ViewPort* view_port = view_port_alloc(); FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); - furi_hal_usb_set_config(&usb_hid); + furi_hal_usb_set_config(&usb_hid, NULL); view_port_draw_callback_set(view_port, usb_mouse_render_callback, NULL); view_port_input_callback_set(view_port, usb_mouse_input_callback, event_queue); @@ -110,7 +110,7 @@ int32_t usb_mouse_app(void* p) { view_port_update(view_port); } - furi_hal_usb_set_config(usb_mode_prev); + furi_hal_usb_set_config(usb_mode_prev, NULL); // remove & free all stuff created by app gui_remove_view_port(gui, view_port); diff --git a/applications/debug_tools/usb_test.c b/applications/debug_tools/usb_test.c index cdc1aa40..0e8f068f 100644 --- a/applications/debug_tools/usb_test.c +++ b/applications/debug_tools/usb_test.c @@ -10,6 +10,7 @@ typedef struct { Gui* gui; ViewDispatcher* view_dispatcher; Submenu* submenu; + FuriHalUsbHidConfig hid_cfg; } UsbTestApp; typedef enum { @@ -19,12 +20,13 @@ typedef enum { UsbTestSubmenuIndexVcpSingle, UsbTestSubmenuIndexVcpDual, UsbTestSubmenuIndexHid, + UsbTestSubmenuIndexHidWithParams, UsbTestSubmenuIndexHidU2F, } SubmenuIndex; void usb_test_submenu_callback(void* context, uint32_t index) { furi_assert(context); - //UsbTestApp* app = context; + UsbTestApp* app = context; if(index == UsbTestSubmenuIndexEnable) { furi_hal_usb_enable(); } else if(index == UsbTestSubmenuIndexDisable) { @@ -32,13 +34,19 @@ void usb_test_submenu_callback(void* context, uint32_t index) { } else if(index == UsbTestSubmenuIndexRestart) { furi_hal_usb_reinit(); } else if(index == UsbTestSubmenuIndexVcpSingle) { - furi_hal_usb_set_config(&usb_cdc_single); + furi_hal_usb_set_config(&usb_cdc_single, NULL); } else if(index == UsbTestSubmenuIndexVcpDual) { - furi_hal_usb_set_config(&usb_cdc_dual); + furi_hal_usb_set_config(&usb_cdc_dual, NULL); } else if(index == UsbTestSubmenuIndexHid) { - furi_hal_usb_set_config(&usb_hid); + furi_hal_usb_set_config(&usb_hid, NULL); + } else if(index == UsbTestSubmenuIndexHidWithParams) { + app->hid_cfg.vid = 0x1234; + app->hid_cfg.pid = 0xabcd; + strncpy(app->hid_cfg.manuf, "WEN", sizeof(app->hid_cfg.manuf)); + strncpy(app->hid_cfg.product, "FLIP", sizeof(app->hid_cfg.product)); + furi_hal_usb_set_config(&usb_hid, &app->hid_cfg); } else if(index == UsbTestSubmenuIndexHidU2F) { - furi_hal_usb_set_config(&usb_hid_u2f); + furi_hal_usb_set_config(&usb_hid_u2f, NULL); } } @@ -71,6 +79,12 @@ UsbTestApp* usb_test_app_alloc() { app->submenu, "Dual VCP", UsbTestSubmenuIndexVcpDual, usb_test_submenu_callback, app); submenu_add_item( app->submenu, "HID KB+Mouse", UsbTestSubmenuIndexHid, usb_test_submenu_callback, app); + submenu_add_item( + app->submenu, + "HID KB+Mouse custom ID", + UsbTestSubmenuIndexHidWithParams, + usb_test_submenu_callback, + app); submenu_add_item( app->submenu, "HID U2F", UsbTestSubmenuIndexHidU2F, usb_test_submenu_callback, app); view_set_previous_callback(submenu_get_view(app->submenu), usb_test_exit); diff --git a/applications/gpio/usb_uart_bridge.c b/applications/gpio/usb_uart_bridge.c index e8762ca9..2832e7f8 100644 --- a/applications/gpio/usb_uart_bridge.c +++ b/applications/gpio/usb_uart_bridge.c @@ -84,10 +84,10 @@ static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) { if(vcp_ch == 0) { - furi_hal_usb_set_config(&usb_cdc_single); + furi_hal_usb_set_config(&usb_cdc_single, NULL); furi_hal_vcp_disable(); } else { - furi_hal_usb_set_config(&usb_cdc_dual); + furi_hal_usb_set_config(&usb_cdc_dual, NULL); } furi_hal_cdc_set_callbacks(vcp_ch, (CdcCallbacks*)&cdc_cb, usb_uart); } @@ -247,7 +247,7 @@ static int32_t usb_uart_worker(void* context) { usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch); usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch); - furi_hal_usb_set_config(usb_mode_prev); + furi_hal_usb_set_config(usb_mode_prev, NULL); if(usb_uart->cfg.flow_pins != 0) { hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog); hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); diff --git a/applications/u2f/u2f_hid.c b/applications/u2f/u2f_hid.c index ff1109fe..e48f8b1c 100644 --- a/applications/u2f/u2f_hid.c +++ b/applications/u2f/u2f_hid.c @@ -191,7 +191,7 @@ static int32_t u2f_hid_worker(void* context) { FURI_LOG_D(WORKER_TAG, "Init"); FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); - furi_hal_usb_set_config(&usb_hid_u2f); + furi_hal_usb_set_config(&usb_hid_u2f, NULL); u2f_hid->lock_timer = osTimerNew(u2f_hid_lock_timeout_callback, osTimerOnce, u2f_hid, NULL); @@ -270,7 +270,7 @@ static int32_t u2f_hid_worker(void* context) { osTimerDelete(u2f_hid->lock_timer); furi_hal_hid_u2f_set_callback(NULL, NULL); - furi_hal_usb_set_config(usb_mode_prev); + furi_hal_usb_set_config(usb_mode_prev, NULL); FURI_LOG_D(WORKER_TAG, "End"); return 0; diff --git a/assets/resources/badusb/demo_macos.txt b/assets/resources/badusb/demo_macos.txt index 2e33c196..5070edad 100644 --- a/assets/resources/badusb/demo_macos.txt +++ b/assets/resources/badusb/demo_macos.txt @@ -1,3 +1,7 @@ +ID 1234:5678 Apple:Keyboard +REM You can change these values to VID/PID of original Apple keyboard +REM to bypass Keyboard Setup Assistant + REM This is BadUSB demo script for macOS REM Open terminal window diff --git a/firmware/targets/f6/furi_hal/furi_hal_usb.c b/firmware/targets/f6/furi_hal/furi_hal_usb.c index c948a3cf..ac87dfe2 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f6/furi_hal/furi_hal_usb.c @@ -18,6 +18,7 @@ typedef struct { bool connected; FuriHalUsbInterface* if_cur; FuriHalUsbInterface* if_next; + void* if_ctx; FuriHalUsbStateCallback callback; void* cb_ctx; } UsbSrv; @@ -88,8 +89,9 @@ void furi_hal_usb_init(void) { FURI_LOG_I(TAG, "Init OK"); } -void furi_hal_usb_set_config(FuriHalUsbInterface* new_if) { +void furi_hal_usb_set_config(FuriHalUsbInterface* new_if, void* ctx) { usb.if_next = new_if; + usb.if_ctx = ctx; if(usb.thread == NULL) { // Service thread hasn't started yet, so just save interface mode return; @@ -246,7 +248,7 @@ static int32_t furi_hal_usb_thread(void* context) { usb.if_cur->deinit(&udev); } if(usb.if_next != NULL) { - usb.if_next->init(&udev, usb.if_next); + usb.if_next->init(&udev, usb.if_next, usb.if_ctx); usbd_reg_event(&udev, usbd_evt_reset, reset_evt); FURI_LOG_I(TAG, "USB Mode change done"); usb.enabled = true; diff --git a/firmware/targets/f6/furi_hal/furi_hal_usb_cdc.c b/firmware/targets/f6/furi_hal/furi_hal_usb_cdc.c index bf0fd7d4..028e3e30 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_usb_cdc.c +++ b/firmware/targets/f6/furi_hal/furi_hal_usb_cdc.c @@ -385,7 +385,7 @@ static const struct CdcConfigDescriptorDual static struct usb_cdc_line_coding cdc_config[IF_NUM_MAX] = {}; static uint8_t cdc_ctrl_line_state[IF_NUM_MAX]; -static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf); +static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx); static void cdc_deinit(usbd_device* dev); static void cdc_on_wakeup(usbd_device* dev); static void cdc_on_suspend(usbd_device* dev); @@ -428,7 +428,7 @@ FuriHalUsbInterface usb_cdc_dual = { .cfg_descr = (void*)&cdc_cfg_desc_dual, }; -static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf) { +static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { usb_dev = dev; cdc_if_cur = intf; diff --git a/firmware/targets/f6/furi_hal/furi_hal_usb_hid.c b/firmware/targets/f6/furi_hal/furi_hal_usb_hid.c index 6f94fb33..b9b4bbb0 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_usb_hid.c +++ b/firmware/targets/f6/furi_hal/furi_hal_usb_hid.c @@ -21,6 +21,9 @@ #define HID_PAGE_CONSUMER 0x0C #define HID_CONSUMER_CONTROL 0x01 +#define HID_VID_DEFAULT 0x046D +#define HID_PID_DEFAULT 0xC529 + struct HidIadDescriptor { struct usb_iad_descriptor hid_iad; struct usb_interface_descriptor hid; @@ -114,12 +117,8 @@ static const uint8_t hid_report_desc[] = { 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 = { +static struct usb_device_descriptor hid_device_desc = { .bLength = sizeof(struct usb_device_descriptor), .bDescriptorType = USB_DTYPE_DEVICE, .bcdUSB = VERSION_BCD(2, 0, 0), @@ -127,12 +126,12 @@ static const struct usb_device_descriptor hid_device_desc = { .bDeviceSubClass = USB_SUBCLASS_IAD, .bDeviceProtocol = USB_PROTO_IAD, .bMaxPacketSize0 = USB_EP0_SIZE, - .idVendor = 0x046d, - .idProduct = 0xc529, + .idVendor = HID_VID_DEFAULT, + .idProduct = HID_PID_DEFAULT, .bcdDevice = VERSION_BCD(1, 0, 0), - .iManufacturer = UsbDevManuf, - .iProduct = UsbDevProduct, - .iSerialNumber = UsbDevSerial, + .iManufacturer = 0, + .iProduct = 0, + .iSerialNumber = 0, .bNumConfigurations = 1, }; @@ -236,11 +235,26 @@ static struct HidReport { struct HidReportConsumer consumer; } __attribute__((packed)) hid_report; -static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf); +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); +FuriHalUsbInterface 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 = NULL, + .str_prod_descr = NULL, + .str_serial_descr = NULL, + + .cfg_descr = (void*)&hid_cfg_desc, +}; + static bool hid_send_report(uint8_t report_id); 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); @@ -348,28 +362,48 @@ bool furi_hal_hid_consumer_key_release(uint16_t button) { return hid_send_report(ReportIdConsumer); } -FuriHalUsbInterface usb_hid = { - .init = hid_init, - .deinit = hid_deinit, - .wakeup = hid_on_wakeup, - .suspend = hid_on_suspend, +static void* hid_set_string_descr(char* str) { + furi_assert(str); - .dev_descr = (struct usb_device_descriptor*)&hid_device_desc, + uint8_t len = strlen(str); + struct usb_string_descriptor* dev_str_desc = malloc(len * 2 + 2); + dev_str_desc->bLength = len * 2 + 2; + dev_str_desc->bDescriptorType = USB_DTYPE_STRING; + for(uint8_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i]; - .str_manuf_descr = (void*)&dev_manuf_desc, - .str_prod_descr = (void*)&dev_prod_desc, - .str_serial_descr = (void*)&dev_serial_desc, + return dev_str_desc; +} - .cfg_descr = (void*)&hid_cfg_desc, -}; - -static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf) { +static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { + FuriHalUsbHidConfig* cfg = (FuriHalUsbHidConfig*)ctx; if(hid_semaphore == NULL) hid_semaphore = osSemaphoreNew(1, 1, NULL); usb_dev = dev; hid_report.keyboard.report_id = ReportIdKeyboard; hid_report.mouse.report_id = ReportIdMouse; hid_report.consumer.report_id = ReportIdConsumer; + usb_hid.dev_descr->iManufacturer = 0; + usb_hid.dev_descr->iProduct = 0; + usb_hid.str_manuf_descr = NULL; + usb_hid.str_prod_descr = NULL; + usb_hid.dev_descr->idVendor = HID_VID_DEFAULT; + usb_hid.dev_descr->idProduct = HID_PID_DEFAULT; + + if(cfg != NULL) { + usb_hid.dev_descr->idVendor = cfg->vid; + usb_hid.dev_descr->idProduct = cfg->pid; + + if(cfg->manuf[0] != '\0') { + usb_hid.str_manuf_descr = hid_set_string_descr(cfg->manuf); + usb_hid.dev_descr->iManufacturer = UsbDevManuf; + } + + if(cfg->product[0] != '\0') { + usb_hid.str_prod_descr = hid_set_string_descr(cfg->product); + usb_hid.dev_descr->iProduct = UsbDevProduct; + } + } + usbd_reg_config(dev, hid_ep_config); usbd_reg_control(dev, hid_control); @@ -379,6 +413,9 @@ static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf) { static void hid_deinit(usbd_device* dev) { usbd_reg_config(dev, NULL); usbd_reg_control(dev, NULL); + + free(usb_hid.str_manuf_descr); + free(usb_hid.str_prod_descr); } static void hid_on_wakeup(usbd_device* dev) { diff --git a/firmware/targets/f6/furi_hal/furi_hal_usb_u2f.c b/firmware/targets/f6/furi_hal/furi_hal_usb_u2f.c index 4ee3d712..37d879ed 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_usb_u2f.c +++ b/firmware/targets/f6/furi_hal/furi_hal_usb_u2f.c @@ -137,7 +137,7 @@ static const struct HidConfigDescriptor hid_u2f_cfg_desc = { }, }; -static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf); +static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx); static void hid_u2f_deinit(usbd_device* dev); static void hid_u2f_on_wakeup(usbd_device* dev); static void hid_u2f_on_suspend(usbd_device* dev); @@ -185,7 +185,7 @@ FuriHalUsbInterface usb_hid_u2f = { .cfg_descr = (void*)&hid_u2f_cfg_desc, }; -static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf) { +static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { if(hid_u2f_semaphore == NULL) hid_u2f_semaphore = osSemaphoreNew(1, 1, NULL); usb_dev = dev; diff --git a/firmware/targets/f6/furi_hal/furi_hal_vcp.c b/firmware/targets/f6/furi_hal/furi_hal_vcp.c index 828fc619..b0edf9db 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_vcp.c +++ b/firmware/targets/f6/furi_hal/furi_hal_vcp.c @@ -79,7 +79,7 @@ static int32_t vcp_worker(void* context) { size_t missed_rx = 0; uint8_t last_tx_pkt_len = 0; - furi_hal_usb_set_config(&usb_cdc_single); + furi_hal_usb_set_config(&usb_cdc_single, NULL); furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL); while(1) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb.c b/firmware/targets/f7/furi_hal/furi_hal_usb.c index c948a3cf..ac87dfe2 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb.c @@ -18,6 +18,7 @@ typedef struct { bool connected; FuriHalUsbInterface* if_cur; FuriHalUsbInterface* if_next; + void* if_ctx; FuriHalUsbStateCallback callback; void* cb_ctx; } UsbSrv; @@ -88,8 +89,9 @@ void furi_hal_usb_init(void) { FURI_LOG_I(TAG, "Init OK"); } -void furi_hal_usb_set_config(FuriHalUsbInterface* new_if) { +void furi_hal_usb_set_config(FuriHalUsbInterface* new_if, void* ctx) { usb.if_next = new_if; + usb.if_ctx = ctx; if(usb.thread == NULL) { // Service thread hasn't started yet, so just save interface mode return; @@ -246,7 +248,7 @@ static int32_t furi_hal_usb_thread(void* context) { usb.if_cur->deinit(&udev); } if(usb.if_next != NULL) { - usb.if_next->init(&udev, usb.if_next); + usb.if_next->init(&udev, usb.if_next, usb.if_ctx); usbd_reg_event(&udev, usbd_evt_reset, reset_evt); FURI_LOG_I(TAG, "USB Mode change done"); usb.enabled = true; diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c index bf0fd7d4..028e3e30 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c @@ -385,7 +385,7 @@ static const struct CdcConfigDescriptorDual static struct usb_cdc_line_coding cdc_config[IF_NUM_MAX] = {}; static uint8_t cdc_ctrl_line_state[IF_NUM_MAX]; -static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf); +static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx); static void cdc_deinit(usbd_device* dev); static void cdc_on_wakeup(usbd_device* dev); static void cdc_on_suspend(usbd_device* dev); @@ -428,7 +428,7 @@ FuriHalUsbInterface usb_cdc_dual = { .cfg_descr = (void*)&cdc_cfg_desc_dual, }; -static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf) { +static void cdc_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { usb_dev = dev; cdc_if_cur = intf; diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c index 6f94fb33..b9b4bbb0 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c @@ -21,6 +21,9 @@ #define HID_PAGE_CONSUMER 0x0C #define HID_CONSUMER_CONTROL 0x01 +#define HID_VID_DEFAULT 0x046D +#define HID_PID_DEFAULT 0xC529 + struct HidIadDescriptor { struct usb_iad_descriptor hid_iad; struct usb_interface_descriptor hid; @@ -114,12 +117,8 @@ static const uint8_t hid_report_desc[] = { 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 = { +static struct usb_device_descriptor hid_device_desc = { .bLength = sizeof(struct usb_device_descriptor), .bDescriptorType = USB_DTYPE_DEVICE, .bcdUSB = VERSION_BCD(2, 0, 0), @@ -127,12 +126,12 @@ static const struct usb_device_descriptor hid_device_desc = { .bDeviceSubClass = USB_SUBCLASS_IAD, .bDeviceProtocol = USB_PROTO_IAD, .bMaxPacketSize0 = USB_EP0_SIZE, - .idVendor = 0x046d, - .idProduct = 0xc529, + .idVendor = HID_VID_DEFAULT, + .idProduct = HID_PID_DEFAULT, .bcdDevice = VERSION_BCD(1, 0, 0), - .iManufacturer = UsbDevManuf, - .iProduct = UsbDevProduct, - .iSerialNumber = UsbDevSerial, + .iManufacturer = 0, + .iProduct = 0, + .iSerialNumber = 0, .bNumConfigurations = 1, }; @@ -236,11 +235,26 @@ static struct HidReport { struct HidReportConsumer consumer; } __attribute__((packed)) hid_report; -static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf); +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); +FuriHalUsbInterface 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 = NULL, + .str_prod_descr = NULL, + .str_serial_descr = NULL, + + .cfg_descr = (void*)&hid_cfg_desc, +}; + static bool hid_send_report(uint8_t report_id); 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); @@ -348,28 +362,48 @@ bool furi_hal_hid_consumer_key_release(uint16_t button) { return hid_send_report(ReportIdConsumer); } -FuriHalUsbInterface usb_hid = { - .init = hid_init, - .deinit = hid_deinit, - .wakeup = hid_on_wakeup, - .suspend = hid_on_suspend, +static void* hid_set_string_descr(char* str) { + furi_assert(str); - .dev_descr = (struct usb_device_descriptor*)&hid_device_desc, + uint8_t len = strlen(str); + struct usb_string_descriptor* dev_str_desc = malloc(len * 2 + 2); + dev_str_desc->bLength = len * 2 + 2; + dev_str_desc->bDescriptorType = USB_DTYPE_STRING; + for(uint8_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i]; - .str_manuf_descr = (void*)&dev_manuf_desc, - .str_prod_descr = (void*)&dev_prod_desc, - .str_serial_descr = (void*)&dev_serial_desc, + return dev_str_desc; +} - .cfg_descr = (void*)&hid_cfg_desc, -}; - -static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf) { +static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { + FuriHalUsbHidConfig* cfg = (FuriHalUsbHidConfig*)ctx; if(hid_semaphore == NULL) hid_semaphore = osSemaphoreNew(1, 1, NULL); usb_dev = dev; hid_report.keyboard.report_id = ReportIdKeyboard; hid_report.mouse.report_id = ReportIdMouse; hid_report.consumer.report_id = ReportIdConsumer; + usb_hid.dev_descr->iManufacturer = 0; + usb_hid.dev_descr->iProduct = 0; + usb_hid.str_manuf_descr = NULL; + usb_hid.str_prod_descr = NULL; + usb_hid.dev_descr->idVendor = HID_VID_DEFAULT; + usb_hid.dev_descr->idProduct = HID_PID_DEFAULT; + + if(cfg != NULL) { + usb_hid.dev_descr->idVendor = cfg->vid; + usb_hid.dev_descr->idProduct = cfg->pid; + + if(cfg->manuf[0] != '\0') { + usb_hid.str_manuf_descr = hid_set_string_descr(cfg->manuf); + usb_hid.dev_descr->iManufacturer = UsbDevManuf; + } + + if(cfg->product[0] != '\0') { + usb_hid.str_prod_descr = hid_set_string_descr(cfg->product); + usb_hid.dev_descr->iProduct = UsbDevProduct; + } + } + usbd_reg_config(dev, hid_ep_config); usbd_reg_control(dev, hid_control); @@ -379,6 +413,9 @@ static void hid_init(usbd_device* dev, FuriHalUsbInterface* intf) { static void hid_deinit(usbd_device* dev) { usbd_reg_config(dev, NULL); usbd_reg_control(dev, NULL); + + free(usb_hid.str_manuf_descr); + free(usb_hid.str_prod_descr); } static void hid_on_wakeup(usbd_device* dev) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c b/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c index 4ee3d712..37d879ed 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_u2f.c @@ -137,7 +137,7 @@ static const struct HidConfigDescriptor hid_u2f_cfg_desc = { }, }; -static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf); +static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx); static void hid_u2f_deinit(usbd_device* dev); static void hid_u2f_on_wakeup(usbd_device* dev); static void hid_u2f_on_suspend(usbd_device* dev); @@ -185,7 +185,7 @@ FuriHalUsbInterface usb_hid_u2f = { .cfg_descr = (void*)&hid_u2f_cfg_desc, }; -static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf) { +static void hid_u2f_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) { if(hid_u2f_semaphore == NULL) hid_u2f_semaphore = osSemaphoreNew(1, 1, NULL); usb_dev = dev; diff --git a/firmware/targets/f7/furi_hal/furi_hal_vcp.c b/firmware/targets/f7/furi_hal/furi_hal_vcp.c index 828fc619..b0edf9db 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_vcp.c +++ b/firmware/targets/f7/furi_hal/furi_hal_vcp.c @@ -79,7 +79,7 @@ static int32_t vcp_worker(void* context) { size_t missed_rx = 0; uint8_t last_tx_pkt_len = 0; - furi_hal_usb_set_config(&usb_cdc_single); + furi_hal_usb_set_config(&usb_cdc_single, NULL); furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL); while(1) { diff --git a/firmware/targets/furi_hal_include/furi_hal_usb.h b/firmware/targets/furi_hal_include/furi_hal_usb.h index 9ab9b642..f1a05107 100644 --- a/firmware/targets/furi_hal_include/furi_hal_usb.h +++ b/firmware/targets/furi_hal_include/furi_hal_usb.h @@ -5,7 +5,7 @@ typedef struct FuriHalUsbInterface FuriHalUsbInterface; struct FuriHalUsbInterface { - void (*init)(usbd_device* dev, FuriHalUsbInterface* intf); + void (*init)(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx); void (*deinit)(usbd_device* dev); void (*wakeup)(usbd_device* dev); void (*suspend)(usbd_device* dev); @@ -41,8 +41,9 @@ void furi_hal_usb_init(); /** Set USB device configuration * * @param mode new USB device mode + * @param ctx context passed to device mode init function */ -void furi_hal_usb_set_config(FuriHalUsbInterface* new_if); +void furi_hal_usb_set_config(FuriHalUsbInterface* new_if, void* ctx); /** Get USB device configuration * diff --git a/firmware/targets/furi_hal_include/furi_hal_usb_hid.h b/firmware/targets/furi_hal_include/furi_hal_usb_hid.h index 6adfb7f1..4819e82e 100644 --- a/firmware/targets/furi_hal_include/furi_hal_usb_hid.h +++ b/firmware/targets/furi_hal_include/furi_hal_usb_hid.h @@ -250,6 +250,13 @@ static const uint16_t hid_asciimap[] = { KEY_NONE, // DEL }; +typedef struct { + uint32_t vid; + uint32_t pid; + char manuf[32]; + char product[32]; +} FuriHalUsbHidConfig; + typedef void (*HidStateCallback)(bool state, void* context); /** ASCII to keycode conversion macro */