diff options
| author | hathach <[email protected]> | 2025-09-22 12:26:03 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2025-09-22 13:10:22 +0700 |
| commit | 6fa5268a9c013c9d38fc71649400d9ecc8c2dddf (patch) | |
| tree | 756ed521d3804fce5e7edc3b6c0d1f7c0c1a28b9 /src | |
| parent | 4c818998d499a5a22c27ddfafc618e04ddcb823f (diff) | |
implement get object, close session
Diffstat (limited to 'src')
| -rw-r--r-- | src/class/mtp/mtp.h | 1 | ||||
| -rw-r--r-- | src/class/mtp/mtp_device.c | 116 | ||||
| -rw-r--r-- | src/class/mtp/mtp_device.h | 32 | ||||
| -rw-r--r-- | src/class/mtp/mtp_device_storage.h | 42 |
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); |
