summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-09-25 17:43:25 +0700
committerhathach <[email protected]>2025-09-25 17:47:50 +0700
commitc9a8330081b59c05b901889d405ed7b9648c0947 (patch)
tree3b04636e06912d14ee5b7440e5ca5f6adca7933a
parentf8397717ea3f476c810ae3ce27ec4c866b305506 (diff)
implement send object command, able to create new file
-rw-r--r--examples/device/mtp/src/mtp_fs_example.c332
-rw-r--r--src/class/mtp/mtp.h6
-rw-r--r--src/class/mtp/mtp_device.c183
-rw-r--r--src/class/mtp/mtp_device.h2
4 files changed, 158 insertions, 365 deletions
diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c
index d6d7f1907..468fc9146 100644
--- a/examples/device/mtp/src/mtp_fs_example.c
+++ b/examples/device/mtp/src/mtp_fs_example.c
@@ -176,107 +176,6 @@ static inline uint8_t* fs_malloc(size_t size) {
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
-int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data) {
- const mtp_container_command_t* command = cb_data->command_container;
- mtp_container_info_t* resp = &cb_data->io_container;
- switch (command->code) {
- case MTP_OP_SEND_OBJECT_INFO: {
- fs_file_t* f = fs_get_file(send_obj_handle);
- if (f == NULL) {
- resp->header->code = MTP_RESP_GENERAL_ERROR;
- 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);
- resp->header->code = MTP_RESP_OK;
- break;
- }
-
- default:
- resp->header->code = (cb_data->xfer_result == XFER_RESULT_SUCCESS) ? MTP_RESP_OK : MTP_RESP_GENERAL_ERROR;
- break;
- }
- tud_mtp_response_send(resp);
- return 0;
-}
-
-int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) {
- (void) cb_data;
- return 0; // nothing to do
-}
-
-int32_t tud_mtp_data_xfer_cb(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;
- uint32_t resp_code = 0;
- switch (command->code) {
- case MTP_OP_GET_OBJECT: {
- // File contents span over multiple xfers
- const uint32_t obj_handle = command->params[0];
- fs_file_t* f = fs_get_file(obj_handle);
- if (f == NULL) {
- resp_code = MTP_RESP_INVALID_OBJECT_HANDLE;
- } else {
- // file contents offset is xferred byte minus header size
- const uint32_t offset = cb_data->xferred_bytes - sizeof(mtp_container_header_t);
- const uint32_t xact_len = tu_min32(f->size - offset, io_container->payload_size);
- memcpy(io_container->payload, f->data + offset, xact_len);
- tud_mtp_data_send(&cb_data->io_container);
- }
- break;
- }
-
- case MTP_OP_SEND_OBJECT_INFO: {
- 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) {
- resp_code = MTP_RESP_INVALID_STORAGE_ID;
- break;
- }
-
- if (obj_info->parent_object) {
- fs_file_t* parent = fs_get_file(obj_info->parent_object);
- if (parent == NULL || !parent->association_type) {
- resp_code = MTP_RESP_INVALID_PARENT_OBJECT;
- break;
- }
- }
-
- fs_file_t* f = fs_create_file();
- f->object_format = obj_info->object_format;
- f->protection_status = obj_info->protection_status;
- f->image_pix_width = obj_info->image_pix_width;
- f->image_pix_height = obj_info->image_pix_height;
- f->image_bit_depth = obj_info->image_bit_depth;
- f->parent = obj_info->parent_object;
- f->association_type = obj_info->association_type;
- f->size = obj_info->object_compressed_size;
- f->data = fs_malloc(f->size);
- if (f->data == NULL) {
- resp_code = MTP_RESP_STORE_FULL;
- break;
- }
- uint8_t* buf = io_container->payload + sizeof(mtp_object_info_header_t);
- mtp_container_get_string(buf,f->name);
- // ignore date created/modified/keywords
- break;
- }
-
- default:
- resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED;
- break;
- }
-
- // send response if needed
- if (resp_code != 0) {
- io_container->header->code = resp_code;
- tud_mtp_response_send(io_container);
- }
-
- return 0; // 0 mean data/response is sent already
-}
-
int32_t tud_mtp_command_received_cb(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;
@@ -425,13 +324,13 @@ int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t* cb_data) {
case MTP_OP_GET_OBJECT: {
const uint32_t obj_handle = command->params[0];
- fs_file_t* obj = fs_get_file(obj_handle);
- if (obj == NULL) {
+ fs_file_t* f = fs_get_file(obj_handle);
+ if (f == NULL) {
resp_code = MTP_RESP_INVALID_OBJECT_HANDLE;
} else {
// If file contents is larger than CFG_TUD_MTP_EP_BUFSIZE, only partial data is added here
// the rest will be sent in tud_mtp_data_more_cb
- mtp_container_add_raw(io_container, obj->data, obj->size);
+ mtp_container_add_raw(io_container, f->data, f->size);
tud_mtp_data_send(io_container);
}
break;
@@ -450,8 +349,16 @@ int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t* cb_data) {
break;
}
- case MTP_OP_SEND_OBJECT:
+ case MTP_OP_SEND_OBJECT: {
+ fs_file_t* f = fs_get_file(send_obj_handle);
+ if (f == NULL) {
+ resp_code = MTP_RESP_INVALID_OBJECT_HANDLE;
+ } else {
+ io_container->header->len += f->size;
+ tud_mtp_data_receive(io_container);
+ }
break;
+ }
default:
resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED;
@@ -467,124 +374,143 @@ int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t* cb_data) {
return 0;
}
-//--------------------------------------------------------------------+
-// API
-//--------------------------------------------------------------------+
-#if 0
-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 != SUPPORTED_STORAGE_ID) {
- TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id);
- return MTP_RESP_INVALID_STORAGE_ID;
- }
+int32_t tud_mtp_data_xfer_cb(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;
+ uint32_t resp_code = 0;
+ switch (command->code) {
+ case MTP_OP_GET_OBJECT: {
+ // File contents span over multiple xfers
+ const uint32_t obj_handle = command->params[0];
+ fs_file_t* f = fs_get_file(obj_handle);
+ if (f == NULL) {
+ resp_code = MTP_RESP_INVALID_OBJECT_HANDLE;
+ } else {
+ // 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(f->size - offset, io_container->payload_bytes);
+ memcpy(io_container->payload, f->data + offset, xact_len);
+ tud_mtp_data_send(io_container);
+ }
+ break;
+ }
- // Simply deallocate all entries
- for (unsigned int i = 0; i < FS_MAX_NODES; i++)
- fs_objects[i].allocated = false;
- TU_LOG1("Format completed\r\n");
- return MTP_RESP_OK;
-}
+ case MTP_OP_SEND_OBJECT_INFO: {
+ 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) {
+ resp_code = MTP_RESP_INVALID_STORAGE_ID;
+ break;
+ }
-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_file_t* obj = NULL;
+ if (obj_info->parent_object) {
+ fs_file_t* parent = fs_get_file(obj_info->parent_object);
+ if (parent == NULL || !parent->association_type) {
+ resp_code = MTP_RESP_INVALID_PARENT_OBJECT;
+ break;
+ }
+ }
- if (_fs_operation.session_id == 0) {
- TU_LOG1("ERR: Session not open\r\n");
- return MTP_RESP_SESSION_NOT_OPEN;
- }
- // Accept command on default storage
- 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;
+ fs_file_t* f = fs_create_file();
+ f->object_format = obj_info->object_format;
+ f->protection_status = obj_info->protection_status;
+ f->image_pix_width = obj_info->image_pix_width;
+ f->image_pix_height = obj_info->image_pix_height;
+ f->image_bit_depth = obj_info->image_bit_depth;
+ f->parent = obj_info->parent_object;
+ f->association_type = obj_info->association_type;
+ f->size = obj_info->object_compressed_size;
+ f->data = fs_malloc(f->size);
+ if (f->data == NULL) {
+ resp_code = MTP_RESP_STORE_FULL;
+ break;
+ }
+ uint8_t* buf = io_container->payload + sizeof(mtp_object_info_header_t);
+ mtp_container_get_string(buf, f->name);
+ // ignore date created/modified/keywords
+ break;
+ }
+
+ case MTP_OP_SEND_OBJECT: {
+ fs_file_t* f = fs_get_file(send_obj_handle);
+ if (f == NULL) {
+ resp_code = MTP_RESP_INVALID_OBJECT_HANDLE;
+ } else {
+ // file contents offset is total xferred minus header size minus last received chunk
+ const uint32_t offset = cb_data->total_xferred_bytes - sizeof(mtp_container_header_t) - io_container->payload_bytes;
+ memcpy(f->data + offset, io_container->payload, io_container->payload_bytes);
+ tud_mtp_data_receive(io_container); // receive more data if needed
+ }
+ break;
+ }
+
+ default:
+ resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED;
+ break;
}
- if (info->object_compressed_size > FS_MAX_NODE_BYTES) {
- TU_LOG1("Object size %ld is more than maximum %ld\r\n", info->object_compressed_size, FS_MAX_NODE_BYTES);
- return MTP_RESP_STORE_FULL;
+ // send response if needed
+ if (resp_code != 0) {
+ io_container->header->code = resp_code;
+ tud_mtp_response_send(io_container);
}
- // Request for objects with no parent (0xFFFFFFFF) are considered root objects
- if (parent_object == 0xFFFFFFFF)
- parent_object = 0;
+ return 0; // 0 mean data/response is sent already
+}
- // Ensure we are not creating an orphaned object outside root
- if (parent_object != 0) {
- obj = fs_get_file(parent_object);
- if (obj == NULL) {
- TU_LOG1("Parent %ld does not exist\r\n", parent_object);
- return MTP_RESP_INVALID_PARENT_OBJECT;
- }
- if (!obj->association_type) {
- TU_LOG1("Parent %ld is not an association\r\n", parent_object);
- return MTP_RESP_INVALID_PARENT_OBJECT;
+int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data) {
+ const mtp_container_command_t* command = cb_data->command_container;
+ mtp_container_info_t* resp = &cb_data->io_container;
+ switch (command->code) {
+ case MTP_OP_SEND_OBJECT_INFO: {
+ fs_file_t* f = fs_get_file(send_obj_handle);
+ if (f == NULL) {
+ resp->header->code = MTP_RESP_GENERAL_ERROR;
+ 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);
+ resp->header->code = MTP_RESP_OK;
+ break;
}
- }
- // Search for first free object
- for (unsigned int i = 0; i < FS_MAX_NODES; i++) {
- if (!fs_objects[i].allocated) {
- obj = &fs_objects[i];
+ case MTP_OP_SEND_OBJECT:
+ resp->header->code = (cb_data->xfer_result == XFER_RESULT_SUCCESS) ? MTP_RESP_OK : MTP_RESP_GENERAL_ERROR;
break;
- }
- }
- if (obj == NULL) {
- TU_LOG1("No space left on device\r\n");
- return MTP_RESP_STORE_FULL;
+ default:
+ resp->header->code = (cb_data->xfer_result == XFER_RESULT_SUCCESS) ? MTP_RESP_OK : MTP_RESP_GENERAL_ERROR;
+ break;
}
- // Fill-in structure
- obj->allocated = true;
- obj->handle = ++_fs_operation.last_handle;
- obj->parent = parent_object;
- obj->size = info->object_compressed_size;
- obj->association_type = info->object_format == MTP_OBJ_FORMAT_ASSOCIATION;
-
- // Extract variable data
- uint16_t offset_data = sizeof(mtp_object_info_header_t);
- mtpd_gct_get_string(&offset_data, obj->name, FS_MAX_NODE_NAME_LEN);
- mtpd_gct_get_string(&offset_data, obj->created, FS_ISODATETIME_LEN);
- mtpd_gct_get_string(&offset_data, obj->modified, FS_ISODATETIME_LEN);
-
- TU_LOG1("Create %s %s with handle %ld, parent %ld and size %ld\r\n",
- obj->association_type ? "association" : "object",
- obj->name, obj->handle, obj->parent, obj->size);
- *new_object_handle = obj->handle;
- // Initialize operation
- _fs_operation.write_handle = obj->handle;
- _fs_operation.write_pos = 0;
- return MTP_RESP_OK;
+ tud_mtp_response_send(resp);
+ return 0;
}
-mtp_response_t tud_mtp_storage_object_write(uint32_t object_handle, const uint8_t* buffer, uint32_t size) {
- fs_file_t* obj;
+int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) {
+ (void) cb_data;
+ return 0; // nothing to do
+}
- obj = fs_get_file(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;
+//--------------------------------------------------------------------+
+// API
+//--------------------------------------------------------------------+
+#if 0
+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;
}
- // It's a requirement that this command is preceded by a write info
- if (object_handle != _fs_operation.write_handle) {
- TU_LOG1("ERR: Object %ld not open for write\r\n", object_handle);
- return MTP_RESP_NO_VALID_OBJECTINFO;
+ if (storage_id != SUPPORTED_STORAGE_ID) {
+ TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id);
+ return MTP_RESP_INVALID_STORAGE_ID;
}
- TU_LOG1("Write object %ld: data chunk at %ld/%ld bytes at offset %ld\r\n", object_handle, _fs_operation.write_pos,
- obj->size, size);
- TU_ASSERT(obj->size >= _fs_operation.write_pos + size, MTP_RESP_INCOMPLETE_TRANSFER);
- if (_fs_operation.write_pos + size < FS_MAX_NODE_BYTES)
- memcpy(&obj->data[_fs_operation.write_pos], buffer, size);
- _fs_operation.write_pos += size;
- // Write operation completed
- if (_fs_operation.write_pos == obj->size) {
- _fs_operation.write_handle = 0;
- _fs_operation.write_pos = 0;
- }
+ // Simply deallocate all entries
+ for (unsigned int i = 0; i < FS_MAX_NODES; i++)
+ fs_objects[i].allocated = false;
+ TU_LOG1("Format completed\r\n");
return MTP_RESP_OK;
}
diff --git a/src/class/mtp/mtp.h b/src/class/mtp/mtp.h
index e713d5c23..15cf1bfc6 100644
--- a/src/class/mtp/mtp.h
+++ b/src/class/mtp/mtp.h
@@ -59,8 +59,6 @@ typedef enum {
MTP_PHASE_IDLE = 0,
MTP_PHASE_COMMAND,
MTP_PHASE_DATA,
- MTP_PHASE_DATA_IN,
- MTP_PHASE_DATA_OUT,
MTP_PHASE_RESPONSE,
MTP_PHASE_RESPONSE_QUEUED,
MTP_PHASE_ERROR,
@@ -690,7 +688,7 @@ typedef struct {
uint16_t* payload16;
uint32_t* payload32;
};
- uint32_t payload_size;
+ uint32_t payload_bytes; // available bytes for read/write
} mtp_container_info_t;
#define mtp_string_t(_nchars) \
@@ -899,7 +897,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_auint32(mtp_conta
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_get_string(uint8_t* buf, uint16_t utf16[]) {
uint8_t nchars = *buf++;
- memcpy(buf, utf16, nchars * 2);
+ memcpy(utf16, buf, 2 * nchars);
return 1 + nchars * 2;
}
diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c
index db562d0c7..6d1c7b29b 100644
--- a/src/class/mtp/mtp_device.c
+++ b/src/class/mtp/mtp_device.c
@@ -266,7 +266,8 @@ static bool mtpd_data_xfer(mtp_container_info_t* p_container, uint8_t ep_addr) {
p_container->header->transaction_id = p_mtp->command.transaction_id;
p_mtp->io_header = *p_container->header; // save header for subsequent data
} else {
- p_mtp->total_len = CFG_TUD_MTP_EP_BUFSIZE;
+ // OUT transfer: total length is at least max packet size
+ p_mtp->total_len = tu_max32(p_container->header->len, CFG_TUD_MTP_EP_BUFSIZE);
}
} else {
// subsequent data block: payload only
@@ -274,7 +275,10 @@ static bool mtpd_data_xfer(mtp_container_info_t* p_container, uint8_t ep_addr) {
}
const uint16_t xact_len = tu_min32(p_mtp->total_len - p_mtp->xferred_len, CFG_TUD_MTP_EP_BUFSIZE);
- TU_ASSERT(usbd_edpt_xfer(p_mtp->rhport, ep_addr, _mtpd_epbuf.buf, xact_len));
+ if (xact_len) {
+ // already transferred all bytes in header's length. Application make an unnecessary extra call
+ TU_ASSERT(usbd_edpt_xfer(p_mtp->rhport, ep_addr, _mtpd_epbuf.buf, xact_len));
+ }
return true;
}
@@ -310,13 +314,23 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
TU_LOG_DRV(" MTP %s phase = %u\r\n", (const char *) tu_lookup_find(&_mtp_op_table, p_mtp->command.code), p_mtp->phase);
#endif
+ const mtp_container_info_t headered_packet = {
+ .header = &p_container->header,
+ .payload32 = p_container->data,
+ .payload_bytes = CFG_TUD_MTP_EP_BUFSIZE - sizeof(mtp_container_header_t)
+ };
+
+ const mtp_container_info_t headerless_packet = {
+ .header = &p_mtp->io_header,
+ .payload = _mtpd_epbuf.buf,
+ .payload_bytes = CFG_TUD_MTP_EP_BUFSIZE
+ };
+
tud_mtp_cb_data_t cb_data;
cb_data.idx = 0;
cb_data.command_container = &p_mtp->command;
- cb_data.io_container.header = &p_container->header;
- cb_data.io_container.payload32 = p_container->data;
- cb_data.io_container.payload_size = CFG_TUD_MTP_EP_BUFSIZE - sizeof(mtp_container_header_t);
- cb_data.xferred_bytes = 0;
+ cb_data.io_container = headered_packet;
+ cb_data.total_xferred_bytes = 0;
cb_data.xfer_result = event;
switch (p_mtp->phase) {
@@ -339,7 +353,7 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
case MTP_PHASE_DATA: {
const uint16_t bulk_mps = (tud_speed_get() == TUSB_SPEED_HIGH) ? 512 : 64;
p_mtp->xferred_len += xferred_bytes;
- cb_data.xferred_bytes = p_mtp->xferred_len;
+ cb_data.total_xferred_bytes = p_mtp->xferred_len;
bool is_complete = false;
// complete if ZLP or short packet or overflow
@@ -349,12 +363,6 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
is_complete = true;
}
- const mtp_container_info_t headerless_packet = {
- .header = &p_mtp->io_header,
- .payload = _mtpd_epbuf.buf,
- .payload_size = CFG_TUD_MTP_EP_BUFSIZE
- };
-
if (ep_addr == p_mtp->ep_in) {
// Data In
if (is_complete) {
@@ -370,12 +378,17 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if (p_mtp->xferred_len == xferred_bytes) {
// 1st OUT packet: header + payload
p_mtp->io_header = p_container->header; // save header for subsequent transaction
+ cb_data.io_container.payload_bytes = xferred_bytes - sizeof(mtp_container_header_t);
} else {
// 2nd+ packet: payload only
cb_data.io_container = headerless_packet;
+ cb_data.io_container.payload_bytes = xferred_bytes;
}
tud_mtp_data_xfer_cb(&cb_data);
+
if (is_complete) {
+ // back to header + payload for response
+ cb_data.io_container = headered_packet;
cb_data.io_container.header->len = sizeof(mtp_container_header_t);
tud_mtp_data_complete_cb(&cb_data);
}
@@ -383,80 +396,6 @@ 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;
-
- // Check if transfer completed TODO check ZLP with FS/HS bulk size
- if (p_mtp->xferred_len >= p_mtp->total_len && (xferred_bytes == 0 || (xferred_bytes % CFG_MTP_EP_SIZE) != 0)) {
- p_mtp->phase = MTP_PHASE_RESPONSE;
- p_container->code = MTP_RESP_OK;
- p_container->len = MTP_CONTAINER_HEADER_LENGTH;
- if (p_mtp->session_id != 0) { // is this needed ?
- p_container->data[0] = p_mtp->session_id;
- p_container->len += sizeof(uint32_t);
- }
- } else {
- // Send next block of DATA
- if (p_mtp->xferred_len == p_mtp->total_len) {
- // send Zero-Length Packet
- TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, NULL, 0 ));
- } else {
- p_mtp->phase = mtpd_handle_data();
- if (p_mtp->phase == MTP_PHASE_DATA_IN) {
- TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, ((uint8_t *)(&p_container->data)), (uint16_t)p_mtp->queued_len));
- }
- }
- }
- break;
-
- case MTP_PHASE_DATA_OUT:
- // First block of data
- if (p_mtp->xferred_len == 0) {
- p_mtp->total_len = p_container->len;
- p_mtp->handled_len = 0;
- p_mtp->xfer_completed = false;
- TU_ASSERT(p_container->type == MTP_CONTAINER_TYPE_DATA_BLOCK);
- }
- p_mtp->xferred_len += xferred_bytes;
-
- // A zero-length or a short packet termination
- if (xferred_bytes < CFG_MTP_EP_SIZE) {
- p_mtp->xfer_completed = true;
- // Handle data block
- p_mtp->phase = mtpd_handle_data();
- if (p_mtp->phase == MTP_PHASE_DATA_OUT) {
- TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, (uint8_t*) p_container, sizeof(mtp_generic_container_t)), 0);
- p_mtp->xferred_len = 0;
- p_mtp->xfer_completed = false;
- }
- } else {
- // Handle data block when container is full
- if (p_mtp->xferred_len - p_mtp->handled_len >= MTP_MAX_PACKET_SIZE - CFG_MTP_EP_SIZE) {
- p_mtp->phase = mtpd_handle_data();
- p_mtp->handled_len = p_mtp->xferred_len;
- }
- // Transfer completed: wait for zero-length packet
- // Some platforms may not respect EP size and xferred_bytes may be more than CFG_MTP_EP_SIZE if
- // the OUT EP is waiting for more data. Ensure we are not waiting for more than CFG_MTP_EP_SIZE.
- if (p_mtp->total_len == p_mtp->xferred_len) {
- TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, ((uint8_t *)(&p_container->data)), CFG_MTP_EP_SIZE), 0);
- } 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,
- (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)));
- }
- }
- break;
-#endif
-
case MTP_PHASE_RESPONSE_QUEUED:
// response phase is complete -> prepare for new command
TU_ASSERT(ep_addr == p_mtp->ep_in);
@@ -574,76 +513,6 @@ mtp_phase_type_t mtpd_handle_cmd_delete_object(void)
return MTP_PHASE_RESPONSE;
}
-mtp_phase_type_t mtpd_handle_cmd_send_object_info(void)
-{
- mtp_generic_container_t* p_container = &_mtpd_epbuf.buf;
- _mtpd_soi.storage_id = p_container->data[0];
- _mtpd_soi.parent_object_handle = (p_container->data[1] == 0xFFFFFFFF ? 0 : p_container->data[1]);
-
- // Enter OUT phase and wait for DATA BLOCK
- return MTP_PHASE_DATA_OUT;
-}
-
-mtp_phase_type_t mtpd_handle_dto_send_object_info(void)
-{
- mtp_generic_container_t* p_container = &_mtpd_epbuf.buf;
- uint32_t new_object_handle = 0;
- 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);
- mtp_phase_type_t phase;
- if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase;
-
- // Save send_object_info
- _mtpd_soi.object_handle = new_object_handle;
-
- // Response
- p_container->len = MTP_CONTAINER_HEADER_LENGTH + 3 * sizeof(uint32_t);
- p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK;
- p_container->code = MTP_RESP_OK;
- p_container->data[0] = _mtpd_soi.storage_id;
- p_container->data[1] = _mtpd_soi.parent_object_handle;
- p_container->data[2] = _mtpd_soi.object_handle;
- return MTP_PHASE_RESPONSE;
-}
-
-mtp_phase_type_t mtpd_handle_cmd_send_object(void)
-{
- // Enter OUT phase and wait for DATA BLOCK
- return MTP_PHASE_DATA_OUT;
-}
-
-mtp_phase_type_t mtpd_handle_dto_send_object(void)
-{
- mtp_generic_container_t* p_container = &_mtpd_epbuf.buf;
- uint8_t *buffer = (uint8_t *)&p_container->data;
- uint32_t buffer_size = _mtpd_itf.xferred_len - _mtpd_itf.handled_len;
- // First block of DATA
- if (_mtpd_itf.handled_len == 0)
- {
- buffer_size -= MTP_CONTAINER_HEADER_LENGTH;
- }
-
- if (buffer_size > 0)
- {
- mtp_response_t res = tud_mtp_storage_object_write(_mtpd_soi.object_handle, buffer, buffer_size);
- mtp_phase_type_t phase;
- if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase;
- }
-
- if (!_mtpd_itf.xfer_completed)
- {
- // Continue with next DATA BLOCK
- return MTP_PHASE_DATA_OUT;
- }
-
- // Send completed
- tud_mtp_storage_object_done();
-
- p_container->len = MTP_CONTAINER_HEADER_LENGTH;
- p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK;
- p_container->code = MTP_RESP_OK;
- return MTP_PHASE_RESPONSE;
-}
-
mtp_phase_type_t mtpd_handle_cmd_format_store(void)
{
mtp_generic_container_t* p_container = &_mtpd_epbuf.buf;
diff --git a/src/class/mtp/mtp_device.h b/src/class/mtp/mtp_device.h
index 7b6ae9e0f..d0c894742 100644
--- a/src/class/mtp/mtp_device.h
+++ b/src/class/mtp/mtp_device.h
@@ -42,7 +42,7 @@ typedef struct {
mtp_container_info_t io_container;
tusb_xfer_result_t xfer_result;
- uint32_t xferred_bytes; // number of bytes transferred so far in this phase
+ uint32_t total_xferred_bytes; // number of bytes transferred so far in this phase
} tud_mtp_cb_data_t;
// Number of supported operations, events, device properties, capture formats, playback formats