mirror of
https://github.com/hathach/tinyusb.git
synced 2026-02-04 23:35:46 +00:00
implement control request
This commit is contained in:
@ -23,7 +23,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "class/mtp/mtp_device_storage.h"
|
||||
#include "tusb.h"
|
||||
#include "tinyusb_logo_png.h"
|
||||
|
||||
@ -188,6 +187,40 @@ static inline uint8_t* fs_malloc(size_t size) {
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Control Request callback
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_mtp_request_cancel_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
mtp_request_reset_cancel_data_t cancel_data;
|
||||
memcpy(&cancel_data, cb_data->buf, sizeof(cancel_data));
|
||||
(void) cancel_data.code;
|
||||
(void ) cancel_data.transaction_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invoked when received Device Reset request
|
||||
// return false to stall the request
|
||||
bool tud_mtp_request_device_reset_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invoked when received Get Extended Event request. Application fill callback data's buffer for response
|
||||
// return negative to stall the request
|
||||
int32_t tud_mtp_request_get_extended_event_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return false; // not implemented yet
|
||||
}
|
||||
|
||||
// Invoked when received Get DeviceStatus request. Application fill callback data's buffer for response
|
||||
// return negative to stall the request
|
||||
int32_t tud_mtp_request_get_device_status_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
uint16_t* buf16 = (uint16_t*)(uintptr_t) cb_data->buf;
|
||||
buf16[0] = 4; // length
|
||||
buf16[1] = MTP_RESP_OK; // status
|
||||
return 4;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Bulk Only Protocol
|
||||
//--------------------------------------------------------------------+
|
||||
@ -531,9 +564,3 @@ int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return 0; // nothing to do
|
||||
}
|
||||
|
||||
void tud_mtp_storage_cancel(void) {
|
||||
}
|
||||
|
||||
void tud_mtp_storage_reset(void) {
|
||||
}
|
||||
|
||||
@ -93,6 +93,7 @@
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_MTP 1
|
||||
#define CFG_TUD_MTP_EP_BUFSIZE 512
|
||||
#define CFG_TUD_MTP_EP_CONTROL_BUFSIZE 16 // should be enough to hold data in MTP control request
|
||||
|
||||
//------------- MTP device info -------------//
|
||||
#define CFG_TUD_MTP_DEVICEINFO_EXTENSIONS "microsoft.com: 1.0; "
|
||||
@ -131,10 +132,6 @@
|
||||
MTP_OBJ_FORMAT_TEXT, \
|
||||
MTP_OBJ_FORMAT_PNG
|
||||
|
||||
#define CFG_TUD_MANUFACTURER "TinyUsb Manufacturer"
|
||||
#define CFG_TUD_MODEL "TinyUsb Device"
|
||||
#define CFG_MTP_INTERFACE (CFG_TUD_MODEL " MTP")
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -140,10 +140,10 @@ enum {
|
||||
char const *string_desc_arr[] =
|
||||
{
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
CFG_TUD_MANUFACTURER, // 1: Manufacturer
|
||||
CFG_TUD_MODEL, // 2: Product
|
||||
"TinyUsb", // 1: Manufacturer
|
||||
"TinyUsb Device", // 2: Product
|
||||
NULL, // 3: Serials will use unique ID if possible
|
||||
CFG_MTP_INTERFACE, // 4: MTP Interface
|
||||
"TinyUSBB MTP", // 4: MTP Interface
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32 + 1];
|
||||
@ -168,7 +168,9 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
|
||||
if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *str = string_desc_arr[index];
|
||||
|
||||
|
||||
@ -38,8 +38,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint16_t wchar16_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Media Transfer Protocol Class Constant
|
||||
//--------------------------------------------------------------------+
|
||||
@ -759,15 +757,10 @@ typedef struct TU_ATTR_PACKED {
|
||||
};
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t wLength;
|
||||
uint16_t code;
|
||||
} mtp_device_status_res_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t object_handle;
|
||||
uint32_t storage_id;
|
||||
uint32_t parent_object_handle;
|
||||
} mtp_basic_object_info_t;
|
||||
uint32_t transaction_id;
|
||||
} mtp_request_reset_cancel_data_t;
|
||||
TU_VERIFY_STATIC(sizeof(mtp_request_reset_cancel_data_t) == 6, "size is not correct");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Container helper function
|
||||
|
||||
@ -31,12 +31,11 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// INCLUDE
|
||||
//--------------------------------------------------------------------+
|
||||
#include "device/dcd.h" // for faking dcd_event_xfer_complete
|
||||
#include "device/dcd.h"
|
||||
#include "device/usbd.h"
|
||||
#include "device/usbd_pvt.h"
|
||||
|
||||
#include "mtp_device.h"
|
||||
#include "mtp_device_storage.h"
|
||||
|
||||
// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
|
||||
#ifndef CFG_TUD_MTP_LOG_LEVEL
|
||||
@ -45,7 +44,45 @@
|
||||
|
||||
#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_MTP_LOG_LEVEL, __VA_ARGS__)
|
||||
|
||||
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
//--------------------------------------------------------------------+
|
||||
// Weak stubs: invoked if no strong implementation is available
|
||||
//--------------------------------------------------------------------+
|
||||
TU_ATTR_WEAK bool tud_mtp_request_cancel_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return false;
|
||||
}
|
||||
TU_ATTR_WEAK bool tud_mtp_request_device_reset_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return false;
|
||||
}
|
||||
TU_ATTR_WEAK int32_t tud_mtp_request_get_extended_event_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return -1;
|
||||
}
|
||||
TU_ATTR_WEAK int32_t tud_mtp_request_get_device_status_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return -1;
|
||||
}
|
||||
TU_ATTR_WEAK bool tud_mtp_request_vendor_cb(tud_mtp_request_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return false;
|
||||
}
|
||||
TU_ATTR_WEAK int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t * cb_data) {
|
||||
(void) cb_data;
|
||||
return -1;
|
||||
}
|
||||
TU_ATTR_WEAK int32_t tud_mtp_data_xfer_cb(tud_mtp_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return -1;
|
||||
}
|
||||
TU_ATTR_WEAK int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return -1;
|
||||
}
|
||||
TU_ATTR_WEAK int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) {
|
||||
(void) cb_data;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// STRUCT
|
||||
@ -66,6 +103,8 @@ typedef struct {
|
||||
uint32_t session_id;
|
||||
mtp_container_command_t command;
|
||||
mtp_container_header_t io_header;
|
||||
|
||||
TU_ATTR_ALIGNED(4) uint8_t control_buf[CFG_TUD_MTP_EP_CONTROL_BUFSIZE];
|
||||
} mtpd_interface_t;
|
||||
|
||||
typedef struct {
|
||||
@ -76,16 +115,10 @@ typedef struct {
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL FUNCTION DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
static void process_cmd(mtpd_interface_t* p_mtp, tud_mtp_cb_data_t* cb_data);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MTP variable declaration
|
||||
//--------------------------------------------------------------------+
|
||||
static mtpd_interface_t _mtpd_itf;
|
||||
CFG_TUD_MEM_SECTION static mtpd_epbuf_t _mtpd_epbuf;
|
||||
|
||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN static mtp_device_status_res_t _mtpd_device_status_res;
|
||||
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN static mtp_basic_object_info_t _mtpd_soi;
|
||||
static void preprocess_cmd(mtpd_interface_t* p_mtp, tud_mtp_cb_data_t* cb_data);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Debug
|
||||
@ -226,7 +259,6 @@ bool tud_mtp_event_send(mtp_event_t* event) {
|
||||
//--------------------------------------------------------------------+
|
||||
void mtpd_init(void) {
|
||||
tu_memclr(&_mtpd_itf, sizeof(mtpd_interface_t));
|
||||
tu_memclr(&_mtpd_soi, sizeof(mtp_basic_object_info_t));
|
||||
}
|
||||
|
||||
bool mtpd_deinit(void) {
|
||||
@ -236,8 +268,6 @@ bool mtpd_deinit(void) {
|
||||
void mtpd_reset(uint8_t rhport) {
|
||||
(void) rhport;
|
||||
tu_memclr(&_mtpd_itf, sizeof(mtpd_interface_t));
|
||||
tu_memclr(&_mtpd_epbuf, sizeof(mtpd_epbuf_t));
|
||||
tu_memclr(&_mtpd_soi, sizeof(mtp_basic_object_info_t));
|
||||
}
|
||||
|
||||
uint16_t mtpd_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16_t max_len) {
|
||||
@ -264,7 +294,6 @@ uint16_t mtpd_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16
|
||||
|
||||
// Open endpoint pair
|
||||
TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(ep_desc), 2, TUSB_XFER_BULK, &p_mtp->ep_out, &p_mtp->ep_in), 0);
|
||||
|
||||
TU_ASSERT(prepare_new_command(p_mtp), 0);
|
||||
|
||||
return mtpd_itf_size;
|
||||
@ -274,40 +303,63 @@ uint16_t mtpd_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool mtpd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
|
||||
if (stage != CONTROL_STAGE_SETUP) {
|
||||
return true; // nothing to do with DATA & ACK stage
|
||||
}
|
||||
mtpd_interface_t* p_mtp = &_mtpd_itf;
|
||||
tud_mtp_request_cb_data_t cb_data = {
|
||||
.idx = 0,
|
||||
.stage = stage,
|
||||
.request = request,
|
||||
.buf = p_mtp->control_buf,
|
||||
.bufsize = tu_le16toh(request->wLength),
|
||||
};
|
||||
|
||||
switch (request->bRequest) {
|
||||
case MTP_REQ_CANCEL:
|
||||
TU_LOG_DRV(" MTP request: MTP_REQ_CANCEL\n");
|
||||
tud_mtp_storage_cancel();
|
||||
TU_LOG_DRV(" MTP request: Cancel\n");
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
return tud_control_xfer(rhport, request, p_mtp->control_buf, CFG_TUD_MTP_EP_CONTROL_BUFSIZE);
|
||||
} else if (stage == CONTROL_STAGE_ACK) {
|
||||
return tud_mtp_request_cancel_cb(&cb_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case MTP_REQ_GET_EXT_EVENT_DATA:
|
||||
TU_LOG_DRV(" MTP request: MTP_REQ_GET_EXT_EVENT_DATA\n");
|
||||
TU_LOG_DRV(" MTP request: Get Extended Event Data\n");
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
const int32_t len = tud_mtp_request_get_extended_event_cb(&cb_data);
|
||||
TU_VERIFY(len > 0);
|
||||
return tud_control_xfer(rhport,request, p_mtp->control_buf, (uint16_t) len);
|
||||
}
|
||||
break;
|
||||
|
||||
case MTP_REQ_RESET:
|
||||
TU_LOG_DRV(" MTP request: MTP_REQ_RESET\n");
|
||||
tud_mtp_storage_reset();
|
||||
// Prepare for a new command
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, _mtpd_epbuf.buf, CFG_TUD_MTP_EP_BUFSIZE));
|
||||
TU_LOG_DRV(" MTP request: Device Reset\n");
|
||||
// used by the host to return the Still Image Capture Device to the Idle state after the Bulk-pipe has stalled
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
// clear stalled
|
||||
if (usbd_edpt_stalled(rhport, p_mtp->ep_out)) {
|
||||
usbd_edpt_clear_stall(rhport, p_mtp->ep_out);
|
||||
}
|
||||
if (usbd_edpt_stalled(rhport, p_mtp->ep_in)) {
|
||||
usbd_edpt_clear_stall(rhport, p_mtp->ep_in);
|
||||
}
|
||||
} else if (stage == CONTROL_STAGE_ACK) {
|
||||
prepare_new_command(p_mtp);
|
||||
return tud_mtp_request_device_reset_cb(&cb_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case MTP_REQ_GET_DEVICE_STATUS: {
|
||||
TU_LOG_DRV(" MTP request: MTP_REQ_GET_DEVICE_STATUS\n");
|
||||
uint16_t len = 4;
|
||||
_mtpd_device_status_res.wLength = len;
|
||||
// Cancel is synchronous, always answer OK
|
||||
_mtpd_device_status_res.code = MTP_RESP_OK;
|
||||
TU_ASSERT(tud_control_xfer(rhport, request, (uint8_t *)&_mtpd_device_status_res , len));
|
||||
TU_LOG_DRV(" MTP request: Get Device Status\n");
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
const int32_t len = tud_mtp_request_get_device_status_cb(&cb_data);
|
||||
TU_VERIFY(len > 0);
|
||||
return tud_control_xfer(rhport, request, p_mtp->control_buf, (uint16_t) len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TU_LOG_DRV(" MTP request: invalid request\r\n");
|
||||
return false; // stall unsupported request
|
||||
return tud_mtp_request_vendor_cb(&cb_data);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -354,7 +406,7 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
TU_VERIFY(ep_addr == p_mtp->ep_out && p_container->header.type == MTP_CONTAINER_TYPE_COMMAND_BLOCK);
|
||||
memcpy(&p_mtp->command, p_container, sizeof(mtp_container_command_t)); // save new command
|
||||
p_container->header.len = sizeof(mtp_container_header_t); // default container to header only
|
||||
process_cmd(p_mtp, &cb_data);
|
||||
preprocess_cmd(p_mtp, &cb_data);
|
||||
if (tud_mtp_command_received_cb(&cb_data) < 0) {
|
||||
p_mtp->phase = MTP_PHASE_ERROR;
|
||||
}
|
||||
@ -435,7 +487,7 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// pre-processed commands
|
||||
void process_cmd(mtpd_interface_t* p_mtp, tud_mtp_cb_data_t* cb_data) {
|
||||
void preprocess_cmd(mtpd_interface_t* p_mtp, tud_mtp_cb_data_t* cb_data) {
|
||||
switch (p_mtp->command.code) {
|
||||
case MTP_OP_GET_DEVICE_INFO: {
|
||||
tud_mtp_device_info_t dev_info = {
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// callback data for Bulk Only Transfer (BOT) protocol
|
||||
typedef struct {
|
||||
uint8_t idx; // mtp instance
|
||||
const mtp_container_command_t* command_container;
|
||||
@ -45,6 +46,16 @@ typedef struct {
|
||||
uint32_t total_xferred_bytes; // number of bytes transferred so far in this phase
|
||||
} tud_mtp_cb_data_t;
|
||||
|
||||
// callback data for Control requests
|
||||
typedef struct {
|
||||
uint8_t idx;
|
||||
uint8_t stage; // control stage
|
||||
const tusb_control_request_t* request;
|
||||
// buffer for data stage
|
||||
uint8_t* buf;
|
||||
uint16_t bufsize;
|
||||
} tud_mtp_request_cb_data_t;
|
||||
|
||||
// Number of supported operations, events, device properties, capture formats, playback formats
|
||||
// and max number of characters for strings manufacturer, model, device_version, serial_number
|
||||
#define MTP_DEVICE_INFO_STRUCT(_extension_nchars, _op_count, _event_count, _devprop_count, _capture_count, _playback_count) \
|
||||
@ -89,24 +100,47 @@ bool tud_mtp_event_send(mtp_event_t* event);
|
||||
//--------------------------------------------------------------------+
|
||||
// Control request Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
// bool tud_mtp_control_xfer_cb(uint8_t idx, uint8_t stage, tusb_control_request_t const *p_request);
|
||||
|
||||
// Invoked when received Cancel request. Data is available in callback data's buffer
|
||||
// return false to stall the request
|
||||
bool tud_mtp_request_cancel_cb(tud_mtp_request_cb_data_t* cb_data);
|
||||
|
||||
// Invoked when received Device Reset request
|
||||
// return false to stall the request
|
||||
bool tud_mtp_request_device_reset_cb(tud_mtp_request_cb_data_t* cb_data);
|
||||
|
||||
// Invoked when received Get Extended Event request. Application fill callback data's buffer for response
|
||||
// return negative to stall the request
|
||||
int32_t tud_mtp_request_get_extended_event_cb(tud_mtp_request_cb_data_t* cb_data);
|
||||
|
||||
// Invoked when received Get DeviceStatus request. Application fill callback data's buffer for response
|
||||
// return negative to stall the request
|
||||
int32_t tud_mtp_request_get_device_status_cb(tud_mtp_request_cb_data_t* cb_data);
|
||||
|
||||
// Invoked when received vendor-specific request not in the above standard MTP requests
|
||||
// return false to stall the request
|
||||
bool tud_mtp_request_vendor_cb(tud_mtp_request_cb_data_t* cb_data);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Bulk only protocol Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* Invoked when new command is received. Application fill the cb_data->reply with either DATA or RESPONSE and call
|
||||
* tud_mtp_data_send() or tud_mtp_response_send(). Return negative to stall the endpoints
|
||||
*/
|
||||
// Invoked when new command is received. Application fill the cb_data->io_container and call tud_mtp_data_send() or
|
||||
// tud_mtp_response_send() for Data or Response phase.
|
||||
// Return negative to stall the endpoints
|
||||
int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t * cb_data);
|
||||
|
||||
// Invoked when a data packet is transferred, and more data is expected
|
||||
// Invoked when a data packet is transferred. If data spans over multiple packets, application can use
|
||||
// total_xferred_bytes and io_container's payload_bytes to determine the offset and remaining bytes to be transferred.
|
||||
// Return negative to stall the endpoints
|
||||
int32_t tud_mtp_data_xfer_cb(tud_mtp_cb_data_t* cb_data);
|
||||
|
||||
// Invoked when all bytes in DATA phase is complete. A response packet is expected
|
||||
// Return negative to stall the endpoints
|
||||
int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data);
|
||||
|
||||
// Invoked when response phase is complete
|
||||
// Return negative to stall the endpoints
|
||||
int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2025 Ennebi Elettronica (https://ennebielettronica.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_MTP_DEVICE_STORAGE_H_
|
||||
#define _TUSB_MTP_DEVICE_STORAGE_H_
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "mtp.h"
|
||||
|
||||
#if (CFG_TUD_ENABLED && CFG_TUD_MTP)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Storage Application Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/*
|
||||
* The entire MTP functionality is based on object handles, as described in MTP Specs v. 1.1 under 3.4.1.
|
||||
* The major weakness of the protocol is that those handles are supposed to be unique within a session
|
||||
* and for every enumerated object. There is no specified lifetime limit or way to control the expiration:
|
||||
* once given, they have to persist for an indefinite time and number of iterations.
|
||||
* If the filesystem does not provide unique persistent object handle for every entry, the best approach
|
||||
* would be to keep a full association between generated handles and full file paths. The suggested
|
||||
* approach with memory constrained devices is to keep a hard ID associated with each file or a volatile
|
||||
* ID generated on the fly and invalidated on each operation that may rearrange the order.
|
||||
* In order to invalidate existing IDS, it might be necessary to invalidate the whole session from
|
||||
* the device side.
|
||||
* Depending on the application, the handle could be also be the file name or a tag (i.e. host-only file access)
|
||||
*/
|
||||
|
||||
// Format the specified storage
|
||||
mtp_response_t tud_mtp_storage_format(uint32_t storage_id);
|
||||
|
||||
// Called with the creation of a new object is requested.
|
||||
// The handle of the new object shall be returned in new_object_handle.
|
||||
// The structure info contains the information to be used for file creation, as passted by the host.
|
||||
// Note that the variable information (e.g. wstring file name, dates and tags shall be retrieved by using the library functions)
|
||||
mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t parent_object, uint32_t *new_object_handle, const mtp_object_info_header_t *info);
|
||||
|
||||
// Write object data
|
||||
//
|
||||
// The function shall open the object for writing if not already open.
|
||||
// The binary data shall be written to the file in full before this function is returned.
|
||||
mtp_response_t tud_mtp_storage_object_write(uint32_t object_handle, const uint8_t *buffer, uint32_t buffer_size);
|
||||
|
||||
// Move an object to a new parent
|
||||
mtp_response_t tud_mtp_storage_object_move(uint32_t object_handle, uint32_t new_parent_object_handle);
|
||||
|
||||
// Delete the specified object
|
||||
mtp_response_t tud_mtp_storage_object_delete(uint32_t object_handle);
|
||||
|
||||
// Issued when IO operation has been terminated (e.g. read, traverse), close open file handles
|
||||
void tud_mtp_storage_object_done(void);
|
||||
|
||||
// Cancel any pending operation. Current operation shall be discarded.
|
||||
void tud_mtp_storage_cancel(void);
|
||||
|
||||
// Restore the operation out of reset. Cancel any pending operation and close the session.
|
||||
void tud_mtp_storage_reset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CFG_TUD_ENABLED && CFG_TUD_MTP */
|
||||
|
||||
#endif /* _TUSB_MTP_DEVICE_STORAGE_H_ */
|
||||
Reference in New Issue
Block a user