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);