Skip to content

Commit 4c81899

Browse files
committed
implement get object info
1 parent f5a3f25 commit 4c81899

File tree

4 files changed

+60
-89
lines changed

4 files changed

+60
-89
lines changed

examples/device/mtp/src/mtp_fs_example.c

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ typedef struct {
6565
static fs_object_info_t fs_objects[FS_MAX_NODES] = {
6666
{
6767
.handle = 1,
68-
.parent = 0xffffffff,
68+
.parent = 0,
6969
.allocated = true,
7070
.association = false,
7171
.name = "readme.txt",
@@ -80,7 +80,7 @@ static fs_object_info_t fs_objects[FS_MAX_NODES] = {
8080
#define STORAGE_DESCRIPTRION { 'd', 'i', 's', 'k', 0 }
8181
#define VOLUME_IDENTIFIER { 'v', 'o', 'l', 0 }
8282

83-
typedef MTP_STORAGE_INFO_TYPEDEF(TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTRION),
83+
typedef MTP_STORAGE_INFO_STRUCT(TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTRION),
8484
TU_ARRAY_SIZE(((uint16_t[])VOLUME_IDENTIFIER))
8585
) storage_info_t;
8686

@@ -261,7 +261,8 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl
261261
uint32_t handles[FS_MAX_NODES] = { 0 };
262262
uint32_t count = 0;
263263
for (uint8_t i = 0, h = 0; i < FS_MAX_NODES; i++) {
264-
if (fs_objects[i].allocated && parent_handle == fs_objects[i].parent) {
264+
if (fs_objects[i].allocated && parent_handle == fs_objects[i].parent ||
265+
(parent_handle == 0xFFFFFFFF && fs_objects[i].parent == 0)) {
265266
handles[count++] = fs_objects[i].handle;
266267
}
267268
}
@@ -270,6 +271,40 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl
270271
break;
271272
}
272273

274+
case MTP_OP_GET_OBJECT_INFO: {
275+
const uint32_t object_handle = cmd_block->data[0];
276+
fs_object_info_t* obj = fs_object_get_from_handle(object_handle);
277+
if (obj == NULL) {
278+
TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle);
279+
return MTP_RESP_INVALID_OBJECT_HANDLE;
280+
}
281+
mtp_object_info_header_t object_info_header = {
282+
.storage_id = SUPPORTED_STORAGE_ID,
283+
.object_format = MTP_OBJ_FORMAT_TEXT,
284+
.protection_status = MTP_PROTECTION_STATUS_NO_PROTECTION,
285+
.object_compressed_size = obj->size,
286+
.thumb_format = MTP_OBJ_FORMAT_UNDEFINED,
287+
.thumb_compressed_size = 0,
288+
.thumb_pix_width = 0,
289+
.thumb_pix_height = 0,
290+
.image_pix_width = 0,
291+
.image_pix_height = 0,
292+
.image_bit_depth = 0,
293+
.parent_object = obj->parent,
294+
.association_type = MTP_ASSOCIATION_UNDEFINED,
295+
.association_desc = 0,
296+
.sequence_number = 0
297+
};
298+
mtp_container_add_raw(out_block, &object_info_header, sizeof(object_info_header));
299+
mtp_container_add_cstring(out_block, obj->name);
300+
mtp_container_add_cstring(out_block, obj->created);
301+
mtp_container_add_cstring(out_block, obj->modified);
302+
mtp_container_add_cstring(out_block, ""); // keywords, not used
303+
304+
tud_mtp_data_send(out_block);
305+
break;
306+
}
307+
273308
default: return MTP_RESP_OPERATION_NOT_SUPPORTED;
274309
}
275310

@@ -346,7 +381,7 @@ mtp_response_t tud_mtp_storage_association_get_object_handle(uint32_t storage_id
346381
}
347382

348383
mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t parent_object,
349-
uint32_t* new_object_handle, const mtp_object_info_t* info) {
384+
uint32_t* new_object_handle, const mtp_object_info_header_t* info) {
350385
fs_object_info_t* obj = NULL;
351386

352387
if (_fs_operation.session_id == 0) {
@@ -402,7 +437,7 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p
402437
obj->association = info->object_format == MTP_OBJ_FORMAT_ASSOCIATION;
403438

404439
// Extract variable data
405-
uint16_t offset_data = sizeof(mtp_object_info_t);
440+
uint16_t offset_data = sizeof(mtp_object_info_header_t);
406441
mtpd_gct_get_string(&offset_data, obj->name, FS_MAX_NODE_NAME_LEN);
407442
mtpd_gct_get_string(&offset_data, obj->created, FS_ISODATETIME_LEN);
408443
mtpd_gct_get_string(&offset_data, obj->modified, FS_ISODATETIME_LEN);
@@ -417,46 +452,6 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p
417452
return MTP_RESP_OK;
418453
}
419454

420-
mtp_response_t tud_mtp_storage_object_read_info(uint32_t object_handle, mtp_object_info_t* info) {
421-
const fs_object_info_t* obj;
422-
423-
if (_fs_operation.session_id == 0) {
424-
TU_LOG1("ERR: Session not open\r\n");
425-
return MTP_RESP_SESSION_NOT_OPEN;
426-
}
427-
428-
obj = fs_object_get_from_handle(object_handle);
429-
if (obj == NULL) {
430-
TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle);
431-
return MTP_RESP_INVALID_OBJECT_HANDLE;
432-
}
433-
434-
memset(info, 0, sizeof(mtp_object_info_t));
435-
info->storage_id = STORAGE_ID(0x0001, 0x0001);
436-
if (obj->association) {
437-
info->object_format = MTP_OBJ_FORMAT_ASSOCIATION;
438-
info->protection_status = MTP_PROTECTION_STATUS_NO_PROTECTION;
439-
info->object_compressed_size = 0;
440-
info->association_type = MTP_ASSOCIATION_UNDEFINED;
441-
} else {
442-
info->object_format = MTP_OBJ_FORMAT_UNDEFINED;
443-
info->protection_status = MTP_PROTECTION_STATUS_NO_PROTECTION;
444-
info->object_compressed_size = obj->size;
445-
info->association_type = MTP_ASSOCIATION_UNDEFINED;
446-
}
447-
info->thumb_format = MTP_OBJ_FORMAT_UNDEFINED;
448-
info->parent_object = obj->parent;
449-
450-
mtpd_gct_append_wstring(obj->name);
451-
mtpd_gct_append_wstring(obj->created); // date_created
452-
mtpd_gct_append_wstring(obj->modified); // date_modified
453-
mtpd_gct_append_wstring(""); // keywords, not used
454-
455-
TU_LOG1("Retrieve object %s with handle %ld\r\n", obj->name, obj->handle);
456-
457-
return MTP_RESP_OK;
458-
}
459-
460455
mtp_response_t tud_mtp_storage_object_write(uint32_t object_handle, const uint8_t* buffer, uint32_t size) {
461456
fs_object_info_t* obj;
462457

src/class/mtp/mtp.h

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -647,11 +647,12 @@ typedef enum {
647647
typedef enum {
648648
MTP_ASSOCIATION_UNDEFINED = 0x0000u,
649649
MTP_ASSOCIATION_GENERIC_FOLDER = 0x0001u,
650-
MTP_ASSOCIATION_GENERIC_ALBUM = 0x0002u,
650+
MTP_ASSOCIATION_ALBUM = 0x0002u,
651651
MTP_ASSOCIATION_TIME_SEQUENCE = 0x0003u,
652652
MTP_ASSOCIATION_HORIZONTAL_PANORAMIC = 0x0004u,
653653
MTP_ASSOCIATION_VERTICAL_PANORAMIC = 0x0005u,
654654
MTP_ASSOCIATION_2D_PANORAMIC = 0x0006u,
655+
MTP_ASSOCIATION_ANCILLARY_DATA = 0x0007u,
655656
} mtp_association_t;
656657

657658
//--------------------------------------------------------------------+
@@ -705,7 +706,7 @@ typedef union TU_ATTR_PACKED {
705706
uint32_t id;
706707
} mtp_storage_id_t;
707708

708-
#define MTP_STORAGE_INFO_TYPEDEF(_storage_desc_chars, _volume_id_chars) \
709+
#define MTP_STORAGE_INFO_STRUCT(_storage_desc_chars, _volume_id_chars) \
709710
struct TU_ATTR_PACKED { \
710711
uint16_t storage_type; \
711712
uint16_t filesystem_type; \
@@ -717,29 +718,24 @@ typedef union TU_ATTR_PACKED {
717718
mtp_string_t(_volume_id_chars) volume_identifier; \
718719
}
719720

720-
// ObjectInfo Dataset
721+
// Object Info Dataset without dynamic string: filename, date_created, date_modified, keywords
721722
typedef struct TU_ATTR_PACKED {
722723
uint32_t storage_id;
723724
uint16_t object_format;
724725
uint16_t protection_status;
725726
uint32_t object_compressed_size;
726-
uint16_t thumb_format; // unused
727-
uint32_t thumb_compressed_size; // unused
728-
uint32_t thumb_pix_width; // unused
729-
uint32_t thumb_pix_height; // unused
730-
uint32_t image_pix_width; // unused
731-
uint32_t image_pix_height; // unused
732-
uint32_t image_bit_depth; // unused
727+
uint16_t thumb_format;
728+
uint32_t thumb_compressed_size;
729+
uint32_t thumb_pix_width;
730+
uint32_t thumb_pix_height;
731+
uint32_t image_pix_width;
732+
uint32_t image_pix_height;
733+
uint32_t image_bit_depth;
733734
uint32_t parent_object; // 0: root
734735
uint16_t association_type;
735-
uint32_t association_description; // not used
736-
uint32_t sequence_number; // not used
737-
} mtp_object_info_t;
738-
// The following fields will be dynamically added to the struct at runtime:
739-
// - wstring filename;
740-
// - datetime_wstring date_created;
741-
// - datetime_wstring date_modified;
742-
// - wstring keywords;
736+
uint32_t association_desc;
737+
uint32_t sequence_number;
738+
} mtp_object_info_header_t;
743739

744740
// Device property desc up to get/set
745741
typedef struct TU_ATTR_PACKED {
@@ -754,7 +750,7 @@ typedef struct TU_ATTR_PACKED {
754750
// - uint8_t form_flag;
755751

756752
// no form
757-
#define MTP_DEVICE_PROPERTIES_TYPEDEF(_type) \
753+
#define MTP_DEVICE_PROPERTIES_STRUCT(_type) \
758754
struct TU_ATTR_PACKED { \
759755
uint16_t device_property_code; \
760756
uint16_t datatype; \
@@ -764,7 +760,6 @@ typedef struct TU_ATTR_PACKED {
764760
uint8_t form_flag; /* 0: none, 1: range, 2: enum */ \
765761
};
766762

767-
768763
typedef struct TU_ATTR_PACKED {
769764
uint16_t wLength;
770765
uint16_t code;

src/class/mtp/mtp_device.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ static mtp_phase_type_t mtpd_chk_session_open(const char *func_name);
8585
static mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp);
8686
static mtp_phase_type_t mtpd_handle_data(void);
8787
static mtp_phase_type_t mtpd_handle_cmd_close_session(void);
88-
static mtp_phase_type_t mtpd_handle_cmd_get_object_info(void);
8988
static mtp_phase_type_t mtpd_handle_cmd_get_object(void);
9089
static mtp_phase_type_t mtpd_handle_dti_get_object(void);
9190
static mtp_phase_type_t mtpd_handle_cmd_delete_object(void);
@@ -454,7 +453,8 @@ mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp) {
454453

455454
case MTP_OP_GET_OBJECT_INFO:
456455
TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT_INFO\n");
457-
return mtpd_handle_cmd_get_object_info();
456+
break;
457+
458458
case MTP_OP_GET_OBJECT:
459459
TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT\n");
460460
return mtpd_handle_cmd_get_object();
@@ -528,25 +528,6 @@ mtp_phase_type_t mtpd_handle_cmd_close_session(void)
528528
return MTP_PHASE_RESPONSE;
529529
}
530530

531-
mtp_phase_type_t mtpd_handle_cmd_get_object_info(void)
532-
{
533-
TU_VERIFY_STATIC(sizeof(mtp_object_info_t) < MTP_MAX_PACKET_SIZE, "mtp_object_info_t shall fit in MTP_MAX_PACKET_SIZE");
534-
mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
535-
uint32_t object_handle = p_container->data[0];
536-
537-
p_container->len = MTP_CONTAINER_HEADER_LENGTH + sizeof(mtp_object_info_t);
538-
p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK;
539-
p_container->code = MTP_OP_GET_OBJECT_INFO;
540-
mtp_response_t res = tud_mtp_storage_object_read_info(object_handle, (mtp_object_info_t *)p_container->data);
541-
mtp_phase_type_t phase;
542-
if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) {
543-
return phase;
544-
}
545-
546-
_mtpd_itf.queued_len = p_container->len;
547-
return MTP_PHASE_DATA_IN;
548-
}
549-
550531
mtp_phase_type_t mtpd_handle_cmd_get_object(void)
551532
{
552533
mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
@@ -634,7 +615,7 @@ mtp_phase_type_t mtpd_handle_dto_send_object_info(void)
634615
{
635616
mtp_generic_container_t* p_container = &_mtpd_epbuf.container;
636617
uint32_t new_object_handle = 0;
637-
mtp_response_t res = tud_mtp_storage_object_write_info(_mtpd_soi.storage_id, _mtpd_soi.parent_object_handle, &new_object_handle, (mtp_object_info_t *)p_container->data);
618+
mtp_response_t res = tud_mtp_storage_object_write_info(_mtpd_soi.storage_id, _mtpd_soi.parent_object_handle, &new_object_handle, (mtp_object_info_header_t *)p_container->data);
638619
mtp_phase_type_t phase;
639620
if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase;
640621

src/class/mtp/mtp_device_storage.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ mtp_response_t tud_mtp_storage_association_get_object_handle(uint32_t session_ha
7777
// The handle of the new object shall be returned in new_object_handle.
7878
// The structure info contains the information to be used for file creation, as passted by the host.
7979
// Note that the variable information (e.g. wstring file name, dates and tags shall be retrieved by using the library functions)
80-
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_t *info);
80+
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);
8181

8282
// Get object information related to a given object handle
8383
//
@@ -89,7 +89,7 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p
8989
// - Date modified (string, use tud_gct_append_date or empty string)
9090
// - Keywords (string containing list of kw, separated by space, use tud_mtp_gct_append_wstring)
9191
// Note that the variable information (e.g. wstring file name, dates and tags shall be written by using the library functions)
92-
mtp_response_t tud_mtp_storage_object_read_info(uint32_t object_handle, mtp_object_info_t *info);
92+
mtp_response_t tud_mtp_storage_object_read_info(uint32_t object_handle, mtp_object_info_header_t *info);
9393

9494
// Get the object size.
9595
//

0 commit comments

Comments
 (0)