diff options
| author | HiFiPhile <[email protected]> | 2026-06-22 21:30:58 +0200 |
|---|---|---|
| committer | HiFiPhile <[email protected]> | 2026-06-22 21:30:58 +0200 |
| commit | 693cdce08e14833f26f4e8a1f26e4fd546be4c35 (patch) | |
| tree | 7667d2223dc32d9f21b5b60ab200e64ed46e3e20 /examples/device/mtp/src/mtp_fs_example.c | |
| parent | 41e9eaa65a935136085d78ec4b99c81ff991b560 (diff) | |
| parent | cd3561bf158afd5a5718904b8139a338d1e3b67c (diff) | |
Merge remote-tracking branch 'tinyusb/master' into pr-osal-spin-deinit
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'examples/device/mtp/src/mtp_fs_example.c')
| -rw-r--r-- | examples/device/mtp/src/mtp_fs_example.c | 162 |
1 files changed, 108 insertions, 54 deletions
diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c index 5f56ca24d..b7d062c64 100644 --- a/examples/device/mtp/src/mtp_fs_example.c +++ b/examples/device/mtp/src/mtp_fs_example.c @@ -39,12 +39,15 @@ #define DEV_PROP_FRIENDLY_NAME "TinyUSB MTP" //------------- storage info -------------// -#define STORAGE_DESCRIPTRION { 'd', 'i', 's', 'k', 0 } +#define STORAGE_DESCRIPTION { '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; +enum { + STORAGE_DESC_LEN = TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTION), + VOLUME_ID_LEN = TU_ARRAY_SIZE((uint16_t[])VOLUME_IDENTIFIER) +}; + +typedef MTP_STORAGE_INFO_STRUCT(STORAGE_DESC_LEN, VOLUME_ID_LEN) storage_info_t; storage_info_t storage_info = { #ifdef CFG_EXAMPLE_MTP_READONLY @@ -59,11 +62,11 @@ storage_info_t storage_info = { .free_space_in_bytes = 0, // calculated at runtime .free_space_in_objects = 0, // calculated at runtime .storage_description = { - .count = (TU_FIELD_SZIE(storage_info_t, storage_description)-1) / sizeof(uint16_t), - .utf16 = STORAGE_DESCRIPTRION + .count = (TU_FIELD_SIZE(storage_info_t, storage_description)-1) / sizeof(uint16_t), + .utf16 = STORAGE_DESCRIPTION }, .volume_identifier = { - .count = (TU_FIELD_SZIE(storage_info_t, volume_identifier)-1) / sizeof(uint16_t), + .count = (TU_FIELD_SIZE(storage_info_t, volume_identifier)-1) / sizeof(uint16_t), .utf16 = VOLUME_IDENTIFIER } }; @@ -111,8 +114,8 @@ static fs_file_t fs_objects[FS_MAX_FILE_COUNT] = { .image_bit_depth = 0, .parent = 0, .association_type = MTP_ASSOCIATION_UNDEFINED, + .size = sizeof(README_TXT_CONTENT)-1, .data = (uint8_t*) (uintptr_t) README_TXT_CONTENT, - .size = sizeof(README_TXT_CONTENT)-1 }, { .name = { 't', 'i', 'n', 'y', 'u', 's', 'b', '.', 'p', 'n', 'g', 0 }, // "tinyusb.png" @@ -123,8 +126,8 @@ static fs_file_t fs_objects[FS_MAX_FILE_COUNT] = { .image_bit_depth = 32, .parent = 0, .association_type = MTP_ASSOCIATION_UNDEFINED, - .data = (uint8_t*) (uintptr_t) logo_bin, - .size = logo_len, + .size = LOGO_LEN, + .data = (uint8_t*) (uintptr_t) logo_bin } }; @@ -140,6 +143,7 @@ static int32_t fs_get_device_properties(tud_mtp_cb_data_t* cb_data); static int32_t fs_get_object_handles(tud_mtp_cb_data_t* cb_data); static int32_t fs_get_object_info(tud_mtp_cb_data_t* cb_data); static int32_t fs_get_object(tud_mtp_cb_data_t* cb_data); +static int32_t fs_get_partial_object(tud_mtp_cb_data_t* cb_data); static int32_t fs_delete_object(tud_mtp_cb_data_t* cb_data); static int32_t fs_send_object_info(tud_mtp_cb_data_t* cb_data); static int32_t fs_send_object(tud_mtp_cb_data_t* cb_data); @@ -161,6 +165,7 @@ fs_op_handler_dict_t fs_op_handler_dict[] = { { MTP_OP_GET_OBJECT_HANDLES, fs_get_object_handles }, { MTP_OP_GET_OBJECT_INFO, fs_get_object_info }, { MTP_OP_GET_OBJECT, fs_get_object }, + { MTP_OP_GET_PARTIAL_OBJECT, fs_get_partial_object }, { MTP_OP_DELETE_OBJECT, fs_delete_object }, { MTP_OP_SEND_OBJECT_INFO, fs_send_object_info }, { MTP_OP_SEND_OBJECT, fs_send_object }, @@ -272,11 +277,11 @@ int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t* cb_data) { resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED; } else { resp_code = handler(cb_data); - if (resp_code > MTP_RESP_UNDEFINED) { - // send response if needed - io_container->header->code = (uint16_t)resp_code; - tud_mtp_response_send(io_container); - } + } + if (resp_code > MTP_RESP_UNDEFINED) { + // send response if needed + io_container->header->code = (uint16_t)resp_code; + tud_mtp_response_send(io_container); } return resp_code; @@ -299,11 +304,11 @@ int32_t tud_mtp_data_xfer_cb(tud_mtp_cb_data_t* cb_data) { resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED; } else { resp_code = handler(cb_data); - if (resp_code > MTP_RESP_UNDEFINED) { - // send response if needed - io_container->header->code = (uint16_t)resp_code; - tud_mtp_response_send(io_container); - } + } + if (resp_code > MTP_RESP_UNDEFINED) { + // send response if needed + io_container->header->code = (uint16_t)resp_code; + tud_mtp_response_send(io_container); } return 0; @@ -320,9 +325,17 @@ int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data) { break; } // parameter is: storage id, parent handle, new handle - mtp_container_add_uint32(resp, SUPPORTED_STORAGE_ID); - mtp_container_add_uint32(resp, f->parent); - mtp_container_add_uint32(resp, send_obj_handle); + (void) mtp_container_add_uint32(resp, SUPPORTED_STORAGE_ID); + (void) mtp_container_add_uint32(resp, f->parent); + (void) mtp_container_add_uint32(resp, send_obj_handle); + resp->header->code = MTP_RESP_OK; + break; + } + + case MTP_OP_GET_PARTIAL_OBJECT: { + // response parameter: actual length of data sent excluding container header + const uint32_t len = cb_data->total_xferred_bytes - sizeof(mtp_container_header_t); + (void) mtp_container_add_uint32(resp, len); resp->header->code = MTP_RESP_OK; break; } @@ -346,19 +359,22 @@ int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) { //--------------------------------------------------------------------+ static int32_t fs_get_device_info(tud_mtp_cb_data_t* cb_data) { // Device info is already prepared up to playback formats. Application only need to add string fields + int32_t resp_code = 0; mtp_container_info_t* io_container = &cb_data->io_container; - mtp_container_add_cstring(io_container, DEV_INFO_MANUFACTURER); - mtp_container_add_cstring(io_container, DEV_INFO_MODEL); - mtp_container_add_cstring(io_container, DEV_INFO_VERSION); + (void) mtp_container_add_cstring(io_container, DEV_INFO_MANUFACTURER); + (void) mtp_container_add_cstring(io_container, DEV_INFO_MODEL); + (void) mtp_container_add_cstring(io_container, DEV_INFO_VERSION); enum { MAX_SERIAL_NCHARS = 32 }; uint16_t serial_utf16[MAX_SERIAL_NCHARS+1]; size_t nchars = board_usb_get_serial(serial_utf16, MAX_SERIAL_NCHARS); serial_utf16[tu_min32(nchars, MAX_SERIAL_NCHARS)] = 0; // ensure null termination - mtp_container_add_string(io_container, serial_utf16); + (void) mtp_container_add_string(io_container, serial_utf16); - tud_mtp_data_send(io_container); - return 0; + if (!tud_mtp_data_send(io_container)) { + resp_code = MTP_RESP_DEVICE_BUSY; + } + return resp_code; } static int32_t fs_open_close_session(tud_mtp_cb_data_t* cb_data) { @@ -380,7 +396,7 @@ static int32_t fs_open_close_session(tud_mtp_cb_data_t* cb_data) { static int32_t fs_get_storage_ids(tud_mtp_cb_data_t* cb_data) { mtp_container_info_t* io_container = &cb_data->io_container; uint32_t storage_ids [] = { SUPPORTED_STORAGE_ID }; - mtp_container_add_auint32(io_container, 1, storage_ids); + (void) mtp_container_add_auint32(io_container, 1, storage_ids); tud_mtp_data_send(io_container); return 0; } @@ -391,10 +407,10 @@ static int32_t fs_get_storage_info(tud_mtp_cb_data_t* cb_data) { const uint32_t storage_id = command->params[0]; TU_VERIFY(SUPPORTED_STORAGE_ID == storage_id, -1); // update storage info with current free space - storage_info.max_capacity_in_bytes = sizeof(README_TXT_CONTENT) + logo_len + FS_MAX_CAPACITY_BYTES; + storage_info.max_capacity_in_bytes = sizeof(README_TXT_CONTENT) + LOGO_LEN + FS_MAX_CAPACITY_BYTES; storage_info.free_space_in_objects = FS_MAX_FILE_COUNT - fs_get_file_count(); storage_info.free_space_in_bytes = storage_info.free_space_in_objects ? FS_MAX_CAPACITY_BYTES : 0; - mtp_container_add_raw(io_container, &storage_info, sizeof(storage_info)); + (void) mtp_container_add_raw(io_container, &storage_info, sizeof(storage_info)); tud_mtp_data_send(io_container); return 0; } @@ -412,10 +428,10 @@ static int32_t fs_get_device_properties(tud_mtp_cb_data_t* cb_data) { case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: device_prop_header.datatype = MTP_DATA_TYPE_STR; device_prop_header.get_set = MTP_MODE_GET; - mtp_container_add_raw(io_container, &device_prop_header, sizeof(device_prop_header)); - mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // factory - mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // current - mtp_container_add_uint8(io_container, 0); // no form + (void) mtp_container_add_raw(io_container, &device_prop_header, sizeof(device_prop_header)); + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // factory + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // current + (void) mtp_container_add_uint8(io_container, 0); // no form tud_mtp_data_send(io_container); break; @@ -426,7 +442,7 @@ static int32_t fs_get_device_properties(tud_mtp_cb_data_t* cb_data) { // get value switch (dev_prop_code) { case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: - mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); tud_mtp_data_send(io_container); break; @@ -446,20 +462,20 @@ static int32_t fs_get_object_handles(tud_mtp_cb_data_t* cb_data) { const uint32_t parent_handle = command->params[2]; // folder handle, 0xFFFFFFFF is root (void)obj_format; - if (storage_id != 0xFFFFFFFF && storage_id != SUPPORTED_STORAGE_ID) { + if (storage_id != 0xFFFFFFFFu && storage_id != SUPPORTED_STORAGE_ID) { return MTP_RESP_INVALID_STORAGE_ID; } uint32_t handles[FS_MAX_FILE_COUNT] = { 0 }; - uint32_t count = 0; - for (uint8_t i = 0; i < FS_MAX_FILE_COUNT; i++) { + uint32_t count = 0u; + for (uint8_t i = 0u; i < FS_MAX_FILE_COUNT; i++) { fs_file_t* f = &fs_objects[i]; if (fs_file_exist(f) && - (parent_handle == f->parent || (parent_handle == 0xFFFFFFFF && f->parent == 0))) { - handles[count++] = i + 1; // handle is index + 1 + (parent_handle == f->parent || (parent_handle == 0xFFFFFFFFu && f->parent == 0u))) { + handles[count++] = (uint32_t) i + 1u; // handle is index + 1 } } - mtp_container_add_auint32(io_container, count, handles); + (void) mtp_container_add_auint32(io_container, count, handles); tud_mtp_data_send(io_container); return 0; @@ -490,11 +506,11 @@ static int32_t fs_get_object_info(tud_mtp_cb_data_t* cb_data) { .association_desc = 0, .sequence_number = 0 }; - mtp_container_add_raw(io_container, &obj_info_header, sizeof(obj_info_header)); - mtp_container_add_string(io_container, f->name); - mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); - mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); - mtp_container_add_cstring(io_container, ""); // keywords, not used + (void) mtp_container_add_raw(io_container, &obj_info_header, sizeof(obj_info_header)); + (void) mtp_container_add_string(io_container, f->name); + (void) mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); + (void) mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); + (void) mtp_container_add_cstring(io_container, ""); // keywords, not used tud_mtp_data_send(io_container); return 0; @@ -512,7 +528,7 @@ static int32_t fs_get_object(tud_mtp_cb_data_t* cb_data) { if (cb_data->phase == MTP_PHASE_COMMAND) { // If file contents is larger than CFG_TUD_MTP_EP_BUFSIZE, data may only partially is added here // the rest will be sent in tud_mtp_data_more_cb - mtp_container_add_raw(io_container, f->data, f->size); + (void) mtp_container_add_raw(io_container, f->data, f->size); tud_mtp_data_send(io_container); } else if (cb_data->phase == MTP_PHASE_DATA) { // continue sending remaining data: file contents offset is xferred byte minus header size @@ -522,6 +538,42 @@ static int32_t fs_get_object(tud_mtp_cb_data_t* cb_data) { memcpy(io_container->payload, f->data + offset, xact_len); tud_mtp_data_send(io_container); } + } else { + // nothing to do + } + + return 0; +} + +static int32_t fs_get_partial_object(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + const uint32_t obj_handle = command->params[0]; + const uint32_t req_offset = command->params[1]; + const uint32_t req_max = command->params[2]; + const fs_file_t* f = fs_get_file(obj_handle); + if (f == NULL) { + return MTP_RESP_INVALID_OBJECT_HANDLE; + } + + const uint32_t avail = (req_offset >= f->size) ? 0u : (f->size - req_offset); + const uint32_t to_send = tu_min32(avail, req_max); + + if (cb_data->phase == MTP_PHASE_COMMAND) { + // If file contents is larger than CFG_TUD_MTP_EP_BUFSIZE, data may only partially be added here + // the rest will be sent in tud_mtp_data_more_cb + (void) mtp_container_add_raw(io_container, f->data + req_offset, to_send); + tud_mtp_data_send(io_container); + } else if (cb_data->phase == MTP_PHASE_DATA) { + // continue sending remaining data: file contents offset is xferred byte minus header size + const uint32_t offset = cb_data->total_xferred_bytes - sizeof(mtp_container_header_t); + const uint32_t xact_len = tu_min32(to_send - offset, io_container->payload_bytes); + if (xact_len > 0) { + memcpy(io_container->payload, f->data + offset + req_offset, xact_len); + tud_mtp_data_send(io_container); + } + } else { + // nothing to do } return 0; @@ -537,21 +589,21 @@ static int32_t fs_send_object_info(tud_mtp_cb_data_t* cb_data) { if (!is_session_opened) { return MTP_RESP_SESSION_NOT_OPEN; } - if (storage_id != 0xFFFFFFFF && storage_id != SUPPORTED_STORAGE_ID) { + if (storage_id != 0xFFFFFFFFu && storage_id != SUPPORTED_STORAGE_ID) { return MTP_RESP_INVALID_STORAGE_ID; } if (cb_data->phase == MTP_PHASE_COMMAND) { - tud_mtp_data_receive(io_container); + (void) tud_mtp_data_receive(io_container); } else if (cb_data->phase == MTP_PHASE_DATA) { mtp_object_info_header_t* obj_info = (mtp_object_info_header_t*) io_container->payload; if (obj_info->storage_id != 0 && obj_info->storage_id != SUPPORTED_STORAGE_ID) { return MTP_RESP_INVALID_STORAGE_ID; } - if (obj_info->parent_object) { + if (obj_info->parent_object != 0 && obj_info->parent_object != 0xFFFFFFFFu) { // not root fs_file_t* parent = fs_get_file(obj_info->parent_object); - if (parent == NULL || !parent->association_type) { + if (parent == NULL || 0u == parent->association_type) { return MTP_RESP_INVALID_PARENT_OBJECT; } } @@ -575,8 +627,10 @@ static int32_t fs_send_object_info(tud_mtp_cb_data_t* cb_data) { f->size = obj_info->object_compressed_size; f->data = f_buf; uint8_t* buf = io_container->payload + sizeof(mtp_object_info_header_t); - mtp_container_get_string(buf, f->name); + (void) mtp_container_get_string(buf, f->name); // ignore date created/modified/keywords + } else { + // nothing to do } return 0; |
