summaryrefslogtreecommitdiff
path: root/src/class
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 /src/class
parent4c818998d499a5a22c27ddfafc618e04ddcb823f (diff)
implement get object, close session
Diffstat (limited to 'src/class')
-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
4 files changed, 43 insertions, 148 deletions
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);