Skip to content

Commit

Permalink
chore: mtp
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex4386 committed Jun 3, 2024
1 parent 4b632c0 commit e3b83f3
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/scenes/mtp/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "../../main.h"
#include "main.h"
#include <demo_app_icons.h>
#include "usb.h"

#define THIS_SCENE MTP

Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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 changes: 6 additions & 0 deletions src/scenes/mtp/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
97 changes: 97 additions & 0 deletions src/scenes/mtp/usb.c
Original file line number Diff line number Diff line change
@@ -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 changes: 113 additions & 0 deletions src/scenes/mtp/usb.h
Original file line number Diff line number Diff line change
@@ -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,
};

0 comments on commit e3b83f3

Please sign in to comment.