diff options
| author | hathach <[email protected]> | 2025-09-20 00:42:06 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2025-09-20 00:42:06 +0700 |
| commit | b70804b0c4212f67625e945986b91bbe1d965059 (patch) | |
| tree | 42d1c5a15589ffbefb202d9ecde624493c28b7ff | |
| parent | 57c5e5516a7e6711085e3d5f57d2023d6ce1b237 (diff) | |
implement get device properties value
| -rw-r--r-- | examples/device/mtp/src/mtp_fs_example.c | 86 | ||||
| -rw-r--r-- | src/class/mtp/mtp.h | 38 | ||||
| -rw-r--r-- | src/class/mtp/mtp_device.c | 11 |
3 files changed, 76 insertions, 59 deletions
diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c index fcd01f54a..89814fb8f 100644 --- a/examples/device/mtp/src/mtp_fs_example.c +++ b/examples/device/mtp/src/mtp_fs_example.c @@ -34,50 +34,12 @@ //--------------------------------------------------------------------+ // device info string (including terminating null) -static const uint16_t dev_info_manufacturer[] = { 'T', 'i', 'n', 'y', 'U', 'S', 'B', 0 }; -static const uint16_t dev_info_model[] = { 'M', 'T', 'P', ' ', 'E', 'x', 'a', 'm', 'p', 'l', 'e', 0 }; -static const uint16_t dev_info_version[] = { '1', '.', '0', 0 }; -static const uint16_t dev_info_serial[] = { '1', '2', '3', '4', '5', '6', 0 }; +#define DEV_INFO_MANUFACTURER "TinyUSB" +#define DEV_INFO_MODEL "MTP Example" +#define DEV_INFO_VERSION "1.0" +#define DEV_INFO_SERIAL "123456" -static const uint16_t supported_operations[] = { - MTP_OP_GET_DEVICE_INFO, - MTP_OP_OPEN_SESSION, - MTP_OP_CLOSE_SESSION, - MTP_OP_GET_STORAGE_IDS, - MTP_OP_GET_STORAGE_INFO, - MTP_OP_GET_NUM_OBJECTS, - MTP_OP_GET_OBJECT_HANDLES, - MTP_OP_GET_OBJECT_INFO, - MTP_OP_GET_OBJECT, - MTP_OP_DELETE_OBJECT, - MTP_OP_SEND_OBJECT_INFO, - MTP_OP_SEND_OBJECT, - MTP_OP_FORMAT_STORE, - MTP_OP_RESET_DEVICE, - MTP_OP_GET_DEVICE_PROP_DESC, - MTP_OP_GET_DEVICE_PROP_VALUE, - MTP_OP_SET_DEVICE_PROP_VALUE -}; - -static const uint16_t supported_events[] = { - MTP_EVENT_OBJECT_ADDED, -}; - -static const uint16_t supported_device_properties[] = { - MTP_DEV_PROP_DEVICE_FRIENDLY_NAME, -}; - -static const uint16_t capture_formats[] = { - MTP_OBJ_FORMAT_UNDEFINED, - MTP_OBJ_FORMAT_ASSOCIATION, - MTP_OBJ_FORMAT_TEXT, -}; - -static const uint16_t playback_formats[] = { - MTP_OBJ_FORMAT_UNDEFINED, - MTP_OBJ_FORMAT_ASSOCIATION, - MTP_OBJ_FORMAT_TEXT, -}; +#define DEV_PROP_FRIENDLY_NAME "TinyUSB MTP" //--------------------------------------------------------------------+ // RAM FILESYSTEM @@ -139,6 +101,10 @@ storage_info_t storage_info = { } }; +enum { + SUPPORTED_STORAGE_ID = 0x00010001u // physical = 1, logical = 1 +}; + //--------------------------------------------------------------------+ // OPERATING STATUS @@ -205,15 +171,24 @@ int32_t tud_mtp_data_complete_cb(uint8_t idx, mtp_container_header_t* cmd_header return 0; } +int32_t tud_mtp_response_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; + (void) cmd_header; + (void) resp_block; + (void) xfer_result; + (void) xferred_bytes; + return 0; // nothing to do +} + int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_block, mtp_generic_container_t* out_block) { (void)idx; switch (cmd_block->code) { case MTP_OP_GET_DEVICE_INFO: { // Device info is already prepared up to playback formats. Application only need to add string fields - mtp_container_add_string(out_block, TU_ARRAY_SIZE(dev_info_manufacturer), dev_info_manufacturer); - mtp_container_add_string(out_block, TU_ARRAY_SIZE(dev_info_model), dev_info_model); - mtp_container_add_string(out_block, TU_ARRAY_SIZE(dev_info_version), dev_info_version); - mtp_container_add_string(out_block, TU_ARRAY_SIZE(dev_info_serial), dev_info_serial); + mtp_container_add_cstring(out_block, DEV_INFO_MANUFACTURER); + mtp_container_add_cstring(out_block, DEV_INFO_MODEL); + mtp_container_add_cstring(out_block, DEV_INFO_VERSION); + mtp_container_add_cstring(out_block, DEV_INFO_SERIAL); tud_mtp_data_send(out_block); break; @@ -225,13 +200,14 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl break; case MTP_OP_GET_STORAGE_IDS: { - uint32_t storage_ids [] = { 0x00010001u }; // physical = 1, logical = 1 + uint32_t storage_ids [] = { SUPPORTED_STORAGE_ID }; // physical = 1, logical = 1 mtp_container_add_auint32(out_block, 1, storage_ids); tud_mtp_data_send(out_block); break; } case MTP_OP_GET_STORAGE_INFO: { + TU_VERIFY(SUPPORTED_STORAGE_ID == cmd_block->data[0], -1); // update storage info with current free space storage_info.free_space_in_objects = FS_MAX_NODES - fs_get_object_count(); storage_info.free_space_in_bytes = storage_info.free_space_in_objects * FS_MAX_NODE_BYTES; @@ -240,6 +216,20 @@ int32_t tud_mtp_command_received_cb(uint8_t idx, mtp_generic_container_t* cmd_bl break; } + case MTP_OP_GET_DEVICE_PROP_VALUE: { + const uint16_t dev_prop_code = (uint16_t) cmd_block->data[0]; + switch (dev_prop_code) { + case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: + mtp_container_add_cstring(out_block, DEV_PROP_FRIENDLY_NAME); + tud_mtp_data_send(out_block); + break; + + default: return -1; + } + break; + } + + default: return -1; } diff --git a/src/class/mtp/mtp.h b/src/class/mtp/mtp.h index c48a2469c..138cb1b86 100644 --- a/src/class/mtp/mtp.h +++ b/src/class/mtp/mtp.h @@ -782,17 +782,30 @@ typedef struct TU_ATTR_PACKED { // - datetime_wstring date_modified; // - wstring keywords; -// DevicePropDesc Dataset +// Device property desc up to get/set typedef struct TU_ATTR_PACKED { uint16_t device_property_code; uint16_t datatype; uint8_t get_set; -} mtp_device_prop_desc_t; +} mtp_device_prop_desc_header_t; + // The following fields will be dynamically added to the struct at runtime: // - wstring factory_def_value; // - wstring current_value_len; // - uint8_t form_flag; +// no form +#define MTP_DEVICE_PROPERTIES_TYPEDEF(_type) \ + struct TU_ATTR_PACKED { \ + uint16_t device_property_code; \ + uint16_t datatype; \ + uint8_t get_set; \ + _type factory_default; \ + _type current_value; \ + uint8_t form_flag; /* 0: none, 1: range, 2: enum */ \ + }; + + typedef struct TU_ATTR_PACKED { uint16_t wLength; uint16_t code; @@ -832,15 +845,28 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_field(mtp_generic } TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_string(mtp_generic_container_t* p_container, uint8_t count, uint16_t* utf16) { - const uint32_t prev_len = p_container->len; uint8_t* container8 = (uint8_t*) p_container; - *(container8 + p_container->len) = count; - p_container->len += 1; + container8[p_container->len] = count; + p_container->len++; memcpy(container8 + p_container->len, utf16, 2 * count); p_container->len += 2 * count; - return p_container->len - prev_len; + return 1 + 2 * count; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_cstring(mtp_generic_container_t* p_container, const char* str) { + uint8_t* container8 = (uint8_t*) p_container; + const uint8_t len = (uint8_t) (strlen(str) + 1); // include null + container8[p_container->len] = len; + p_container->len++; + + for (uint8_t i = 0; i < len; i++) { + container8[p_container->len] = str[i]; + container8[p_container->len + 1] = 0; + p_container->len += 2; + } + return 1 + 2 * len; } TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_uint8(mtp_generic_container_t* p_container, uint8_t data) { diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c index d0a1d6c40..2e9ac9a92 100644 --- a/src/class/mtp/mtp_device.c +++ b/src/class/mtp/mtp_device.c @@ -466,11 +466,12 @@ mtp_phase_type_t mtpd_handle_cmd(mtpd_interface_t* p_mtp) { case MTP_OP_GET_DEVICE_PROP_DESC: TU_LOG_DRV(" MTP command: MTP_OP_GET_DEVICE_PROP_DESC\n"); - return mtpd_handle_cmd_get_device_prop_desc(); + break; case MTP_OP_GET_DEVICE_PROP_VALUE: TU_LOG_DRV(" MTP command: MTP_OP_GET_DEVICE_PROP_VALUE\n"); - return mtpd_handle_cmd_get_device_prop_value(); + break; + case MTP_OP_SEND_OBJECT_INFO: TU_LOG_DRV(" MTP command: MTP_OP_SEND_OBJECT_INFO\n"); return mtpd_handle_cmd_send_object_info(); @@ -673,11 +674,11 @@ mtp_phase_type_t mtpd_handle_cmd_get_device_prop_desc(void) { case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: { - TU_VERIFY_STATIC(sizeof(mtp_device_prop_desc_t) < MTP_MAX_PACKET_SIZE, "mtp_device_info_t shall fit in MTP_MAX_PACKET_SIZE"); + TU_VERIFY_STATIC(sizeof(mtp_device_prop_desc_header_t) < MTP_MAX_PACKET_SIZE, "mtp_device_info_t shall fit in MTP_MAX_PACKET_SIZE"); p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; p_container->code = MTP_OP_GET_DEVICE_PROP_DESC; - p_container->len = MTP_CONTAINER_HEADER_LENGTH + sizeof(mtp_device_prop_desc_t); - mtp_device_prop_desc_t *d = (mtp_device_prop_desc_t *)p_container->data; + p_container->len = MTP_CONTAINER_HEADER_LENGTH + sizeof(mtp_device_prop_desc_header_t); + mtp_device_prop_desc_header_t *d = (mtp_device_prop_desc_header_t *)p_container->data; d->device_property_code = (uint16_t)(device_prop_code); d->datatype = MTP_DATA_TYPE_STR; d->get_set = MTP_MODE_GET; |
