summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-09-22 12:26:03 +0700
committerhathach <[email protected]>2025-09-22 13:10:22 +0700
commit6fa5268a9c013c9d38fc71649400d9ecc8c2dddf (patch)
tree756ed521d3804fce5e7edc3b6c0d1f7c0c1a28b9
parent4c818998d499a5a22c27ddfafc618e04ddcb823f (diff)
implement get object, close session
-rw-r--r--examples/device/mtp/src/mtp_fs_example.c165
-rw-r--r--src/class/mtp/mtp.h1
-rw-r--r--src/class/mtp/mtp_device.c116
-rw-r--r--src/class/mtp/mtp_device.h32
-rw-r--r--src/class/mtp/mtp_device_storage.h42
5 files changed, 90 insertions, 266 deletions
diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c
index 20d09508f..a1c45c6e4 100644
--- a/examples/device/mtp/src/mtp_fs_example.c
+++ b/examples/device/mtp/src/mtp_fs_example.c
@@ -30,10 +30,10 @@
#define MTPD_VOLUME_IDENTIFIER "volume"
//--------------------------------------------------------------------+
-// Device Info
+// Dataset
//--------------------------------------------------------------------+
-// device info string (including terminating null)
+//------------- device info -------------//
#define DEV_INFO_MANUFACTURER "TinyUSB"
#define DEV_INFO_MODEL "MTP Example"
#define DEV_INFO_VERSION "1.0"
@@ -41,6 +41,14 @@
#define DEV_PROP_FRIENDLY_NAME "TinyUSB MTP"
+//------------- storage info -------------//
+#define STORAGE_DESCRIPTRION { 'd', 'i', 's', 'k', 0 }
+#define VOLUME_IDENTIFIER { 'v', 'o', 'l', 0 }
+
+typedef MTP_STORAGE_INFO_STRUCT(TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTRION),
+ TU_ARRAY_SIZE(((uint16_t[])VOLUME_IDENTIFIER))
+) storage_info_t;
+
//--------------------------------------------------------------------+
// RAM FILESYSTEM
//--------------------------------------------------------------------+
@@ -77,12 +85,7 @@ static fs_object_info_t fs_objects[FS_MAX_NODES] = {
};
//------------- Storage Info -------------//
-#define STORAGE_DESCRIPTRION { 'd', 'i', 's', 'k', 0 }
-#define VOLUME_IDENTIFIER { 'v', 'o', 'l', 0 }
-typedef MTP_STORAGE_INFO_STRUCT(TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTRION),
- TU_ARRAY_SIZE(((uint16_t[])VOLUME_IDENTIFIER))
-) storage_info_t;
storage_info_t storage_info = {
.storage_type = MTP_STORAGE_TYPE_FIXED_RAM,
@@ -105,6 +108,7 @@ enum {
SUPPORTED_STORAGE_ID = 0x00010001u // physical = 1, logical = 1
};
+static bool is_session_opened = false;
//--------------------------------------------------------------------+
// OPERATING STATUS
@@ -160,14 +164,9 @@ unsigned int fs_get_object_count(void) {
int32_t tud_mtp_data_complete_cb(uint8_t idx, mtp_container_header_t* cmd_header, mtp_generic_container_t* resp_block, tusb_xfer_result_t xfer_result, uint32_t xferred_bytes) {
(void) idx;
- // switch (cmd_header->code) {
- // default: break;
- // }
resp_block->len = MTP_CONTAINER_HEADER_LENGTH;
resp_block->code = (xfer_result == XFER_RESULT_SUCCESS) ? MTP_RESP_OK : MTP_RESP_GENERAL_ERROR;
-
tud_mtp_response_send(resp_block);
-
return 0;
}
@@ -195,7 +194,24 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl
}
case MTP_OP_OPEN_SESSION:
- out_block->code = MTP_RESP_OK;
+ if (is_session_opened) {
+ //return MTP_RESP_SESSION_ALREADY_OPEN;
+ out_block->code = MTP_RESP_SESSION_ALREADY_OPEN;
+ }else {
+ out_block->code = MTP_RESP_OK;
+ }
+ is_session_opened = true;
+ tud_mtp_response_send(out_block);
+ break;
+
+ case MTP_OP_CLOSE_SESSION:
+ if (!is_session_opened) {
+ // return MTP_RESP_SESSION_NOT_OPEN;
+ out_block->code = MTP_RESP_SESSION_NOT_OPEN;
+ } else {
+ out_block->code = MTP_RESP_OK;
+ }
+ is_session_opened = false;
tud_mtp_response_send(out_block);
break;
@@ -272,13 +288,12 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl
}
case MTP_OP_GET_OBJECT_INFO: {
- const uint32_t object_handle = cmd_block->data[0];
- fs_object_info_t* obj = fs_object_get_from_handle(object_handle);
+ const uint32_t obj_handle = cmd_block->data[0];
+ fs_object_info_t* obj = fs_object_get_from_handle(obj_handle);
if (obj == NULL) {
- TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle);
return MTP_RESP_INVALID_OBJECT_HANDLE;
}
- mtp_object_info_header_t object_info_header = {
+ mtp_object_info_header_t obj_info_header = {
.storage_id = SUPPORTED_STORAGE_ID,
.object_format = MTP_OBJ_FORMAT_TEXT,
.protection_status = MTP_PROTECTION_STATUS_NO_PROTECTION,
@@ -295,7 +310,7 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl
.association_desc = 0,
.sequence_number = 0
};
- mtp_container_add_raw(out_block, &object_info_header, sizeof(object_info_header));
+ mtp_container_add_raw(out_block, &obj_info_header, sizeof(obj_info_header));
mtp_container_add_cstring(out_block, obj->name);
mtp_container_add_cstring(out_block, obj->created);
mtp_container_add_cstring(out_block, obj->modified);
@@ -305,6 +320,18 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl
break;
}
+ case MTP_OP_GET_OBJECT: {
+ const uint32_t obj_handle = cmd_block->data[0];
+ fs_object_info_t* obj = fs_object_get_from_handle(obj_handle);
+ if (obj == NULL) {
+ return MTP_RESP_INVALID_OBJECT_HANDLE;
+ }
+
+ mtp_container_add_raw(out_block, obj->data, obj->size);
+ tud_mtp_data_send(out_block);
+ break;
+ }
+
default: return MTP_RESP_OPERATION_NOT_SUPPORTED;
}
@@ -314,22 +341,12 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl
//--------------------------------------------------------------------+
// API
//--------------------------------------------------------------------+
-mtp_response_t tud_mtp_storage_close_session(uint32_t session_id) {
- if (session_id != _fs_operation.session_id) {
- TU_LOG1("ERR: Session %ld not open\r\n", session_id);
- return MTP_RESP_SESSION_NOT_OPEN;
- }
- _fs_operation.session_id = 0;
- TU_LOG1("Session closed\r\n");
- return MTP_RESP_OK;
-}
-
mtp_response_t tud_mtp_storage_format(uint32_t storage_id) {
if (_fs_operation.session_id == 0) {
TU_LOG1("ERR: Session not open\r\n");
return MTP_RESP_SESSION_NOT_OPEN;
}
- if (storage_id != STORAGE_ID(0x0001, 0x0001)) {
+ if (storage_id != SUPPORTED_STORAGE_ID) {
TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id);
return MTP_RESP_INVALID_STORAGE_ID;
}
@@ -341,45 +358,6 @@ mtp_response_t tud_mtp_storage_format(uint32_t storage_id) {
return MTP_RESP_OK;
}
-mtp_response_t tud_mtp_storage_association_get_object_handle(uint32_t storage_id, uint32_t parent_object_handle,
- uint32_t* next_child_handle) {
- fs_object_info_t* obj;
-
- if (_fs_operation.session_id == 0) {
- TU_LOG1("ERR: Session not open\r\n");
- return MTP_RESP_SESSION_NOT_OPEN;
- }
- // We just have one storage, same reply if querying all storages
- if (storage_id != 0xFFFFFFFF && storage_id != STORAGE_ID(0x0001, 0x0001)) {
- TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id);
- return MTP_RESP_INVALID_STORAGE_ID;
- }
-
- // Request for objects with no parent (0xFFFFFFFF) are considered root objects
- // Note: implementation may pass 0 as parent_object_handle
- if (parent_object_handle == 0xFFFFFFFF)
- parent_object_handle = 0;
-
- if (parent_object_handle != _fs_operation.traversal_parent) {
- _fs_operation.traversal_parent = parent_object_handle;
- _fs_operation.traversal_index = 0;
- }
-
- for (unsigned int i = _fs_operation.traversal_index; i < FS_MAX_NODES; i++) {
- obj = &fs_objects[i];
- if (obj->allocated && obj->parent == parent_object_handle) {
- _fs_operation.traversal_index = i + 1;
- *next_child_handle = obj->handle;
- TU_LOG1("Association %ld -> child %ld\r\n", parent_object_handle, obj->handle);
- return MTP_RESP_OK;
- }
- }
- TU_LOG1("Association traversal completed\r\n");
- _fs_operation.traversal_index = 0;
- *next_child_handle = 0;
- return MTP_RESP_OK;
-}
-
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) {
fs_object_info_t* obj = NULL;
@@ -389,7 +367,7 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p
return MTP_RESP_SESSION_NOT_OPEN;
}
// Accept command on default storage
- if (storage_id != 0xFFFFFFFF && storage_id != STORAGE_ID(0x0001, 0x0001)) {
+ if (storage_id != 0xFFFFFFFF && storage_id != SUPPORTED_STORAGE_ID) {
TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id);
return MTP_RESP_INVALID_STORAGE_ID;
}
@@ -480,55 +458,6 @@ mtp_response_t tud_mtp_storage_object_write(uint32_t object_handle, const uint8_
return MTP_RESP_OK;
}
-mtp_response_t tud_mtp_storage_object_size(uint32_t object_handle, uint32_t* size) {
- const fs_object_info_t* obj;
- obj = fs_object_get_from_handle(object_handle);
- if (obj == NULL) {
- TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle);
- return MTP_RESP_INVALID_OBJECT_HANDLE;
- }
- *size = obj->size;
- return MTP_RESP_OK;
-}
-
-mtp_response_t tud_mtp_storage_object_read(uint32_t object_handle, void* buffer, uint32_t buffer_size,
- uint32_t* read_count) {
- const fs_object_info_t* obj;
-
- obj = fs_object_get_from_handle(object_handle);
-
- if (obj == NULL) {
- TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle);
- return MTP_RESP_INVALID_OBJECT_HANDLE;
- }
- // It's not a requirement that this command is preceded by a read info
- if (object_handle != _fs_operation.read_handle) {
- TU_LOG1("ERR: Object %ld not open for read\r\n", object_handle);
- _fs_operation.read_handle = object_handle;
- _fs_operation.read_pos = 0;
- }
-
- if (obj->size - _fs_operation.read_pos > buffer_size) {
- TU_LOG1("Read object %ld: %ld bytes at offset %ld\r\n", object_handle, buffer_size, _fs_operation.read_pos);
- *read_count = buffer_size;
- if (_fs_operation.read_pos + buffer_size < FS_MAX_NODE_BYTES) {
- memcpy(buffer, &obj->data[_fs_operation.read_pos], *read_count);
- }
- _fs_operation.read_pos += *read_count;
- } else {
- TU_LOG1("Read object %ld: %ld bytes at offset %ld\r\n", object_handle, obj->size - _fs_operation.read_pos,
- _fs_operation.read_pos);
- *read_count = obj->size - _fs_operation.read_pos;
- if (_fs_operation.read_pos + *read_count < FS_MAX_NODE_BYTES) {
- memcpy(buffer, &obj->data[_fs_operation.read_pos], *read_count);
- }
- // Read operation completed
- _fs_operation.read_handle = 0;
- _fs_operation.read_pos = 0;
- }
- return MTP_RESP_OK;
-}
-
mtp_response_t tud_mtp_storage_object_move(uint32_t object_handle, uint32_t new_parent_object_handle) {
fs_object_info_t* obj;
diff --git a/src/class/mtp/mtp.h b/src/class/mtp/mtp.h
index 61adc29e4..c844b08ab 100644
--- a/src/class/mtp/mtp.h
+++ b/src/class/mtp/mtp.h
@@ -38,7 +38,6 @@
extern "C" {
#endif
-#define STORAGE_ID(physical_id, logical_id) ( (((uint32_t)physical_id & 0xFFFF) << 16) | ((uint32_t)logical_id & 0x0000FFFF) )
typedef uint16_t wchar16_t;
//--------------------------------------------------------------------+
diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c
index 22ef45cd9..ca594158e 100644
--- a/src/class/mtp/mtp_device.c
+++ b/src/class/mtp/mtp_device.c
@@ -79,14 +79,10 @@ typedef struct {
//--------------------------------------------------------------------+
// Checker
static mtp_phase_type_t mtpd_chk_generic(const char *func_name, const bool err_cd, const uint16_t ret_code, const char *message);
-static mtp_phase_type_t mtpd_chk_session_open(const char *func_name);
// MTP commands
static mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp);
static mtp_phase_type_t mtpd_handle_data(void);
-static mtp_phase_type_t mtpd_handle_cmd_close_session(void);
-static mtp_phase_type_t mtpd_handle_cmd_get_object(void);
-static mtp_phase_type_t mtpd_handle_dti_get_object(void);
static mtp_phase_type_t mtpd_handle_cmd_delete_object(void);
static mtp_phase_type_t mtpd_handle_cmd_send_object_info(void);
static mtp_phase_type_t mtpd_handle_dto_send_object_info(void);
@@ -272,6 +268,7 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
break;
}
+#if 0
case MTP_PHASE_DATA_IN:
p_mtp->xferred_len += xferred_bytes;
p_mtp->handled_len = p_mtp->xferred_len;
@@ -333,16 +330,17 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
} else if (p_mtp->handled_len == 0) {
// First data block includes container header + container data
TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out,
- (uint8_t*) p_container + p_mtp->xferred_len,
+ (uint8_t*) p_container + p_mtp->xferred_len,
(uint16_t)TU_MIN(p_mtp->total_len - p_mtp->xferred_len, CFG_MTP_EP_SIZE)));
} else {
// Successive data block includes only container data
TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out,
- ((uint8_t *)(&p_container->data)) + p_mtp->xferred_len - p_mtp->handled_len,
- (uint16_t)TU_MIN(p_mtp->total_len - p_mtp->xferred_len, CFG_MTP_EP_SIZE)));
+ ((uint8_t *)(&p_container->data)) + p_mtp->xferred_len - p_mtp->handled_len,
+ (uint16_t)TU_MIN(p_mtp->total_len - p_mtp->xferred_len, CFG_MTP_EP_SIZE)));
}
}
break;
+#endif
case MTP_PHASE_RESPONSE_QUEUED:
// response phase is complete -> prepare for new command
@@ -391,12 +389,16 @@ mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp) {
TU_LOG_DRV(" MTP command: MTP_OP_GET_DEVICE_INFO\n");
tud_mtp_device_info_t dev_info = {
.standard_version = 100,
- .mtp_vendor_extension_id = 0xFFFFFFFFU,
+ .mtp_vendor_extension_id = 6, // MTP specs say 0xFFFFFFFF but libMTP check for value 6
.mtp_version = 100,
+#ifdef CFG_TUD_MTP_DEVICEINFO_EXTENSIONS
.mtp_extensions = {
.count = sizeof(CFG_TUD_MTP_DEVICEINFO_EXTENSIONS),
.utf16 = { 0 }
},
+#else
+ .mtp_extensions = 0,
+#endif
.functional_mode = 0x0000,
.supported_operations = {
.count = TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS),
@@ -419,9 +421,11 @@ mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp) {
.arr = { CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS }
}
};
+#ifdef CFG_TUD_MTP_DEVICEINFO_EXTENSIONS
for (uint8_t i=0; i < dev_info.mtp_extensions.count; i++) {
dev_info.mtp_extensions.utf16[i] = (uint16_t)CFG_TUD_MTP_DEVICEINFO_EXTENSIONS[i];
}
+#endif
p_container->len = MTP_CONTAINER_HEADER_LENGTH + sizeof(tud_mtp_device_info_t);
p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK;
p_container->code = MTP_OP_GET_DEVICE_INFO;
@@ -437,7 +441,7 @@ mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp) {
case MTP_OP_CLOSE_SESSION:
TU_LOG_DRV(" MTP command: MTP_OP_CLOSE_SESSION\n");
- return mtpd_handle_cmd_close_session();
+ break;
case MTP_OP_GET_STORAGE_IDS:
TU_LOG_DRV(" MTP command: MTP_OP_GET_STORAGE_IDS\n");
@@ -457,7 +461,8 @@ mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp) {
case MTP_OP_GET_OBJECT:
TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT\n");
- return mtpd_handle_cmd_get_object();
+ break;
+
case MTP_OP_DELETE_OBJECT:
TU_LOG_DRV(" MTP command: MTP_OP_DELETE_OBJECT\n");
return mtpd_handle_cmd_delete_object();
@@ -495,9 +500,6 @@ mtp_phase_type_t mtpd_handle_data(void)
switch(p_container->code)
{
- case MTP_OP_GET_OBJECT:
- TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT-DATA_IN\n");
- return mtpd_handle_dti_get_object();
case MTP_OP_SEND_OBJECT_INFO:
TU_LOG_DRV(" MTP command: MTP_OP_SEND_OBJECT_INFO-DATA_OUT\n");
return mtpd_handle_dto_send_object_info();
@@ -511,79 +513,6 @@ mtp_phase_type_t mtpd_handle_data(void)
return true;
}
-
-mtp_phase_type_t mtpd_handle_cmd_close_session(void)
-{
- mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
- uint32_t session_id = p_container->data[0];
-
- mtp_response_t res = tud_mtp_storage_close_session(session_id);
-
- _mtpd_itf.session_id = session_id;
-
- p_container->len = MTP_CONTAINER_HEADER_LENGTH;
- p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK;
- p_container->code = res;
-
- return MTP_PHASE_RESPONSE;
-}
-
-mtp_phase_type_t mtpd_handle_cmd_get_object(void)
-{
- mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
- _mtpd_get_object_handle = p_container->data[0];
-
- // Continue with DATA-IN
- return mtpd_handle_dti_get_object();
-}
-
-mtp_phase_type_t mtpd_handle_dti_get_object(void)
-{
- mtp_response_t res;
- mtp_phase_type_t phase;
- uint32_t file_size = 0;
- mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
- res = tud_mtp_storage_object_size(_mtpd_get_object_handle, &file_size);
- if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) {
- return phase;
- }
- p_container->len = MTP_CONTAINER_HEADER_LENGTH + file_size;
- p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK;
- p_container->code = MTP_OP_GET_OBJECT;
-
- uint32_t buffer_size;
- uint32_t read_count;
- // Data block must be multiple of EP size
- if (_mtpd_itf.handled_len == 0)
- {
- // First data block: include container header
- buffer_size = ((MTP_MAX_PACKET_SIZE + MTP_CONTAINER_HEADER_LENGTH) / CFG_MTP_EP_SIZE) * CFG_MTP_EP_SIZE - MTP_CONTAINER_HEADER_LENGTH;
- res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&p_container->data, buffer_size, &read_count);
- if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) {
- return phase;
- }
- _mtpd_itf.queued_len = MTP_CONTAINER_HEADER_LENGTH + read_count;
- }
- else
- {
- // Successive data block: consider only container data
- buffer_size = (MTP_MAX_PACKET_SIZE / CFG_MTP_EP_SIZE) * CFG_MTP_EP_SIZE;
- res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&p_container->data, buffer_size, &read_count);
- if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) {
- return phase;
- }
- _mtpd_itf.queued_len = read_count;
- }
-
- // File completed
- if (read_count < buffer_size)
- {
- tud_mtp_storage_object_done();
- }
-
- return MTP_PHASE_DATA_IN;
-}
-
mtp_phase_type_t mtpd_handle_cmd_delete_object(void)
{
mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
@@ -689,21 +618,6 @@ mtp_phase_type_t mtpd_handle_cmd_format_store(void)
//--------------------------------------------------------------------+
// Checker
//--------------------------------------------------------------------+
-mtp_phase_type_t mtpd_chk_session_open(const char *func_name)
-{
- (void)func_name;
- mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
- if (_mtpd_itf.session_id == 0)
- {
- TU_LOG_DRV(" MTP error: %s session not open\n", func_name);
- p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK;
- p_container->code = MTP_RESP_SESSION_NOT_OPEN;
- p_container->len = MTP_CONTAINER_HEADER_LENGTH;
- return MTP_PHASE_RESPONSE;
- }
- return MTP_PHASE_NONE;
-}
-
mtp_phase_type_t mtpd_chk_generic(const char *func_name, const bool err_cd, const uint16_t ret_code, const char *message)
{
(void)func_name;
diff --git a/src/class/mtp/mtp_device.h b/src/class/mtp/mtp_device.h
index 538e3c8d0..b85b1706e 100644
--- a/src/class/mtp/mtp_device.h
+++ b/src/class/mtp/mtp_device.h
@@ -44,7 +44,7 @@ typedef struct {
// 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_TYPEDEF(_extension_nchars, _op_count, _event_count, _devprop_count, _capture_count, _playback_count) \
+#define MTP_DEVICE_INFO_STRUCT(_extension_nchars, _op_count, _event_count, _devprop_count, _capture_count, _playback_count) \
struct TU_ATTR_PACKED { \
uint16_t standard_version; \
uint32_t mtp_vendor_extension_id; \
@@ -59,11 +59,34 @@ typedef struct {
/* string fields will be added using append function */ \
}
-typedef MTP_DEVICE_INFO_TYPEDEF(
- sizeof(CFG_TUD_MTP_DEVICEINFO_EXTENSIONS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS),
+#define MTP_DEVICE_INFO_NO_EXTENSION_STRUCT(_op_count, _event_count, _devprop_count, _capture_count, _playback_count) \
+ struct TU_ATTR_PACKED { \
+ uint16_t standard_version; \
+ uint32_t mtp_vendor_extension_id; \
+ uint16_t mtp_version; \
+ uint8_t mtp_extensions; \
+ uint16_t functional_mode; \
+ mtp_auint16_t(_op_count) supported_operations; \
+ mtp_auint16_t(_event_count) supported_events; \
+ mtp_auint16_t(_devprop_count) supported_device_properties; \
+ mtp_auint16_t(_capture_count) capture_formats; \
+ mtp_auint16_t(_playback_count) playback_formats; \
+ /* string fields will be added using append function */ \
+ }
+
+#ifdef CFG_TUD_MTP_DEVICEINFO_EXTENSIONS
+ typedef MTP_DEVICE_INFO_STRUCT(
+ sizeof(CFG_TUD_MTP_DEVICEINFO_EXTENSIONS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS),
+ TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES),
+ TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS)
+ ) tud_mtp_device_info_t;
+#else
+ typedef MTP_DEVICE_INFO_NO_EXTENSION_STRUCT(
+ TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS),
TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES),
TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS)
) tud_mtp_device_info_t;
+#endif
//--------------------------------------------------------------------+
// Application API
@@ -76,7 +99,8 @@ bool tud_mtp_response_send(mtp_generic_container_t* resp_block);
// Application Callbacks
//--------------------------------------------------------------------+
-// Invoked when new command is received
+// Invoked when new command is received. Application fill the out_block with either DATA or RESPONSE container
+// return MTP response code
int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_block, mtp_generic_container_t* out_block);
// Invoked when data phase is complete
diff --git a/src/class/mtp/mtp_device_storage.h b/src/class/mtp/mtp_device_storage.h
index 29d4b0bd5..30038978f 100644
--- a/src/class/mtp/mtp_device_storage.h
+++ b/src/class/mtp/mtp_device_storage.h
@@ -54,63 +54,21 @@
* Depending on the application, the handle could be also be the file name or a tag (i.e. host-only file access)
*/
-
-// Initialize MTP storage subsystem
-//
-// The function shall check if the session is already opened and, in case, set session_id to the
-// ID of the current session.
-
-// Close an open session
-mtp_response_t tud_mtp_storage_close_session(uint32_t session_id);
-
// Format the specified storage
mtp_response_t tud_mtp_storage_format(uint32_t storage_id);
-// Traverse the given parent object handle and return a child handle for each call
-//
-// If the parent object has not been opened (or closed before) the function returns the first handle.
-// When next_child_handle is 0 all the handles have been listed.
-// TODO: traverse by ObjectFormatCode and ObjectHandle association. For now they are unsupported.
-mtp_response_t tud_mtp_storage_association_get_object_handle(uint32_t session_handle, uint32_t parent_object_handle, uint32_t *next_child_handle);
-
// 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);
-// Get object information related to a given object handle
-//
-// The structure info shall be filled according to MTP specifications. Note that
-// in addition to filling the fixed mtp_object_info_t structure, the caller must add the following fields via
-// library calls
-// - Filename (string, use tud_mtp_gct_append_wstring)
-// - Date created (string, use tud_gct_append_date or empty string)
-// - Date modified (string, use tud_gct_append_date or empty string)
-// - Keywords (string containing list of kw, separated by space, use tud_mtp_gct_append_wstring)
-// Note that the variable information (e.g. wstring file name, dates and tags shall be written by using the library functions)
-mtp_response_t tud_mtp_storage_object_read_info(uint32_t object_handle, mtp_object_info_header_t *info);
-
-// Get the object size.
-//
-// The object may be already open when this function is called.
-// The implementation shall not assume a specific call order between this function and tud_mtp_storage_object_read.
-// The function may leave the file open.
-mtp_response_t tud_mtp_storage_object_size(uint32_t object_handle, uint32_t *size);
-
// 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);
-// Get object data
-//
-// The function shall open the object for reading if not already open.
-// The amount of data returned shall be the given size parameter.
-// read_count shall contain the effective number of bytes written. Iteration is terminated when read_count < buffer_size.
-mtp_response_t tud_mtp_storage_object_read(uint32_t object_handle, void *buffer, uint32_t buffer_size, uint32_t *read_count);
-
// 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);