implement get device properties value

This commit is contained in:
hathach
2025-09-20 00:42:06 +07:00
parent 57c5e5516a
commit b70804b0c4
3 changed files with 76 additions and 59 deletions

View File

@@ -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;
}

View File

@@ -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) {

View File

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