From 85a19dea7239170dcfec7b4adb88e8a903d2411d Mon Sep 17 00:00:00 2001 From: Alex4386 Date: Mon, 10 Jun 2024 04:09:34 +0900 Subject: [PATCH] feat: `send_mtp_response_stream` now works. also, `send_mtp_response_buffer` now utilizes `send_mtp_response_stream` under the hood. --- src/scenes/mtp/mtp.c | 124 ++++++++++++++++++++----------------------- src/scenes/mtp/mtp.h | 6 +++ 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/src/scenes/mtp/mtp.c b/src/scenes/mtp/mtp.c index d27e12c..e9434b0 100644 --- a/src/scenes/mtp/mtp.c +++ b/src/scenes/mtp/mtp.c @@ -251,7 +251,7 @@ void handle_mtp_command(AppMTP* mtp, struct MTPContainer* container) { break; case MTP_OP_OPEN_SESSION: case MTP_OP_CLOSE_SESSION: - FURI_LOG_I("MTP", "Open/CloseSession operation (STUB)"); + //FURI_LOG_I("MTP", "Open/CloseSession operation (STUB)"); send_mtp_response(mtp, 3, MTP_RESP_OK, container->header.transaction_id, NULL); break; case MTP_OP_GET_STORAGE_IDS: @@ -260,17 +260,18 @@ void handle_mtp_command(AppMTP* mtp, struct MTPContainer* container) { break; case MTP_OP_GET_STORAGE_INFO: { FURI_LOG_I("MTP", "GetStorageInfo operation"); - uint8_t info[256]; + uint8_t* info = malloc(sizeof(uint8_t) * 256); int length = GetStorageInfo(mtp, container->params[0], info); send_mtp_response_buffer( mtp, MTP_TYPE_DATA, MTP_OP_GET_STORAGE_INFO, container->header.transaction_id, - (uint8_t*)&info, + info, length); send_mtp_response_buffer( mtp, MTP_TYPE_RESPONSE, MTP_RESP_OK, container->header.transaction_id, NULL, 0); + free(info); break; } case MTP_OP_GET_OBJECT_HANDLES: @@ -285,7 +286,7 @@ void handle_mtp_command(AppMTP* mtp, struct MTPContainer* container) { 0); break; } else { - uint8_t buffer[256]; + uint8_t* buffer = malloc(sizeof(uint8_t) * 256); int length = GetObjectHandles(mtp, container->params[0], container->params[2], buffer); send_mtp_response_buffer( mtp, @@ -297,6 +298,7 @@ void handle_mtp_command(AppMTP* mtp, struct MTPContainer* container) { send_mtp_response_buffer( mtp, MTP_TYPE_RESPONSE, MTP_RESP_OK, container->header.transaction_id, NULL, 0); + free(buffer); } break; case MTP_OP_GET_OBJECT_INFO: { @@ -384,27 +386,30 @@ void send_storage_ids(AppMTP* mtp, uint32_t transaction_id) { } void send_device_info(AppMTP* mtp, uint32_t transaction_id) { - uint8_t response[256]; + uint8_t* response = malloc(sizeof(uint8_t) * 256); int length = BuildDeviceInfo(response); send_mtp_response_buffer( mtp, MTP_TYPE_DATA, MTP_OP_GET_DEVICE_INFO, transaction_id, response, length); send_mtp_response_buffer(mtp, MTP_TYPE_RESPONSE, MTP_RESP_OK, transaction_id, NULL, 0); + free(response); } void send_device_prop_value(AppMTP* mtp, uint32_t transaction_id, uint32_t prop_code) { - uint8_t response[256]; + uint8_t* response = malloc(sizeof(uint8_t) * 256); int length = GetDevicePropValue(prop_code, response); send_mtp_response_buffer( mtp, MTP_TYPE_DATA, MTP_OP_GET_DEVICE_PROP_VALUE, transaction_id, response, length); send_mtp_response_buffer(mtp, MTP_TYPE_RESPONSE, MTP_RESP_OK, transaction_id, NULL, 0); + free(response); } void send_device_prop_desc(AppMTP* mtp, uint32_t transaction_id, uint32_t prop_code) { - uint8_t response[256]; + uint8_t* response = malloc(sizeof(uint8_t) * 256); int length = GetDevicePropDesc(prop_code, response); send_mtp_response_buffer( mtp, MTP_TYPE_DATA, MTP_OP_GET_DEVICE_PROP_DESC, transaction_id, response, length); send_mtp_response_buffer(mtp, MTP_TYPE_RESPONSE, MTP_RESP_OK, transaction_id, NULL, 0); + free(response); } char* get_path_from_handle(AppMTP* mtp, uint32_t handle) { @@ -768,13 +773,15 @@ void send_mtp_response_stream( uint8_t* ptr = buffer; uint32_t sent_length = 0; + FURI_LOG_I("MTP", "Sending MTP response stream: %ld bytes", length); - while(sent_length < length + sizeof(struct MTPHeader)) { + do { buffer_available = MTP_MAX_PACKET_SIZE; + ptr = buffer; // reset the pointer if(chunk_idx == 0) { struct MTPHeader* hdr = (struct MTPHeader*)buffer; - hdr->len = length; + hdr->len = length + sizeof(*hdr); hdr->type = resp_type; hdr->op = resp_code; hdr->transaction_id = transaction_id; @@ -783,16 +790,46 @@ void send_mtp_response_stream( buffer_available -= sizeof(*hdr); } + FURI_LOG_I("MTP", "Remaining bytes for packet: %d", buffer_available); + int read_bytes = callback(callback_context, ptr, buffer_available); uint32_t usb_bytes = (ptr - buffer) + read_bytes; + FURI_LOG_I("MTP", "USB packet size: %ld", usb_bytes); + usbd_ep_write(mtp->dev, MTP_EP_IN_ADDR, buffer, usb_bytes); sent_length += usb_bytes; - } + chunk_idx++; + + FURI_LOG_I( + "MTP", + "Sent chunk %d (currently sent: %ld/%ld)", + chunk_idx, + sent_length - sizeof(struct MTPHeader), + length); + } while(sent_length < length + sizeof(struct MTPHeader)); free(buffer); } +int send_mtp_response_buffer_callback(void* ctx, uint8_t* buffer, int size) { + struct MTPResponseBufferContext* context = (struct MTPResponseBufferContext*)ctx; + if(context->buffer == NULL || context->size == 0) { + return 0; + } + + uint32_t remaining = context->size - context->sent; + uint32_t to_send = size; + if(remaining < to_send) { + to_send = remaining; + } + + memcpy(buffer, context->buffer + context->sent, to_send); + context->sent += to_send; + + return to_send; +} + void send_mtp_response_buffer( AppMTP* mtp, uint16_t resp_type, @@ -800,62 +837,14 @@ void send_mtp_response_buffer( uint32_t transaction_id, uint8_t* buffer, uint32_t size) { - size_t target_size = size + sizeof(struct MTPHeader); - struct MTPHeader header = { - .len = target_size, - .type = resp_type, - .op = resp_code, - .transaction_id = transaction_id, - }; - - // Send the response in one go - /* - uint8_t* response = malloc(target_size); - memcpy(response, &header, sizeof(header)); - memcpy(response + sizeof(header), buffer, size); + struct MTPResponseBufferContext* ctx = malloc(sizeof(struct MTPResponseBufferContext)); + ctx->buffer = buffer; + ctx->size = size; + ctx->sent = 0; - usbd_ep_write(mtp->dev, MTP_EP_OUT_ADDR, response, target_size); - */ - - // Send the response in chunks - int chunk_count = (target_size / MTP_MAX_PACKET_SIZE) + 1; - FURI_LOG_I("MTP", "Sending MTP response: %d bytes in %d chunks", target_size, chunk_count); - uint8_t* ptr = buffer; - - mtp->write_pending = true; - - for(int i = 0; i < chunk_count; i++) { - FURI_LOG_I("MTP", "Sending chunk %d/%d", i + 1, chunk_count); - mtp->write_pending = true; - size_t chunk_size = (i == chunk_count - 1) ? target_size % MTP_MAX_PACKET_SIZE : - MTP_MAX_PACKET_SIZE; - - uint8_t* buf = NULL; - - if(i == 0) { - // first send header - buf = malloc(chunk_size); - FURI_LOG_I("MTP", "1st chunk! size = %d", chunk_size); - memcpy(buf, &header, sizeof(header)); - memcpy(buf + sizeof(header), ptr, chunk_size - sizeof(header)); - usbd_ep_write(mtp->dev, MTP_EP_IN_ADDR, buf, chunk_size); - ptr += chunk_size - sizeof(header); - } else { - usbd_ep_write(mtp->dev, MTP_EP_IN_ADDR, ptr, chunk_size); - ptr += chunk_size; - } - - FURI_LOG_I( - "MTP", - "Sent chunk %d/%d (offset: %d)", - i + 1, - chunk_count, - ptr - buffer + sizeof(header)); - - if(buf != NULL) { - free(buf); - } - } + send_mtp_response_stream( + mtp, resp_type, resp_code, transaction_id, ctx, send_mtp_response_buffer_callback, size); + free(ctx); } void send_mtp_response( @@ -1016,6 +1005,7 @@ int GetStorageInfo(AppMTP* mtp, uint32_t storage_id, uint8_t* buf) { info->free_space_in_objects = 20ul; info->filesystem_type = 0x0002; // Generic hierarchical info->access_capability = 0x0000; // Read-write + FURI_LOG_I("MTP", "Getting storage info for storage ID %04lx", storage_id); if(storage_id == INTERNAL_STORAGE_ID) { // Fill in details for internal storage @@ -1076,6 +1066,9 @@ void WriteMTPString(uint8_t* buffer, const char* str, uint16_t* length) { uint8_t* ptr = buffer; uint8_t str_len = strlen(str); + FURI_LOG_I("MTP", "Writing MTP string: %s", str); + FURI_LOG_I("MTP", "String length: %d", str_len); + // extra handling for empty string if(str_len == 0) { *ptr = 0x00; @@ -1094,6 +1087,7 @@ void WriteMTPString(uint8_t* buffer, const char* str, uint16_t* length) { *ptr++ = 0x00; // Null terminator (UTF-16LE) *ptr++ = 0x00; + FURI_LOG_I("MTP", "String byte length: %d", ptr - buffer); *length = ptr - buffer; } diff --git a/src/scenes/mtp/mtp.h b/src/scenes/mtp/mtp.h index 867f1fc..bc3b8dc 100644 --- a/src/scenes/mtp/mtp.h +++ b/src/scenes/mtp/mtp.h @@ -182,3 +182,9 @@ char* get_base_path_from_storage_id(uint32_t storage_id); char* get_path_from_handle(AppMTP* mtp, uint32_t handle); uint32_t issue_object_handle(AppMTP* mtp, char* path); void handle_mtp_data_complete(AppMTP* mtp); + +struct MTPResponseBufferContext { + uint8_t* buffer; + uint32_t size; + uint32_t sent; +};