浏览代码

chore: mtp

Alex4386 1 年之前
父节点
当前提交
e3b83f3401
共有 4 个文件被更改,包括 228 次插入1 次删除
  1. 12 1
      src/scenes/mtp/main.c
  2. 6 0
      src/scenes/mtp/main.h
  3. 97 0
      src/scenes/mtp/usb.c
  4. 113 0
      src/scenes/mtp/usb.h

+ 12 - 1
src/scenes/mtp/main.c

@@ -3,6 +3,7 @@
 #include "../../main.h"
 #include "main.h"
 #include <demo_app_icons.h>
+#include "usb.h"
 
 #define THIS_SCENE MTP
 
@@ -15,7 +16,7 @@ AppMTP* MTP_alloc() {
     view_set_context(about->view, about);
     view_set_draw_callback(about->view, MTP_on_draw);
 
-    about->usb_connected = true;
+    about->usb_connected = false;
     tmp = about;
 
     return about;
@@ -79,6 +80,13 @@ void MTP_on_enter(void* context) {
     App* app = (App*)context;
 
     view_dispatcher_switch_to_view(app->view_dispatcher, THIS_SCENE);
+    furi_assert(app->allocated_scenes != NULL, "App allocated scenes is NULL");
+
+    AppMTP* mtp = app->allocated_scenes[THIS_SCENE];
+    if(mtp != NULL) {
+        mtp->old_usb = furi_hal_usb_get_config();
+        furi_hal_usb_set_config(&usb_mtp_interface, mtp);
+    }
 }
 
 bool MTP_on_event(void* context, SceneManagerEvent event) {
@@ -98,6 +106,9 @@ void MTP_on_exit(void* context) {
         return;
     }
 
+    // revert to old usb mode
+    furi_hal_usb_set_config(tmp->old_usb, NULL);
+
     // if(app->view_dispatcher) view_dispatcher_switch_to_view(app->view_dispatcher, Home);
     // if(app->scene_manager) scene_manager_previous_scene(app->scene_manager);
 }

+ 6 - 0
src/scenes/mtp/main.h

@@ -2,12 +2,18 @@
 #include <gui/view.h>
 #include <gui/modules/submenu.h>
 #include <gui/modules/popup.h>
+#include <furi_hal.h>
 
 typedef struct AppMTP {
     Submenu* menu;
     View* view;
 
     bool usb_connected;
+
+    // usb stuff
+    FuriHalUsbInterface* old_usb;
+    FuriThread* worker_thread;
+    usbd_device* dev;
 } AppMTP;
 
 AppMTP* MTP_alloc();

+ 97 - 0
src/scenes/mtp/usb.c

@@ -0,0 +1,97 @@
+#include "main.h"
+#include "usb.h"
+#include <furi.h>
+#include <furi_hal.h>
+
+// Define MTP specific request constants
+#define MTP_REQ_GET_DEVICE_STATUS 0x67
+#define MTP_REQ_SEND_DATA 0x68
+#define MTP_REQ_GET_DATA 0x69
+
+AppMTP* global_mtp;
+
+typedef enum {
+    EventExit = 1 << 0,
+    EventReset = 1 << 1,
+    EventRxTx = 1 << 2,
+
+    EventAll = EventExit | EventReset | EventRxTx,
+} MTPEvent;
+
+int32_t usb_mtp_worker(void* ctx) {
+    AppMTP* mtp = ctx;
+    usbd_device* dev = mtp->dev;
+    while(true) {
+        furi_thread_flags_wait(EventAll, FuriFlagWaitAny, FuriWaitForever);
+        if(furi_thread_flags_get() & EventExit) break;
+
+        if(furi_thread_flags_get() & EventReset) {
+            furi_thread_flags_clear(EventReset);
+            furi_hal_usb_set_config(mtp->old_usb, NULL);
+        }
+
+        if(furi_thread_flags_get() & EventRxTx) {
+            furi_thread_flags_clear(EventRxTx);
+            // Handle MTP RX/TX data here
+            // Implement the logic for processing MTP requests, sending responses, etc.
+        }
+    }
+    return 0;
+}
+
+void usb_mtp_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
+    UNUSED(intf);
+    AppMTP* mtp = ctx;
+    global_mtp = mtp;
+
+    usbd_reg_control(dev, usb_mtp_control);
+    usbd_connect(dev, true);
+
+    mtp->worker_thread = furi_thread_alloc();
+    furi_thread_set_name(mtp->worker_thread, "FlipperMTPUsb");
+    furi_thread_set_stack_size(mtp->worker_thread, 1024);
+    furi_thread_set_context(mtp->worker_thread, ctx);
+    furi_thread_set_callback(mtp->worker_thread, usb_mtp_worker);
+    furi_thread_start(mtp->worker_thread);
+}
+
+usbd_respond usb_mtp_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
+    UNUSED(callback);
+    if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) !=
+       (USB_REQ_INTERFACE | USB_REQ_CLASS)) {
+        if(global_mtp != NULL) {
+            global_mtp->usb_connected = false;
+        }
+        return usbd_fail;
+    }
+    switch(req->bRequest) {};
+    return usbd_fail;
+}
+
+void usb_deinit(usbd_device* dev) {
+    usbd_reg_control(dev, NULL);
+
+    AppMTP* mtp = global_mtp;
+    if(!mtp || mtp->dev != dev) {
+        FURI_LOG_E("MTP", "deinit mtp_cur leak");
+        return;
+    }
+
+    global_mtp = NULL;
+
+    furi_assert(mtp->worker_thread);
+    furi_thread_flags_set(furi_thread_get_id(mtp->worker_thread), EventExit);
+    furi_thread_join(mtp->worker_thread);
+    furi_thread_free(mtp->worker_thread);
+    mtp->worker_thread = NULL;
+}
+
+void usb_wakeup(usbd_device* dev) {
+    UNUSED(dev);
+}
+
+void usb_suspend(usbd_device* dev) {
+    AppMTP* mtp = global_mtp;
+    if(!mtp || mtp->dev != dev) return;
+    furi_thread_flags_set(furi_thread_get_id(mtp->worker_thread), EventReset);
+}

+ 113 - 0
src/scenes/mtp/usb.h

@@ -0,0 +1,113 @@
+#pragma once
+#include <furi.h>
+#include <furi_hal.h>
+#include <furi_hal_usb.h>
+
+/* === START furi_hal_usb_i.h === */
+// https://github.com/flipperdevices/flipperzero-firmware/blob/03196fa11007c0f1e002cbb0b82102d8492456b5/targets/f7/furi_hal/furi_hal_usb_i.h#L5
+#define USB_EP0_SIZE 8
+
+enum UsbDevDescStr {
+    UsbDevLang = 0,
+    UsbDevManuf = 1,
+    UsbDevProduct = 2,
+    UsbDevSerial = 3,
+};
+/* ===   END furi_hal_usb_i.h === */
+
+void usb_mtp_init(void);
+void usb_mtp_deinit(void);
+void usb_mtp_wakeup(void);
+void usb_mtp_suspend(void);
+
+#define USB_EP0_SIZE 64
+#define USB_MTP_RX_EP 0x01
+#define USB_MTP_TX_EP 0x81
+#define USB_MTP_RX_EP_SIZE 64
+#define USB_MTP_TX_EP_SIZE 64
+
+static const struct usb_string_descriptor dev_manuf_desc = USB_STRING_DESC("Flipper Devices Inc.");
+static const struct usb_string_descriptor dev_prod_desc = USB_STRING_DESC("MTP Device");
+
+struct MtpDescriptor {
+    struct usb_config_descriptor config;
+    struct usb_interface_descriptor intf;
+    struct usb_endpoint_descriptor ep_rx;
+    struct usb_endpoint_descriptor ep_tx;
+} __attribute__((packed));
+
+static const struct usb_device_descriptor usb_mtp_dev_descr = {
+    .bLength = sizeof(struct usb_device_descriptor),
+    .bDescriptorType = USB_DTYPE_DEVICE,
+    .bcdUSB = VERSION_BCD(2, 0, 0),
+    .bDeviceClass = USB_CLASS_STILL_IMAGE, // MTP falls under Still Image class
+    .bDeviceSubClass = 1, // Subclass for MTP
+    .bDeviceProtocol = 1, // Protocol for MTP
+    .bMaxPacketSize0 = USB_EP0_SIZE,
+    .idVendor = 0x0483, // STMicroelectronics
+    .idProduct = 0x5741, // Custom Product ID
+    .bcdDevice = VERSION_BCD(1, 0, 0),
+    .iManufacturer = UsbDevManuf, // UsbDevManuf
+    .iProduct = UsbDevProduct, // UsbDevProduct
+    .iSerialNumber = UsbDevSerial, // UsbDevSerial
+    .bNumConfigurations = 1,
+};
+
+static const struct MtpDescriptor usb_mtp_cfg_descr = {
+    .config =
+        {
+            .bLength = sizeof(struct usb_config_descriptor),
+            .bDescriptorType = USB_DTYPE_CONFIGURATION,
+            .wTotalLength = sizeof(struct MtpDescriptor),
+            .bNumInterfaces = 1,
+            .bConfigurationValue = 1,
+            .iConfiguration = NO_DESCRIPTOR,
+            .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
+            .bMaxPower = USB_CFG_POWER_MA(100),
+        },
+    .intf =
+        {
+            .bLength = sizeof(struct usb_interface_descriptor),
+            .bDescriptorType = USB_DTYPE_INTERFACE,
+            .bInterfaceNumber = 0,
+            .bAlternateSetting = 0,
+            .bNumEndpoints = 2,
+            .bInterfaceClass = USB_CLASS_STILL_IMAGE,
+            .bInterfaceSubClass = 1, // Subclass for MTP
+            .bInterfaceProtocol = 1, // Protocol for MTP
+            .iInterface = NO_DESCRIPTOR,
+        },
+    .ep_rx =
+        {
+            .bLength = sizeof(struct usb_endpoint_descriptor),
+            .bDescriptorType = USB_DTYPE_ENDPOINT,
+            .bEndpointAddress = USB_MTP_RX_EP,
+            .bmAttributes = USB_EPTYPE_BULK,
+            .wMaxPacketSize = USB_MTP_RX_EP_SIZE,
+            .bInterval = 0,
+        },
+    .ep_tx =
+        {
+            .bLength = sizeof(struct usb_endpoint_descriptor),
+            .bDescriptorType = USB_DTYPE_ENDPOINT,
+            .bEndpointAddress = USB_MTP_TX_EP,
+            .bmAttributes = USB_EPTYPE_BULK,
+            .wMaxPacketSize = USB_MTP_TX_EP_SIZE,
+            .bInterval = 0,
+        },
+};
+
+FuriHalUsbInterface usb_mtp_interface = {
+    .init = usb_mtp_init,
+    .deinit = usb_mtp_deinit,
+    .wakeup = usb_mtp_wakeup,
+    .suspend = usb_mtp_suspend,
+
+    .dev_descr = (struct usb_device_descriptor*)&usb_mtp_dev_descr,
+
+    .str_manuf_descr = (void*)&dev_manuf_desc,
+    .str_prod_descr = (void*)&dev_prod_desc,
+    .str_serial_descr = NULL,
+
+    .cfg_descr = (void*)&usb_mtp_cfg_descr,
+};