From 283b06bb543f513d964dc3a6953115df897a93a1 Mon Sep 17 00:00:00 2001 From: Maurizio Pesce Date: Wed, 12 Mar 2025 09:50:04 +0100 Subject: Add MTP class device --- src/device/usbd.c | 13 +++++++++++++ src/device/usbd.h | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index fb5cec49d..8f50d815f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -309,6 +309,19 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .sof = NULL }, #endif + + #if CFG_TUD_MTP + { + .name = DRIVER_NAME("MTP"), + .init = mtpd_init, + .deinit = mtpd_deinit, + .reset = mtpd_reset, + .open = mtpd_open, + .control_xfer_cb = mtpd_control_xfer_cb, + .xfer_cb = mtpd_xfer_cb, + .sof = NULL + }, + #endif }; enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index de6007fb3..b89a0200b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -269,6 +269,25 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 +//--------------------------------------------------------------------+ +// MTP Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor: 30 bytes +#define TUD_MTP_DESC_LEN (9 + 7 + 7 + 7) + +// Interface number, string index, EP Out & EP In address, EP size +#define TUD_MTP_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_polling_interval, _epout, _epin, _epsize) \ + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUSB_CLASS_IMAGE, MTP_SUBCLASS, MTP_PROTOCOL_STILL_IMAGE, _stridx,\ + /* Endpoint Interrupt */\ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_polling_interval,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + //--------------------------------------------------------------------+ // HID Descriptor Templates //--------------------------------------------------------------------+ -- cgit v1.3.1 From 802819d271314298ea5a786a37ec6a1e65ef31d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Sep 2025 17:13:52 +0700 Subject: add all constant from MTP specs appendix, rename some e.g OPEC to OP, EVTC to EVENT --- examples/device/CMakeLists.txt | 1 + examples/device/mtp/src/mtp_fs_example.c | 92 ++-- src/class/mtp/mtp.h | 748 +++++++++++++++++++++++-------- src/class/mtp/mtp_device.c | 146 +++--- src/device/usbd.h | 2 +- 5 files changed, 682 insertions(+), 307 deletions(-) (limited to 'src/device') diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index bb7dd0a0f..eb625ea51 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -26,6 +26,7 @@ family_add_subdirectory(hid_generic_inout) family_add_subdirectory(hid_multiple_interface) family_add_subdirectory(midi_test) family_add_subdirectory(msc_dual_lun) +family_add_subdirectory(mtp) family_add_subdirectory(net_lwip_webserver) family_add_subdirectory(uac2_headset) family_add_subdirectory(uac2_speaker_fb) diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c index 41673ea53..87730bcd3 100644 --- a/examples/device/mtp/src/mtp_fs_example.c +++ b/examples/device/mtp/src/mtp_fs_example.c @@ -130,17 +130,17 @@ mtp_response_t tud_mtp_storage_open_session(uint32_t *session_id) if (*session_id == 0) { TU_LOG1("Invalid session ID\r\n"); - return MTP_RESC_INVALID_PARAMETER; + return MTP_RESP_INVALID_PARAMETER; } if (_fs_operation.session_id != 0) { *session_id = _fs_operation.session_id; TU_LOG1("ERR: Session %ld already open\r\n", _fs_operation.session_id); - return MTP_RESC_SESSION_ALREADY_OPEN; + return MTP_RESP_SESSION_ALREADY_OPEN; } _fs_operation.session_id = *session_id; TU_LOG1("Open session with id %ld\r\n", _fs_operation.session_id); - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_close_session(uint32_t session_id) @@ -148,11 +148,11 @@ mtp_response_t tud_mtp_storage_close_session(uint32_t session_id) if (session_id != _fs_operation.session_id) { TU_LOG1("ERR: Session %ld not open\r\n", session_id); - return MTP_RESC_SESSION_NOT_OPEN; + return MTP_RESP_SESSION_NOT_OPEN; } _fs_operation.session_id = 0; TU_LOG1("Session closed\r\n"); - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_get_storage_id(uint32_t *storage_id) @@ -160,11 +160,11 @@ mtp_response_t tud_mtp_get_storage_id(uint32_t *storage_id) if (_fs_operation.session_id == 0) { TU_LOG1("ERR: Session not open\r\n"); - return MTP_RESC_SESSION_NOT_OPEN; + return MTP_RESP_SESSION_NOT_OPEN; } *storage_id = STORAGE_ID(0x0001, 0x0001); TU_LOG1("Retrieved storage identifier %ld\r\n", *storage_id); - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_get_storage_info(uint32_t storage_id, mtp_storage_info_t *info) @@ -172,12 +172,12 @@ mtp_response_t tud_mtp_get_storage_info(uint32_t storage_id, mtp_storage_info_t if (_fs_operation.session_id == 0) { TU_LOG1("ERR: Session not open\r\n"); - return MTP_RESC_SESSION_NOT_OPEN; + return MTP_RESP_SESSION_NOT_OPEN; } if (storage_id != STORAGE_ID(0x0001, 0x0001)) { TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id); - return MTP_RESC_INVALID_STORAGE_ID; + return MTP_RESP_INVALID_STORAGE_ID; } info->storage_type = MTP_STORAGE_TYPE_FIXED_RAM; info->filesystem_type = MTP_FILESYSTEM_TYPE_GENERIC_HIERARCHICAL; @@ -187,7 +187,7 @@ mtp_response_t tud_mtp_get_storage_info(uint32_t storage_id, mtp_storage_info_t info->free_space_in_bytes = info->free_space_in_objects * FS_MAX_NODE_BYTES; mtpd_gct_append_wstring(MTPD_STORAGE_DESCRIPTION); mtpd_gct_append_wstring(MTPD_VOLUME_IDENTIFIER); - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_format(uint32_t storage_id) @@ -195,19 +195,19 @@ 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_RESC_SESSION_NOT_OPEN; + return MTP_RESP_SESSION_NOT_OPEN; } if (storage_id != STORAGE_ID(0x0001, 0x0001)) { TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id); - return MTP_RESC_INVALID_STORAGE_ID; + return MTP_RESP_INVALID_STORAGE_ID; } // Simply deallocate all entries for (unsigned int i=0; ihandle; TU_LOG1("Association %ld -> child %ld\r\n", parent_object_handle, obj->handle); - return MTP_RESC_OK; + return MTP_RESP_OK; } } TU_LOG1("Association traversal completed\r\n"); _fs_operation.traversal_index = 0; *next_child_handle = 0; - return MTP_RESC_OK; + return MTP_RESP_OK; } 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) @@ -261,19 +261,19 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p if (_fs_operation.session_id == 0) { TU_LOG1("ERR: Session not open\r\n"); - return MTP_RESC_SESSION_NOT_OPEN; + return MTP_RESP_SESSION_NOT_OPEN; } // Accept command on default storage if (storage_id != 0xFFFFFFFF && storage_id != STORAGE_ID(0x0001, 0x0001)) { TU_LOG1("ERR: Unexpected storage id %ld\r\n", storage_id); - return MTP_RESC_INVALID_STORAGE_ID; + return MTP_RESP_INVALID_STORAGE_ID; } 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_RESC_STORE_FULL; + return MTP_RESP_STORE_FULL; } // Request for objects with no parent (0xFFFFFFFF) are considered root objects @@ -287,12 +287,12 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p if (obj == NULL) { TU_LOG1("Parent %ld does not exist\r\n", parent_object); - return MTP_RESC_INVALID_PARENT_OBJECT; + return MTP_RESP_INVALID_PARENT_OBJECT; } if (!obj->association) { TU_LOG1("Parent %ld is not an association\r\n", parent_object); - return MTP_RESC_INVALID_PARENT_OBJECT; + return MTP_RESP_INVALID_PARENT_OBJECT; } } @@ -309,7 +309,7 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p if (obj == NULL) { TU_LOG1("No space left on device\r\n"); - return MTP_RESC_STORE_FULL; + return MTP_RESP_STORE_FULL; } // Fill-in structure @@ -317,7 +317,7 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p obj->handle = ++_fs_operation.last_handle; obj->parent = parent_object; obj->size = info->object_compressed_size; - obj->association = info->object_format == MTP_OBJF_ASSOCIATION; + obj->association = info->object_format == MTP_OBJ_FORMAT_ASSOCIATION; // Extract variable data uint16_t offset_data = sizeof(mtp_object_info_t); @@ -332,7 +332,7 @@ mtp_response_t tud_mtp_storage_object_write_info(uint32_t storage_id, uint32_t p // Initialize operation _fs_operation.write_handle = obj->handle; _fs_operation.write_pos = 0; - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_object_read_info(uint32_t object_handle, mtp_object_info_t *info) @@ -342,33 +342,33 @@ mtp_response_t tud_mtp_storage_object_read_info(uint32_t object_handle, mtp_obje if (_fs_operation.session_id == 0) { TU_LOG1("ERR: Session not open\r\n"); - return MTP_RESC_SESSION_NOT_OPEN; + return MTP_RESP_SESSION_NOT_OPEN; } obj = fs_object_get_from_handle(object_handle); if (obj == NULL) { TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle); - return MTP_RESC_INVALID_OBJECT_HANDLE; + return MTP_RESP_INVALID_OBJECT_HANDLE; } memset(info, 0, sizeof(mtp_object_info_t)); info->storage_id = STORAGE_ID(0x0001, 0x0001); if (obj->association) { - info->object_format = MTP_OBJF_ASSOCIATION; + info->object_format = MTP_OBJ_FORMAT_ASSOCIATION; info->protection_status = MTP_PROTECTION_STATUS_NO_PROTECTION; info->object_compressed_size = 0; info->association_type = MTP_ASSOCIATION_UNDEFINED; } else { - info->object_format = MTP_OBJF_UNDEFINED; + info->object_format = MTP_OBJ_FORMAT_UNDEFINED; info->protection_status = MTP_PROTECTION_STATUS_NO_PROTECTION; info->object_compressed_size = obj->size; info->association_type = MTP_ASSOCIATION_UNDEFINED; } - info->thumb_format = MTP_OBJF_UNDEFINED; + info->thumb_format = MTP_OBJ_FORMAT_UNDEFINED; info->parent_object = obj->parent; mtpd_gct_append_wstring(obj->name); @@ -378,7 +378,7 @@ mtp_response_t tud_mtp_storage_object_read_info(uint32_t object_handle, mtp_obje TU_LOG1("Retrieve object %s with handle %ld\r\n", obj->name, obj->handle); - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_object_write(uint32_t object_handle, const uint8_t *buffer, uint32_t size) @@ -389,17 +389,17 @@ mtp_response_t tud_mtp_storage_object_write(uint32_t object_handle, const uint8_ if (obj == NULL) { TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle); - return MTP_RESC_INVALID_OBJECT_HANDLE; + return MTP_RESP_INVALID_OBJECT_HANDLE; } // 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_RESC_NO_VALID_OBJECTINFO; + return MTP_RESP_NO_VALID_OBJECTINFO; } 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_RESC_INCOMPLETE_TRANSFER); + 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; @@ -409,7 +409,7 @@ mtp_response_t tud_mtp_storage_object_write(uint32_t object_handle, const uint8_ _fs_operation.write_handle = 0; _fs_operation.write_pos = 0; } - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_object_size(uint32_t object_handle, uint32_t *size) @@ -419,10 +419,10 @@ mtp_response_t tud_mtp_storage_object_size(uint32_t object_handle, uint32_t *siz if (obj == NULL) { TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle); - return MTP_RESC_INVALID_OBJECT_HANDLE; + return MTP_RESP_INVALID_OBJECT_HANDLE; } *size = obj->size; - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_object_read(uint32_t object_handle, void *buffer, uint32_t buffer_size, uint32_t *read_count) @@ -434,7 +434,7 @@ mtp_response_t tud_mtp_storage_object_read(uint32_t object_handle, void *buffer, if (obj == NULL) { TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle); - return MTP_RESC_INVALID_OBJECT_HANDLE; + return MTP_RESP_INVALID_OBJECT_HANDLE; } // It's not a requirement that this command is preceded by a read info if (object_handle != _fs_operation.read_handle) @@ -462,7 +462,7 @@ mtp_response_t tud_mtp_storage_object_read(uint32_t object_handle, void *buffer, _fs_operation.read_handle = 0; _fs_operation.read_pos = 0; } - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_object_move(uint32_t object_handle, uint32_t new_parent_object_handle) @@ -479,12 +479,12 @@ mtp_response_t tud_mtp_storage_object_move(uint32_t object_handle, uint32_t new_ if (obj == NULL) { TU_LOG1("Parent %ld does not exist\r\n", new_parent_object_handle); - return MTP_RESC_INVALID_PARENT_OBJECT; + return MTP_RESP_INVALID_PARENT_OBJECT; } if (!obj->association) { TU_LOG1("Parent %ld is not an association\r\n", new_parent_object_handle); - return MTP_RESC_INVALID_PARENT_OBJECT; + return MTP_RESP_INVALID_PARENT_OBJECT; } } @@ -493,11 +493,11 @@ mtp_response_t tud_mtp_storage_object_move(uint32_t object_handle, uint32_t new_ if (obj == NULL) { TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle); - return MTP_RESC_INVALID_OBJECT_HANDLE; + return MTP_RESP_INVALID_OBJECT_HANDLE; } TU_LOG1("Move object %ld to new parent %ld\r\n", object_handle, new_parent_object_handle); obj->parent = new_parent_object_handle; - return MTP_RESC_OK; + return MTP_RESP_OK; } mtp_response_t tud_mtp_storage_object_delete(uint32_t object_handle) @@ -507,7 +507,7 @@ mtp_response_t tud_mtp_storage_object_delete(uint32_t object_handle) if (_fs_operation.session_id == 0) { TU_LOG1("ERR: Session not open\r\n"); - return MTP_RESC_SESSION_NOT_OPEN; + return MTP_RESP_SESSION_NOT_OPEN; } if (object_handle == 0xFFFFFFFF) @@ -520,7 +520,7 @@ mtp_response_t tud_mtp_storage_object_delete(uint32_t object_handle) if (obj == NULL) { TU_LOG1("ERR: Object with handle %ld does not exist\r\n", object_handle); - return MTP_RESC_INVALID_OBJECT_HANDLE; + return MTP_RESP_INVALID_OBJECT_HANDLE; } obj->allocated = false; TU_LOG1("Delete object with handle %ld\r\n", object_handle); @@ -539,7 +539,7 @@ mtp_response_t tud_mtp_storage_object_delete(uint32_t object_handle) } } - return MTP_RESC_OK; + return MTP_RESP_OK; } void tud_mtp_storage_object_done(void) diff --git a/src/class/mtp/mtp.h b/src/class/mtp/mtp.h index 33c6bb552..b5db2cd6c 100644 --- a/src/class/mtp/mtp.h +++ b/src/class/mtp/mtp.h @@ -47,20 +47,17 @@ typedef uint16_t wchar16_t; //--------------------------------------------------------------------+ // Media Transfer Protocol Subclass -typedef enum -{ - MTP_SUBCLASS = 1 +typedef enum { + MTP_SUBCLASS_STILL_IMAGE = 1 } mtp_subclass_type_t; // MTP Protocol. -typedef enum -{ - MTP_PROTOCOL_STILL_IMAGE = 1, +typedef enum { + MTP_PROTOCOL_PIMA_15470 = 1, ///< Picture Transfer Protocol (PIMA 15470) } mtp_protocol_type_t; // PTP/MTP protocol phases -typedef enum -{ +typedef enum { MTP_PHASE_IDLE = 0, MTP_PHASE_COMMAND, MTP_PHASE_DATA_IN, @@ -70,7 +67,7 @@ typedef enum MTP_PHASE_NONE, } mtp_phase_type_t; -// PTP/MTP Class requests +// PTP/MTP Class requests, PIMA 15740-2000: D.5.2 typedef enum { MTP_REQ_CANCEL = 0x64, @@ -79,19 +76,6 @@ typedef enum MTP_REQ_GET_DEVICE_STATUS = 0x67, } mtp_class_request_t; -#define MTP_GENERIC_DATA_BLOCK_LENGTH 12 -#define MTP_MAX_PACKET_SIZE 512 - -// PTP/MTP Generic container -typedef struct TU_ATTR_PACKED -{ - uint32_t container_length; - uint16_t container_type; - uint16_t code; - uint32_t transaction_id; - uint32_t data[MTP_MAX_PACKET_SIZE / sizeof(uint32_t)]; -} mtp_generic_container_t; - // PTP/MTP Container type typedef enum { @@ -102,85 +86,493 @@ typedef enum MTP_CONTAINER_TYPE_EVENT_BLOCK = 4, } mtp_container_type_t; -// Supported OperationCode +// MTP 1.1 Appendix A: Object formats typedef enum { - MTP_OPEC_GET_DEVICE_INFO = 0x1001u, - MTP_OPEC_OPEN_SESSION = 0x1002u, - MTP_OPEC_CLOSE_SESSION = 0x1003u, - MTP_OPEC_GET_STORAGE_IDS = 0x1004u, - MTP_OPEC_GET_STORAGE_INFO = 0x1005u, - MTP_OPEC_GET_NUM_OBJECTS = 0x1006u, - MTP_OPEC_GET_OBJECT_HANDLES = 0x1007u, - MTP_OPEC_GET_OBJECT_INFO = 0x1008u, - MTP_OPEC_GET_OBJECT = 0x1009u, - MTP_OPEC_GET_THUMB = 0x100Au, - MTP_OPEC_DELETE_OBJECT = 0x100Bu, - MTP_OPEC_SEND_OBJECT_INFO = 0x100Cu, - MTP_OPEC_SEND_OBJECT = 0x100Du, - MTP_OPEC_INITIAL_CAPTURE = 0x100Eu, - MTP_OPEC_FORMAT_STORE = 0x100Fu, - MTP_OPEC_RESET_DEVICE = 0x1010u, - MTP_OPEC_SELF_TEST = 0x1011u, - MTP_OPEC_SET_OBJECT_PROTECTION = 0x1012u, - MTP_OPEC_POWER_DOWN = 0x1013u, - MTP_OPEC_GET_DEVICE_PROP_DESC = 0x1014u, - MTP_OPEC_GET_DEVICE_PROP_VALUE = 0x1015u, - MTP_OPEC_SET_DEVICE_PROP_VALUE = 0x1016u, - MTP_OPEC_RESET_DEVICE_PROP_VALUE = 0x1017u, - MTP_OPEC_TERMINATE_OPEN_CAPTURE = 0x1018u, - MTP_OPEC_MOVE_OBJECT = 0x1019u, - MTP_OPEC_COPY_OBJECT = 0x101Au, - MTP_OPEC_GET_PARTIAL_OBJECT = 0x101Bu, - MTP_OPEC_INITIATE_OPEN_CAPTURE = 0x101Bu, - MTP_OPEC_GET_OBJECT_PROPS_SUPPORTED = 0x9801u, - MTP_OPEC_GET_OBJECT_PROP_DESC = 0x9802u, - MTP_OPEC_GET_OBJECT_PROP_VALUE = 0x9803u, - MTP_OPEC_SET_OBJECT_PROP_VALUE = 0x9804u, - MTP_OPEC_GET_OBJECT_PROPLIST = 0x9805u, - MTP_OPEC_GET_OBJECT_PROP_REFERENCES = 0x9810u, - MTP_OPEC_GETSERVICEIDS = 0x9301u, - MTP_OPEC_GETSERVICEINFO = 0x9302u, - MTP_OPEC_GETSERVICECAPABILITIES = 0x9303u, - MTP_OPEC_GETSERVICEPROPDESC = 0x9304u, -} mtp_operation_code_t; + // ---- Base formats ---- + MTP_OBJ_FORMAT_UNDEFINED = 0x3000u, // Undefined object + MTP_OBJ_FORMAT_ASSOCIATION = 0x3001u, // Association (for example, a folder) + MTP_OBJ_FORMAT_SCRIPT = 0x3002u, // Device model-specific script + MTP_OBJ_FORMAT_EXECUTABLE = 0x3003u, // Device model-specific binary executable + MTP_OBJ_FORMAT_TEXT = 0x3004u, // Text file + MTP_OBJ_FORMAT_HTML = 0x3005u, // Hypertext Markup Language file (text) + MTP_OBJ_FORMAT_DPOF = 0x3006u, // Digital Print Order Format file (text) + MTP_OBJ_FORMAT_AIFF = 0x3007u, // Audio clip (AIFF) + MTP_OBJ_FORMAT_WAV = 0x3008u, // Audio clip (WAV) + MTP_OBJ_FORMAT_MP3 = 0x3009u, // MPEG-1 Layer III audio (ISO/IEC 13818-3) + MTP_OBJ_FORMAT_AVI = 0x300Au, // Video clip (AVI) + MTP_OBJ_FORMAT_MPEG = 0x300Bu, // Video clip (MPEG) + MTP_OBJ_FORMAT_ASF = 0x300Cu, // Microsoft Advanced Streaming Format (video) + + // ---- Image formats ---- + MTP_OBJ_FORMAT_UNDEFINED_IMAGE = 0x3800u, // Undefined image object + MTP_OBJ_FORMAT_EXIF_JPEG = 0x3801u, // Exchangeable Image Format, JEIDA standard + MTP_OBJ_FORMAT_TIFF_EP = 0x3802u, // Tag Image File Format for Electronic Photography + MTP_OBJ_FORMAT_FLASHPIX = 0x3803u, // Structured Storage Image Format (FlashPix) + MTP_OBJ_FORMAT_BMP = 0x3804u, // Microsoft Windows Bitmap file + MTP_OBJ_FORMAT_CIFF = 0x3805u, // Canon Camera Image File Format + MTP_OBJ_FORMAT_UNDEFINED_3806 = 0x3806u, // Reserved / Undefined + MTP_OBJ_FORMAT_GIF = 0x3807u, // Graphics Interchange Format + MTP_OBJ_FORMAT_JFIF = 0x3808u, // JPEG File Interchange Format + MTP_OBJ_FORMAT_CD = 0x3809u, // PhotoCD Image Pac + MTP_OBJ_FORMAT_PICT = 0x380Au, // Quickdraw Image Format + MTP_OBJ_FORMAT_PNG = 0x380Bu, // Portable Network Graphics + MTP_OBJ_FORMAT_UNDEFINED_380C = 0x380Cu, // Reserved / Undefined + MTP_OBJ_FORMAT_TIFF = 0x380Du, // Tag Image File Format (baseline) + MTP_OBJ_FORMAT_TIFF_IT = 0x380Eu, // Tag Image File Format for IT (graphic arts) + MTP_OBJ_FORMAT_JP2 = 0x380Fu, // JPEG2000 Baseline File Format + MTP_OBJ_FORMAT_JPX = 0x3810u, // JPEG2000 Extended File Format + + // ---- Firmware & misc ---- + MTP_OBJ_FORMAT_UNDEFINED_FIRMWARE = 0xB802u, // Undefined Firmware + MTP_OBJ_FORMAT_WBMP = 0xB803u, // Wireless Application Protocol Bitmap Format (.wbmp) + MTP_OBJ_FORMAT_WINDOWS_IMAGE = 0xB881u, // Windows Image Format + MTP_OBJ_FORMAT_JPEGXR = 0xB804u, // JPEG XR (.hdp, .jxr, .wdp) + + // ---- Audio formats ---- + MTP_OBJ_FORMAT_UNDEFINED_AUDIO = 0xB900u, // Undefined audio object + MTP_OBJ_FORMAT_WMA = 0xB901u, // Windows Media Audio + MTP_OBJ_FORMAT_OGG = 0xB902u, // OGG container + MTP_OBJ_FORMAT_AAC = 0xB903u, // Advanced Audio Coding (.aac) + MTP_OBJ_FORMAT_AUDIBLE = 0xB904u, // Audible format + MTP_OBJ_FORMAT_FLAC = 0xB906u, // Free Lossless Audio Codec + MTP_OBJ_FORMAT_QCELP = 0xB907u, // Qualcomm Code Excited Linear Prediction (.qcp) + MTP_OBJ_FORMAT_AMR = 0xB908u, // Adaptive Multi-Rate audio (.amr) + + // ---- Video formats ---- + MTP_OBJ_FORMAT_UNDEFINED_VIDEO = 0xB980u, // Undefined video object + MTP_OBJ_FORMAT_WMV = 0xB981u, // Windows Media Video + MTP_OBJ_FORMAT_MP4 = 0xB982u, // MP4 Container (ISO 14496-1) + MTP_OBJ_FORMAT_MP2 = 0xB983u, // MPEG-1 Layer II audio + MTP_OBJ_FORMAT_3GP = 0xB984u, // 3GP Container + MTP_OBJ_FORMAT_3G2 = 0xB985u, // 3GPP2 Container + MTP_OBJ_FORMAT_AVCHD = 0xB986u, // AVCHD (MPEG-4 AVC + Dolby Digital) + MTP_OBJ_FORMAT_ATSC_TS = 0xB987u, // ATSC-compliant MPEG-2 Transport Stream + MTP_OBJ_FORMAT_DVB_TS = 0xB988u, // DVB-compliant MPEG-2 Transport Stream + + // ---- Collections ---- + MTP_OBJ_FORMAT_UNDEFINED_COLLECTION = 0xBA00u, // Undefined collection + MTP_OBJ_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM = 0xBA01u, // Abstract Multimedia Album + MTP_OBJ_FORMAT_ABSTRACT_IMAGE_ALBUM = 0xBA02u, // Abstract Image Album + MTP_OBJ_FORMAT_ABSTRACT_AUDIO_ALBUM = 0xBA03u, // Abstract Audio Album + MTP_OBJ_FORMAT_ABSTRACT_VIDEO_ALBUM = 0xBA04u, // Abstract Video Album + MTP_OBJ_FORMAT_ABSTRACT_AV_PLAYLIST = 0xBA05u, // Abstract Audio & Video Playlist + MTP_OBJ_FORMAT_ABSTRACT_CONTACT_GROUP = 0xBA06u, // Abstract Contact Group + MTP_OBJ_FORMAT_ABSTRACT_MESSAGE_FOLDER = 0xBA07u, // Abstract Message Folder + MTP_OBJ_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION = 0xBA08u, // Abstract Chaptered Production + MTP_OBJ_FORMAT_ABSTRACT_AUDIO_PLAYLIST = 0xBA09u, // Abstract Audio Playlist + MTP_OBJ_FORMAT_ABSTRACT_VIDEO_PLAYLIST = 0xBA0Au, // Abstract Video Playlist + MTP_OBJ_FORMAT_ABSTRACT_MEDIACAST = 0xBA0Bu, // Abstract Mediacast (RSS enclosure) + + // ---- Playlist formats ---- + MTP_OBJ_FORMAT_WPL_PLAYLIST = 0xBA10u, // Windows Media Player Playlist (.wpl) + MTP_OBJ_FORMAT_M3U_PLAYLIST = 0xBA11u, // M3U Playlist + MTP_OBJ_FORMAT_MPL_PLAYLIST = 0xBA12u, // MPL Playlist + MTP_OBJ_FORMAT_ASX_PLAYLIST = 0xBA13u, // ASX Playlist + MTP_OBJ_FORMAT_PLS_PLAYLIST = 0xBA14u, // PLS Playlist + + // ---- Document formats ---- + MTP_OBJ_FORMAT_UNDEFINED_DOC = 0xBA80u, // Undefined Document + MTP_OBJ_FORMAT_ABSTRACT_DOC = 0xBA81u, // Abstract Document + MTP_OBJ_FORMAT_XML_DOC = 0xBA82u, // XML Document + MTP_OBJ_FORMAT_DOC = 0xBA83u, // Microsoft Word Document + MTP_OBJ_FORMAT_MHT_DOC = 0xBA84u, // MHT Compiled HTML Document + MTP_OBJ_FORMAT_XLS = 0xBA85u, // Microsoft Excel Spreadsheet + MTP_OBJ_FORMAT_PPT = 0xBA86u, // Microsoft PowerPoint Presentation + + // ---- Messaging ---- + MTP_OBJ_FORMAT_UNDEFINED_MSG = 0xBB00u, // Undefined Message + MTP_OBJ_FORMAT_ABSTRACT_MSG = 0xBB01u, // Abstract Message + + // ---- Bookmarks ---- + MTP_OBJ_FORMAT_UNDEFINED_BOOKMARK = 0xBB10u, // Undefined Bookmark + MTP_OBJ_FORMAT_ABSTRACT_BOOKMARK = 0xBB11u, // Abstract Bookmark + + // ---- Appointments ---- + MTP_OBJ_FORMAT_UNDEFINED_APPT = 0xBB20u, // Undefined Appointment + MTP_OBJ_FORMAT_ABSTRACT_APPT = 0xBB21u, // Abstract Appointment + MTP_OBJ_FORMAT_VCALENDAR1 = 0xBB22u, // vCalendar 1.0 + + // ---- Tasks ---- + MTP_OBJ_FORMAT_UNDEFINED_TASK = 0xBB40u, // Undefined Task + MTP_OBJ_FORMAT_ABSTRACT_TASK = 0xBB41u, // Abstract Task + MTP_OBJ_FORMAT_ICALENDAR = 0xBB42u, // iCalendar + + // ---- Notes ---- + MTP_OBJ_FORMAT_UNDEFINED_NOTE = 0xBB60u, // Undefined Note + MTP_OBJ_FORMAT_ABSTRACT_NOTE = 0xBB61u, // Abstract Note + + // ---- Contacts ---- + MTP_OBJ_FORMAT_UNDEFINED_CONTACT= 0xBB80u, // Undefined Contact + MTP_OBJ_FORMAT_ABSTRACT_CONTACT = 0xBB81u, // Abstract Contact + MTP_OBJ_FORMAT_VCARD2 = 0xBB82u, // vCard 2.1 + MTP_OBJ_FORMAT_VCARD3 = 0xBB83u, // vCard 3.0 +} mtp_object_formats_t; -// Supported EventCode -typedef enum -{ - MTP_EVTC_OBJECT_ADDED = 0x4002, -} mtp_event_code_t; +// MTP 1.1 Appendix B: Object Properties +typedef enum { + MTP_OBJ_PROP_STORAGE_ID = 0xDC01u, // StorageID + MTP_OBJ_PROP_OBJECT_FORMAT = 0xDC02u, // Object Format + MTP_OBJ_PROP_PROTECTION_STATUS = 0xDC03u, // Protection Status + MTP_OBJ_PROP_OBJECT_SIZE = 0xDC04u, // Object Size + MTP_OBJ_PROP_ASSOCIATION_TYPE = 0xDC05u, // Association Type + MTP_OBJ_PROP_ASSOCIATION_DESC = 0xDC06u, // Association Description + MTP_OBJ_PROP_OBJECT_FILE_NAME = 0xDC07u, // Object File Name + MTP_OBJ_PROP_DATE_CREATED = 0xDC08u, // Date Created + MTP_OBJ_PROP_DATE_MODIFIED = 0xDC09u, // Date Modified + MTP_OBJ_PROP_KEYWORDS = 0xDC0Au, // Keywords + MTP_OBJ_PROP_PARENT_OBJECT = 0xDC0Bu, // Parent Object + MTP_OBJ_PROP_ALLOWED_FOLDER_CONTENTS = 0xDC0Cu, // Allowed Folder Contents + MTP_OBJ_PROP_HIDDEN = 0xDC0Du, // Hidden + MTP_OBJ_PROP_SYSTEM_OBJECT = 0xDC0Eu, // System Object + // 0xDC0F-0xDC40 is reserved + + MTP_OBJ_PROP_PERSISTENT_UID = 0xDC41u, // Persistent Unique Object Identifier + MTP_OBJ_PROP_SYNC_ID = 0xDC42u, // SyncID + MTP_OBJ_PROP_PROPERTY_BAG = 0xDC43u, // Property Bag + MTP_OBJ_PROP_NAME = 0xDC44u, // Name + MTP_OBJ_PROP_CREATED_BY = 0xDC45u, // Created By + MTP_OBJ_PROP_ARTIST = 0xDC46u, // Artist + MTP_OBJ_PROP_DATE_AUTHORED = 0xDC47u, // Date Authored + MTP_OBJ_PROP_DESCRIPTION = 0xDC48u, // Description + MTP_OBJ_PROP_URL_REFERENCE = 0xDC49u, // URL Reference + MTP_OBJ_PROP_LANGUAGE_LOCALE = 0xDC4Au, // Language-Locale + MTP_OBJ_PROP_COPYRIGHT_INFO = 0xDC4Bu, // Copyright Information + MTP_OBJ_PROP_SOURCE = 0xDC4Cu, // Source + MTP_OBJ_PROP_ORIGIN_LOCATION = 0xDC4Du, // Origin Location + MTP_OBJ_PROP_DATE_ADDED = 0xDC4Eu, // Date Added + MTP_OBJ_PROP_NON_CONSUMABLE = 0xDC4Fu, // Non-Consumable + MTP_OBJ_PROP_CORRUPT_UNPLAYABLE = 0xDC50u, // Corrupt/Unplayable + MTP_OBJ_PROP_PRODUCER_SERIAL_NUMBER = 0xDC51u, // ProducerSerialNumber + // 0xDC52-0xDC80 is reserved + + MTP_OBJ_PROP_REP_SAMPLE_FORMAT = 0xDC81u, // Representative Sample Format + MTP_OBJ_PROP_REP_SAMPLE_SIZE = 0xDC82u, // Representative Sample Size + MTP_OBJ_PROP_REP_SAMPLE_HEIGHT = 0xDC83u, // Representative Sample Height + MTP_OBJ_PROP_REP_SAMPLE_WIDTH = 0xDC84u, // Representative Sample Width + MTP_OBJ_PROP_REP_SAMPLE_DURATION = 0xDC85u, // Representative Sample Duration + MTP_OBJ_PROP_REP_SAMPLE_DATA = 0xDC86u, // Representative Sample Data + MTP_OBJ_PROP_WIDTH = 0xDC87u, // Width + MTP_OBJ_PROP_HEIGHT = 0xDC88u, // Height + MTP_OBJ_PROP_DURATION = 0xDC89u, // Duration + MTP_OBJ_PROP_RATING = 0xDC8Au, // Rating + MTP_OBJ_PROP_TRACK = 0xDC8Bu, // Track + MTP_OBJ_PROP_GENRE = 0xDC8Cu, // Genre + MTP_OBJ_PROP_CREDITS = 0xDC8Du, // Credits + MTP_OBJ_PROP_LYRICS = 0xDC8Eu, // Lyrics + MTP_OBJ_PROP_SUBSCRIPTION_CONTENT_ID = 0xDC8Fu, // Subscription Content ID + MTP_OBJ_PROP_PRODUCED_BY = 0xDC90u, // Produced By + MTP_OBJ_PROP_USE_COUNT = 0xDC91u, // Use Count + MTP_OBJ_PROP_SKIP_COUNT = 0xDC92u, // Skip Count + MTP_OBJ_PROP_LAST_ACCESSED = 0xDC93u, // Last Accessed + MTP_OBJ_PROP_PARENTAL_RATING = 0xDC94u, // Parental Rating + MTP_OBJ_PROP_META_GENRE = 0xDC95u, // Meta Genre + MTP_OBJ_PROP_COMPOSER = 0xDC96u, // Composer + MTP_OBJ_PROP_EFFECTIVE_RATING = 0xDC97u, // Effective Rating + MTP_OBJ_PROP_SUBTITLE = 0xDC98u, // Subtitle + MTP_OBJ_PROP_ORIGINAL_RELEASE_DATE = 0xDC99u, // Original Release Date + MTP_OBJ_PROP_ALBUM_NAME = 0xDC9Au, // Album Name + MTP_OBJ_PROP_ALBUM_ARTIST = 0xDC9Bu, // Album Artist + MTP_OBJ_PROP_MOOD = 0xDC9Cu, // Mood + MTP_OBJ_PROP_DRM_STATUS = 0xDC9Du, // DRM Status + MTP_OBJ_PROP_SUB_DESCRIPTION = 0xDC9Eu, // Sub Description + // 0xDC9F-0xDCD0 is reserved + + MTP_OBJ_PROP_IS_CROPPED = 0xDCD1u, // Is Cropped + MTP_OBJ_PROP_IS_COLOUR_CORRECTED = 0xDCD2u, // Is Colour Corrected + MTP_OBJ_PROP_IMAGE_BIT_DEPTH = 0xDCD3u, // Image Bit Depth + MTP_OBJ_PROP_FNUMBER = 0xDCD4u, // Fnumber (aperture ×100) + MTP_OBJ_PROP_EXPOSURE_TIME = 0xDCD5u, // Exposure Time (sec ×10,000) + MTP_OBJ_PROP_EXPOSURE_INDEX = 0xDCD6u, // Exposure Index (ISO) + // 0xDCD7-0xDCDF is reserved + + MTP_OBJ_PROP_DISPLAY_NAME = 0xDCE0u, // Display Name + MTP_OBJ_PROP_BODY_TEXT = 0xDCE1u, // Body Text + MTP_OBJ_PROP_SUBJECT = 0xDCE2u, // Subject + MTP_OBJ_PROP_PRIORITY = 0xDCE3u, // Priority + // 0xDCE4-0xDCFF is reserved + + MTP_OBJ_PROP_GIVEN_NAME = 0xDD00u, // Given Name + MTP_OBJ_PROP_MIDDLE_NAMES = 0xDD01u, // Middle Names + MTP_OBJ_PROP_FAMILY_NAME = 0xDD02u, // Family Name + MTP_OBJ_PROP_PREFIX = 0xDD03u, // Prefix + MTP_OBJ_PROP_SUFFIX = 0xDD04u, // Suffix + MTP_OBJ_PROP_PHONETIC_GIVEN_NAME = 0xDD05u, // Phonetic Given Name + MTP_OBJ_PROP_PHONETIC_FAMILY_NAME = 0xDD06u, // Phonetic Family Name + MTP_OBJ_PROP_EMAIL_PRIMARY = 0xDD07u, // Email Primary + MTP_OBJ_PROP_EMAIL_PERSONAL_1 = 0xDD08u, // Email Personal 1 + MTP_OBJ_PROP_EMAIL_PERSONAL_2 = 0xDD09u, // Email Personal 2 + MTP_OBJ_PROP_EMAIL_BUSINESS_1 = 0xDD0Au, // Email Business 1 + MTP_OBJ_PROP_EMAIL_BUSINESS_2 = 0xDD0Bu, // Email Business 2 + MTP_OBJ_PROP_EMAIL_OTHERS = 0xDD0Cu, // Email Others + MTP_OBJ_PROP_PHONE_PRIMARY = 0xDD0Du, // Phone Number Primary + MTP_OBJ_PROP_PHONE_PERSONAL_1 = 0xDD0Eu, // Phone Number Personal + MTP_OBJ_PROP_PHONE_PERSONAL_2 = 0xDD0Fu, // Phone Number Personal 2 + MTP_OBJ_PROP_PHONE_BUSINESS_1 = 0xDD10u, // Phone Number Business + MTP_OBJ_PROP_PHONE_BUSINESS_2 = 0xDD11u, // Phone Number Business 2 + MTP_OBJ_PROP_PHONE_MOBILE_1 = 0xDD12u, // Phone Number Mobile + MTP_OBJ_PROP_PHONE_MOBILE_2 = 0xDD13u, // Phone Number Mobile 2 + MTP_OBJ_PROP_FAX_PRIMARY = 0xDD14u, // Fax Number Primary + MTP_OBJ_PROP_FAX_PERSONAL = 0xDD15u, // Fax Number Personal + MTP_OBJ_PROP_FAX_BUSINESS = 0xDD16u, // Fax Number Business + MTP_OBJ_PROP_PAGER_NUMBER = 0xDD17u, // Pager Number + MTP_OBJ_PROP_PHONE_OTHERS = 0xDD18u, // Phone Number Others + MTP_OBJ_PROP_WEB_PRIMARY = 0xDD19u, // Primary Web Address + MTP_OBJ_PROP_WEB_PERSONAL = 0xDD1Au, // Personal Web Address + MTP_OBJ_PROP_WEB_BUSINESS = 0xDD1Bu, // Business Web Address + MTP_OBJ_PROP_IM_ADDRESS_1 = 0xDD1Cu, // Instant Messenger Address + MTP_OBJ_PROP_IM_ADDRESS_2 = 0xDD1Du, // Instant Messenger Address 2 + MTP_OBJ_PROP_IM_ADDRESS_3 = 0xDD1Eu, // Instant Messenger Address 3 + MTP_OBJ_PROP_ADDR_PERSONAL_FULL = 0xDD1Fu, // Postal Address Personal Full + MTP_OBJ_PROP_ADDR_PERSONAL_LINE1 = 0xDD20u, // Postal Address Personal Line 1 + MTP_OBJ_PROP_ADDR_PERSONAL_LINE2 = 0xDD21u, // Postal Address Personal Line 2 + MTP_OBJ_PROP_ADDR_PERSONAL_CITY = 0xDD22u, // Postal Address Personal City + MTP_OBJ_PROP_ADDR_PERSONAL_REGION = 0xDD23u, // Postal Address Personal Region + MTP_OBJ_PROP_ADDR_PERSONAL_POSTAL_CODE = 0xDD24u, // Postal Address Personal Postal Code + MTP_OBJ_PROP_ADDR_PERSONAL_COUNTRY = 0xDD25u, // Postal Address Personal Country + MTP_OBJ_PROP_ADDR_BUSINESS_FULL = 0xDD26u, // Postal Address Business Full + MTP_OBJ_PROP_ADDR_BUSINESS_LINE1 = 0xDD27u, // Postal Address Business Line 1 + MTP_OBJ_PROP_ADDR_BUSINESS_LINE2 = 0xDD28u, // Postal Address Business Line 2 + MTP_OBJ_PROP_ADDR_BUSINESS_CITY = 0xDD29u, // Postal Address Business City + MTP_OBJ_PROP_ADDR_BUSINESS_REGION = 0xDD2Au, // Postal Address Business Region + MTP_OBJ_PROP_ADDR_BUSINESS_POSTAL_CODE = 0xDD2Bu, // Postal Address Business Postal Code + MTP_OBJ_PROP_ADDR_BUSINESS_COUNTRY = 0xDD2Cu, // Postal Address Business Country + MTP_OBJ_PROP_ADDR_OTHER_FULL = 0xDD2Du, // Postal Address Other Full + MTP_OBJ_PROP_ADDR_OTHER_LINE1 = 0xDD2Eu, // Postal Address Other Line 1 + MTP_OBJ_PROP_ADDR_OTHER_LINE2 = 0xDD2Fu, // Postal Address Other Line 2 + MTP_OBJ_PROP_ADDR_OTHER_CITY = 0xDD30u, // Postal Address Other City + MTP_OBJ_PROP_ADDR_OTHER_REGION = 0xDD31u, // Postal Address Other Region + MTP_OBJ_PROP_ADDR_OTHER_POSTAL_CODE = 0xDD32u, // Postal Address Other Postal Code + MTP_OBJ_PROP_ADDR_OTHER_COUNTRY = 0xDD33u, // Postal Address Other Country + MTP_OBJ_PROP_ORGANIZATION_NAME = 0xDD34u, // Organization Name + MTP_OBJ_PROP_PHONETIC_ORG_NAME = 0xDD35u, // Phonetic Organization Name + MTP_OBJ_PROP_ROLE = 0xDD36u, // Role + MTP_OBJ_PROP_BIRTHDATE = 0xDD37u, // Birthdate + // 0xDD38-0xDD3F is reserved + + MTP_OBJ_PROP_MESSAGE_TO = 0xDD40u, // Message To + MTP_OBJ_PROP_MESSAGE_CC = 0xDD41u, // Message CC + MTP_OBJ_PROP_MESSAGE_BCC = 0xDD42u, // Message BCC + MTP_OBJ_PROP_MESSAGE_READ = 0xDD43u, // Message Read + MTP_OBJ_PROP_MESSAGE_RECEIVED_TIME = 0xDD44u, // Message Received Time + MTP_OBJ_PROP_MESSAGE_SENDER = 0xDD45u, // Message Sender + // 0xDD46-0xDD4F is reserved + + MTP_OBJ_PROP_ACTIVITY_BEGIN_TIME = 0xDD50u, // Activity Begin Time + MTP_OBJ_PROP_ACTIVITY_END_TIME = 0xDD51u, // Activity End Time + MTP_OBJ_PROP_ACTIVITY_LOCATION = 0xDD52u, // Activity Location + // 0xDD53 is reserved + MTP_OBJ_PROP_ACTIVITY_REQUIRED_ATTENDEES= 0xDD54u, // Activity Required Attendees + MTP_OBJ_PROP_ACTIVITY_OPTIONAL_ATTENDEES= 0xDD55u, // Activity Optional Attendees + MTP_OBJ_PROP_ACTIVITY_RESOURCES = 0xDD56u, // Activity Resources + MTP_OBJ_PROP_ACTIVITY_ACCEPTED = 0xDD57u, // Activity Accepted + MTP_OBJ_PROP_ACTIVITY_TENTATIVE = 0xDD58u, // Activity Tentative + MTP_OBJ_PROP_ACTIVITY_DECLINED = 0xDD59u, // Activity Declined + MTP_OBJ_PROP_ACTIVITY_REMINDER_TIME = 0xDD5Au, // Activity Reminder Time + MTP_OBJ_PROP_ACTIVITY_OWNER = 0xDD5Bu, // Activity Owner + MTP_OBJ_PROP_ACTIVITY_STATUS = 0xDD5Cu, // Activity Status + MTP_OBJ_PROP_OWNER = 0xDD5Du, // Owner + MTP_OBJ_PROP_EDITOR = 0xDD5Eu, // Editor + MTP_OBJ_PROP_WEBMASTER = 0xDD5Fu, // Webmaster + + MTP_OBJ_PROP_URL_SOURCE = 0xDD60u, // URL Source + MTP_OBJ_PROP_URL_DESTINATION = 0xDD61u, // URL Destination + MTP_OBJ_PROP_TIME_BOOKMARK = 0xDD62u, // Time Bookmark + MTP_OBJ_PROP_OBJECT_BOOKMARK = 0xDD63u, // Object Bookmark + MTP_OBJ_PROP_BYTE_BOOKMARK = 0xDD64u, // Byte Bookmark + // 0xDD65-0xDD6F is reserved + + MTP_OBJ_PROP_LAST_BUILD_DATE = 0xDD70u, // Last Build Date + MTP_OBJ_PROP_TIME_TO_LIVE = 0xDD71u, // Time to Live (minutes) + MTP_OBJ_PROP_MEDIA_GUID = 0xDD72u, // Media GUID + // 0xDD73-0xDDFF is reserved + + // media encoding + MTP_OBJ_PROP_TOTAL_BITRATE = 0xDE91u, // Total BitRate + MTP_OBJ_PROP_BITRATE_TYPE = 0xDE92u, // Bitrate Type + MTP_OBJ_PROP_SAMPLE_RATE = 0xDE93u, // Sample Rate + MTP_OBJ_PROP_NUM_CHANNELS = 0xDE94u, // Number Of Channels + MTP_OBJ_PROP_AUDIO_BITDEPTH = 0xDE95u, // Audio BitDepth + // 0xDE96 is reserved + MTP_OBJ_PROP_SCAN_TYPE = 0xDE97u, // Scan Type + // 0xDE98 is reserved + MTP_OBJ_PROP_AUDIO_WAVE_CODEC = 0xDE99u, // Audio WAVE Codec + MTP_OBJ_PROP_AUDIO_BITRATE = 0xDE9Au, // Audio BitRate + MTP_OBJ_PROP_VIDEO_FOURCC_CODEC = 0xDE9Bu, // Video FourCC Codec + MTP_OBJ_PROP_VIDEO_BITRATE = 0xDE9Cu, // Video BitRate + MTP_OBJ_PROP_FRAMES_PER_KSEC = 0xDE9Du, // Frames Per Thousand Seconds + MTP_OBJ_PROP_KEYFRAME_DISTANCE = 0xDE9Eu, // KeyFrame Distance (ms) + MTP_OBJ_PROP_BUFFER_SIZE = 0xDE9Fu, // Buffer Size + MTP_OBJ_PROP_ENCODING_QUALITY = 0xDEA0u, // Encoding Quality + MTP_OBJ_PROP_ENCODING_PROFILE = 0xDEA1u // Encoding Profile +} mtp_object_properties_t; -// Supported Device Properties -typedef enum -{ - MTP_DEVP_UNDEFINED = 0x5000u, - MTP_DEVP_BATTERY_LEVEL = 0x5001u, - MTP_DEVP_DEVICE_FRIENDLY_NAME = 0xD402u, +// MTP 1.1 Appendeix C: Device Properties +typedef enum { + MTP_DEV_PROP_UNDEFINED = 0x5000u, + MTP_DEV_PROP_BATTERY_LEVEL = 0x5001u, + MTP_DEV_PROP_FUNCTIONAL_MODE = 0x5002u, + MTP_DEV_PROP_IMAGE_SIZE = 0x5003u, + MTP_DEV_PROP_COMPRESSION_SETTING = 0x5004u, + MTP_DEV_PROP_WHITE_BALANCE = 0x5005u, + MTP_DEV_PROP_RGB_GAIN = 0x5006u, + MTP_DEV_PROP_F_NUMBER = 0x5007u, + MTP_DEV_PROP_FOCAL_LENGTH = 0x5008u, + MTP_DEV_PROP_FOCUS_DISTANCE = 0x5009u, + MTP_DEV_PROP_FOCUS_MODE = 0x500Au, + MTP_DEV_PROP_EXPOSURE_METERING_MODE = 0x500Bu, + MTP_DEV_PROP_FLASH_MODE = 0x500Cu, + MTP_DEV_PROP_EXPOSURE_TIME = 0x500Du, + MTP_DEV_PROP_EXPOSURE_PROGRAM_MODE = 0x500Eu, + MTP_DEV_PROP_EXPOSURE_INDEX = 0x500Fu, + MTP_DEV_PROP_EXPOSURE_BIAS_COMPENSATION = 0x5010u, + MTP_DEV_PROP_DATE_TIME = 0x5011u, + MTP_DEV_PROP_CAPTURE_DELAY = 0x5012u, + MTP_DEV_PROP_STILL_CAPTURE_MODE = 0x5013u, + MTP_DEV_PROP_CONTRAST = 0x5014u, + MTP_DEV_PROP_SHARPNESS = 0x5015u, + MTP_DEV_PROP_DIGITAL_ZOOM = 0x5016u, + MTP_DEV_PROP_EFFECT_MODE = 0x5017u, + MTP_DEV_PROP_BURST_NUMBER = 0x5018u, + MTP_DEV_PROP_BURST_INTERVAL = 0x5019u, + MTP_DEV_PROP_TIMELAPSE_NUMBER = 0x501Au, + MTP_DEV_PROP_TIMELAPSE_INTERVAL = 0x501Bu, + MTP_DEV_PROP_FOCUS_METERING_MODE = 0x501Cu, + MTP_DEV_PROP_UPLOAD_URL = 0x501Du, + MTP_DEV_PROP_ARTIST = 0x501Eu, + MTP_DEV_PROP_COPYRIGHT_INFO = 0x501Fu, + MTP_DEV_PROP_SYNCHRONIZTION_PARTNER = 0xD401, + MTP_DEV_PROP_DEVICE_FRIENDLY_NAME = 0xD402u, + MTP_DEV_PROP_VOLUME = 0xD403u, + MTP_DEV_PROP_SUPPORTED_FORMATS_ORDERED = 0xD404u, + MTP_DEV_PROP_DEVICE_ICON = 0xD405u, + MTP_DEV_PROP_SECTION_INITIATOR_VERSION_INFO = 0xD406u, + MTP_DEV_PROP_PERCEIVED_DEVICE_TYPE = 0xD407u, + MTP_DEV_PROP_PLAYBACK_RATE = 0xD410u, + MTP_DEV_PROP_PLAYBACK_OBJECT = 0xD411u, + MTP_DEV_PROP_PLAYBACK_CONTAINER_INDEX = 0xD412u, } mtp_event_properties_t; -// Supported Object Properties -typedef enum -{ - MTP_OBJP_STORAGE_ID = 0xDC01u, - MTP_OBJP_OBJECT_FORMAT = 0xDC02u, - MTP_OBJP_PROTECTION_STATUS = 0xDC03u, - MTP_OBJP_OBJECT_SIZE = 0xDC04u, - MTP_OBJP_ASSOCIATION_TYPE = 0xDC05u, - MTP_OBJP_OBJECT_FILE_NAME = 0xDC07u, - MTP_OBJP_PARENT_OBJECT = 0xDC0Bu, - MTP_OBJP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER = 0xDC41u, - MTP_OBJP_NAME = 0xDC44u, -} mtp_object_properties_t; +// MTP 1.1 Appendix D: Operations +typedef enum { + MTP_OP_UNDEFINED = 0x1000u, + MTP_OP_GET_DEVICE_INFO = 0x1001u, + MTP_OP_OPEN_SESSION = 0x1002u, + MTP_OP_CLOSE_SESSION = 0x1003u, + MTP_OP_GET_STORAGE_IDS = 0x1004u, + MTP_OP_GET_STORAGE_INFO = 0x1005u, + MTP_OP_GET_NUM_OBJECTS = 0x1006u, + MTP_OP_GET_OBJECT_HANDLES = 0x1007u, + MTP_OP_GET_OBJECT_INFO = 0x1008u, + MTP_OP_GET_OBJECT = 0x1009u, + MTP_OP_GET_THUMB = 0x100Au, + MTP_OP_DELETE_OBJECT = 0x100Bu, + MTP_OP_SEND_OBJECT_INFO = 0x100Cu, + MTP_OP_SEND_OBJECT = 0x100Du, + MTP_OP_INITIAL_CAPTURE = 0x100Eu, + MTP_OP_FORMAT_STORE = 0x100Fu, + MTP_OP_RESET_DEVICE = 0x1010u, + MTP_OP_SELF_TEST = 0x1011u, + MTP_OP_SET_OBJECT_PROTECTION = 0x1012u, + MTP_OP_POWER_DOWN = 0x1013u, + MTP_OP_GET_DEVICE_PROP_DESC = 0x1014u, + MTP_OP_GET_DEVICE_PROP_VALUE = 0x1015u, + MTP_OP_SET_DEVICE_PROP_VALUE = 0x1016u, + MTP_OP_RESET_DEVICE_PROP_VALUE = 0x1017u, + MTP_OP_TERMINATE_OPEN_CAPTURE = 0x1018u, + MTP_OP_MOVE_OBJECT = 0x1019u, + MTP_OP_COPY_OBJECT = 0x101Au, + MTP_OP_GET_PARTIAL_OBJECT = 0x101Bu, + MTP_OP_INITIATE_OPEN_CAPTURE = 0x101Bu, + MTP_OP_GET_OBJECT_PROPS_SUPPORTED = 0x9801u, + MTP_OP_GET_OBJECT_PROP_DESC = 0x9802u, + MTP_OP_GET_OBJECT_PROP_VALUE = 0x9803u, + MTP_OP_SET_OBJECT_PROP_VALUE = 0x9804u, + MTP_OP_GET_OBJECT_PROPLIST = 0x9805u, + MTP_OP_GET_OBJECT_PROP_REFERENCES = 0x9810u, + + MTP_OP_GET_SERVICE_IDS = 0x9301u, + MTP_OP_GET_SERVICE_INFO = 0x9302u, + MTP_OP_GET_SERVICE_CAPABILITIES = 0x9303u, + MTP_OP_GET_SERVICE_PROP_DESC = 0x9304u, + + // Appendix E: Enhanced Operations + MTP_OP_GET_OBJECT_PROP_LIST = 0x9805u, + MTP_OP_SET_OBJECT_PROP_LIST = 0x9806u, + MTP_OP_GET_INTERDEPENDENT_PROP_DESC = 0x9807u, + MTP_OP_SEND_OBJECT_PROP_LIST = 0x9808u, +} mtp_operation_code_t; -// Object formats -typedef enum -{ - MTP_OBJF_UNDEFINED = 0x3000u, - MTP_OBJF_ASSOCIATION = 0x3001u, - MTP_OBJF_TEXT = 0x3004u, -} mtp_object_formats_t; +// Appendix F: Responses +typedef enum { + MTP_RESP_UNDEFINED = 0x2000u, + MTP_RESP_OK = 0x2001u, + MTP_RESP_GENERAL_ERROR = 0x2002u, + MTP_RESP_SESSION_NOT_OPEN = 0x2003u, + MTP_RESP_INVALID_TRANSACTION_ID = 0x2004u, + MTP_RESP_OPERATION_NOT_SUPPORTED = 0x2005u, + MTP_RESP_PARAMETER_NOT_SUPPORTED = 0x2006u, + MTP_RESP_INCOMPLETE_TRANSFER = 0x2007u, + MTP_RESP_INVALID_STORAGE_ID = 0x2008u, + MTP_RESP_INVALID_OBJECT_HANDLE = 0x2009u, + MTP_RESP_DEVICE_PROP_NOT_SUPPORTED = 0x200Au, + MTP_RESP_INVALID_OBJECT_FORMAT_CODE = 0x200Bu, + MTP_RESP_STORE_FULL = 0x200Cu, + MTP_RESP_OBJECT_WRITE_PROTECTED = 0x200Du, + MPT_RESC_STORE_READ_ONLY = 0x200Eu, + MTP_RESP_ACCESS_DENIED = 0x200Fu, + MTP_RESP_NO_THUMBNAIL_PRESENT = 0x2010u, + MTP_RESP_SELF_TEST_FAILED = 0x2011u, + MTP_RESP_PARTIAL_DELETION = 0x2012u, + MTP_RESP_STORE_NOT_AVAILABLE = 0x2013u, + MTP_RESP_SPECIFICATION_BY_FORMAT_UNSUPPORTED = 0x2014u, + MTP_RESP_NO_VALID_OBJECTINFO = 0x2015u, + MTP_RESP_INVALID_CODE_FORMAT = 0x2016u, + MTP_RESP_UNKNOWN_VENDOR_CODE = 0x2017u, + MTP_RESP_CAPTURE_ALREADY_TERMINATED = 0x2018u, + MTP_RESP_DEVICE_BUSY = 0x2019u, + MTP_RESP_INVALID_PARENT_OBJECT = 0x201Au, + MTP_RESP_INVALID_DEVICE_PROP_FORMAT = 0x201Bu, + MTP_RESP_INVALID_DEVICE_PROP_VALUE = 0x201Cu, + MTP_RESP_INVALID_PARAMETER = 0x201Du, + MTP_RESP_SESSION_ALREADY_OPEN = 0x201Eu, + MTP_RESP_TRANSACTION_CANCELLED = 0x201Fu, + MTP_RESP_SPEC_OF_DESTINATION_UNSUPPORTED = 0x2020u, + + MTP_RESP_INVALID_OBJECT_PROP_CODE = 0xA801u, + MTP_RESP_INVALID_OBJECT_PROP_FORMAT = 0xA802u, + MTP_RESP_INVALID_OBJECT_PROP_VALUE = 0xA803u, + MTP_RESP_INVALID_OBJECT_REFERENCE = 0xA804u, + MTP_RESP_GROUP_NOT_SUPPORTED = 0xA805u, + MTP_RESP_INVALID_DATASET = 0xA806u, + MTP_RESP_SPEC_BY_GROUP_UNSUPPORTED = 0xA807u, + MTP_RESP_SPEC_BY_DEPTH_UNSUPPORTED = 0xA808u, + MTP_RESP_OBJECT_TOO_LARGE = 0xA809u, + MTP_RESP_OBJECT_PROP_NOT_SUPPORTED = 0xA80Au, +} mtp_response_t; + +// Appendix G: Events +typedef enum { + MTP_EVENT_UNDEFINED = 0x4000, + MTP_EVENT_CANCEL_TRANSACTION = 0x4001, + MTP_EVENT_OBJECT_ADDED = 0x4002, + MTP_EVENT_OBJECT_REMOVED = 0x4003, + MTP_EVENT_STORE_ADDED = 0x4004, + MTP_EVENT_STORE_REMOVED = 0x4005, + MTP_EVENT_DEVICE_PROP_CHANGED = 0x4006, + MTP_EVENT_OBJECT_INFO_CHANGED = 0x4007, + MTP_EVENT_DEVICE_INFO_CHANGED = 0x4008, + MTP_EVENT_REQUEST_OBJECT_TRANSFER = 0x4009, + MTP_EVENT_STORE_FULL = 0x400Au, + MTP_EVENT_DEVICE_RESET = 0x400Bu, + MTP_EVENT_STORAGE_INFO_CHANGED = 0x400Cu, + MTP_EVENT_CAPTURE_COMPLETE = 0x400Du, + MTP_EVENT_UNREPORTED_STATUS = 0x400Eu, + MTP_EVENT_OBJECT_PROP_CHANGED = 0xC801u, + MTP_EVENT_OBJECT_PROP_DESC_CHANGED = 0xC802u, + MTP_EVENT_OBJECT_REFERENCES_CHANGED = 0xC803u, +} mtp_event_code_t; // Predefined Object handles typedef enum @@ -210,50 +602,101 @@ typedef enum MTP_MODE_GET_SET = 0x01u, } mtp_mode_get_set_t; +typedef enum { + MTP_STORAGE_TYPE_UNDEFINED = 0x0000u, + MTP_STORAGE_TYPE_FIXED_ROM = 0x0001u, + MTP_STORAGE_TYPE_REMOVABLE_ROM = 0x0002u, + MTP_STORAGE_TYPE_FIXED_RAM = 0x0003u, + MTP_STORAGE_TYPE_REMOVABLE_RAM = 0x0004u, +} mtp_storage_type_t; + +typedef enum { + MTP_FILESYSTEM_TYPE_UNDEFINED = 0x0000u, + MTP_FILESYSTEM_TYPE_GENERIC_FLAT = 0x0001u, + MTP_FILESYSTEM_TYPE_GENERIC_HIERARCHICAL = 0x0002u, + MTP_FILESYSTEM_TYPE_DCF = 0x0003u, +} mtp_filesystem_type_t; + +typedef enum { + MTP_ACCESS_CAPABILITY_READ_WRITE = 0x0000u, + MTP_ACCESS_CAPABILITY_READ_ONLY_WITHOUT_OBJECT_DELETION = 0x0001u, + MTP_ACCESS_CAPABILITY_READ_ONLY_WITH_OBJECT_DELETION = 0x0002u, +} mtp_access_capability_t; + +typedef enum { + MTP_PROTECTION_STATUS_NO_PROTECTION = 0x0000u, + MTP_PROTECTION_STATUS_READ_ONLY = 0x0001u, + MTP_PROTECTION_STATUS_READ_ONLY_DATA = 0x8002u, + MTP_PROTECTION_NON_TRANSFERABLE_DATA = 0x8003u, +} mtp_protection_status_t; + +typedef enum { + MTP_ASSOCIATION_UNDEFINED = 0x0000u, + MTP_ASSOCIATION_GENERIC_FOLDER = 0x0001u, + MTP_ASSOCIATION_GENERIC_ALBUM = 0x0002u, + MTP_ASSOCIATION_TIME_SEQUENCE = 0x0003u, + MTP_ASSOCIATION_HORIZONTAL_PANORAMIC = 0x0004u, + MTP_ASSOCIATION_VERTICAL_PANORAMIC = 0x0005u, + MTP_ASSOCIATION_2D_PANORAMIC = 0x0006u, +} mtp_association_t; + + tu_static const uint16_t mtp_operations_supported[] = { - MTP_OPEC_GET_DEVICE_INFO, - MTP_OPEC_OPEN_SESSION, - MTP_OPEC_CLOSE_SESSION, - MTP_OPEC_GET_STORAGE_IDS, - MTP_OPEC_GET_STORAGE_INFO, - MTP_OPEC_GET_NUM_OBJECTS, - MTP_OPEC_GET_OBJECT_HANDLES, - MTP_OPEC_GET_OBJECT_INFO, - MTP_OPEC_GET_OBJECT, - MTP_OPEC_DELETE_OBJECT, - MTP_OPEC_SEND_OBJECT_INFO, - MTP_OPEC_SEND_OBJECT, - MTP_OPEC_FORMAT_STORE, - MTP_OPEC_RESET_DEVICE, - MTP_OPEC_GET_DEVICE_PROP_DESC, - MTP_OPEC_GET_DEVICE_PROP_VALUE, - MTP_OPEC_SET_DEVICE_PROP_VALUE, + 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, }; tu_static const uint16_t mtp_events_supported[] = { - MTP_EVTC_OBJECT_ADDED, + MTP_EVENT_OBJECT_ADDED, }; tu_static const uint16_t mtp_device_properties_supported[] = { - MTP_DEVP_DEVICE_FRIENDLY_NAME, + MTP_DEV_PROP_DEVICE_FRIENDLY_NAME, }; tu_static const uint16_t mtp_capture_formats[] = { - MTP_OBJF_UNDEFINED, - MTP_OBJF_ASSOCIATION, - MTP_OBJF_TEXT, + MTP_OBJ_FORMAT_UNDEFINED, + MTP_OBJ_FORMAT_ASSOCIATION, + MTP_OBJ_FORMAT_TEXT, }; tu_static const uint16_t mtp_playback_formats[] = { - MTP_OBJF_UNDEFINED, - MTP_OBJF_ASSOCIATION, - MTP_OBJF_TEXT, + MTP_OBJ_FORMAT_UNDEFINED, + MTP_OBJ_FORMAT_ASSOCIATION, + MTP_OBJ_FORMAT_TEXT, }; //--------------------------------------------------------------------+ // Data structures //--------------------------------------------------------------------+ +#define MTP_GENERIC_DATA_BLOCK_LENGTH 12 +#define MTP_MAX_PACKET_SIZE 512 + +// PTP/MTP Generic container +typedef struct TU_ATTR_PACKED { + uint32_t container_length; + uint16_t container_type; + uint16_t code; + uint32_t transaction_id; + uint32_t data[MTP_MAX_PACKET_SIZE / sizeof(uint32_t)]; +} mtp_generic_container_t; + // DeviceInfo Dataset #define MTP_EXTENSIONS "microsoft.com: 1.0; " typedef struct TU_ATTR_PACKED { @@ -360,75 +803,6 @@ typedef struct TU_ATTR_PACKED { uint32_t parent_object_handle; } mtp_basic_object_info_t; -//--------------------------------------------------------------------+ -// Definitions -//--------------------------------------------------------------------+ - -typedef enum { - MTP_STORAGE_TYPE_UNDEFINED = 0x0000u, - MTP_STORAGE_TYPE_FIXED_ROM = 0x0001u, - MTP_STORAGE_TYPE_REMOVABLE_ROM = 0x0002u, - MTP_STORAGE_TYPE_FIXED_RAM = 0x0003u, - MTP_STORAGE_TYPE_REMOVABLE_RAM = 0x0004u, -} mtp_storage_type_t; - -typedef enum { - MTP_FILESYSTEM_TYPE_UNDEFINED = 0x0000u, - MTP_FILESYSTEM_TYPE_GENERIC_FLAT = 0x0001u, - MTP_FILESYSTEM_TYPE_GENERIC_HIERARCHICAL = 0x0002u, - MTP_FILESYSTEM_TYPE_DCF = 0x0003u, -} mtp_filesystem_type_t; - -typedef enum { - MTP_ACCESS_CAPABILITY_READ_WRITE = 0x0000u, - MTP_ACCESS_CAPABILITY_READ_ONLY_WITHOUT_OBJECT_DELETION = 0x0001u, - MTP_ACCESS_CAPABILITY_READ_ONLY_WITH_OBJECT_DELETION = 0x0002u, -} mtp_access_capability_t; - -typedef enum { - MTP_PROTECTION_STATUS_NO_PROTECTION = 0x0000u, - MTP_PROTECTION_STATUS_READ_ONLY = 0x0001u, - MTP_PROTECTION_STATUS_READ_ONLY_DATA = 0x8002u, - MTP_PROTECTION_NON_TRANSFERABLE_DATA = 0x8003u, -} mtp_protection_status_t; - -typedef enum { - MTP_ASSOCIATION_UNDEFINED = 0x0000u, - MTP_ASSOCIATION_GENERIC_FOLDER = 0x0001u, - MTP_ASSOCIATION_GENERIC_ALBUM = 0x0002u, - MTP_ASSOCIATION_TIME_SEQUENCE = 0x0003u, - MTP_ASSOCIATION_HORIZONTAL_PANORAMIC = 0x0004u, - MTP_ASSOCIATION_VERTICAL_PANORAMIC = 0x0005u, - MTP_ASSOCIATION_2D_PANORAMIC = 0x0006u, -} mtp_association_t; - -// Responses -typedef enum { -// Supported ResponseCode - MTP_RESC_UNDEFINED = 0x2000u, - MTP_RESC_OK = 0x2001u, - MTP_RESC_GENERAL_ERROR = 0x2002u, - MTP_RESC_SESSION_NOT_OPEN = 0x2003u, - MTP_RESC_INVALID_TRANSACTION_ID = 0x2004u, - MTP_RESC_OPERATION_NOT_SUPPORTED = 0x2005u, - MTP_RESC_PARAMETER_NOT_SUPPORTED = 0x2006u, - MTP_RESC_INCOMPLETE_TRANSFER = 0x2007u, - MTP_RESC_INVALID_STORAGE_ID = 0x2008u, - MTP_RESC_INVALID_OBJECT_HANDLE = 0x2009u, - MTP_RESC_STORE_FULL = 0x200Cu, - MTP_RESC_OBJECT_WRITE_PROTECTED = 0x200Du, - MTP_RESC_STORE_NOT_AVAILABLE = 0x2013u, - MTP_RESC_SPECIFICATION_BY_FORMAT_UNSUPPORTED = 0x2014u, - MTP_RESC_NO_VALID_OBJECTINFO = 0x2015u, - MTP_RESC_DEVICE_BUSY = 0x2019u, - MTP_RESC_INVALID_PARENT_OBJECT = 0x201Au, - MTP_RESC_INVALID_DEVICE_PROP_FORMAT = 0x201Bu, - MTP_RESC_INVALID_DEVICE_PROP_VALUE = 0x201Cu, - MTP_RESC_INVALID_PARAMETER = 0x201Du, - MTP_RESC_SESSION_ALREADY_OPEN = 0x201Eu, - MTP_RESC_TRANSACTION_CANCELLED = 0x201Fu, -} mtp_response_t; - #ifdef __cplusplus } #endif diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c index 854d4f10e..68a7c6c2a 100644 --- a/src/class/mtp/mtp_device.c +++ b/src/class/mtp/mtp_device.c @@ -147,9 +147,9 @@ uint16_t mtpd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16 TU_LOG_DRV(" MTP mtpd_open\n"); tusb_desc_endpoint_t const *ep_desc; // only support SCSI's BOT protocol - TU_VERIFY(TUSB_CLASS_IMAGE == itf_desc->bInterfaceClass && - MTP_SUBCLASS == itf_desc->bInterfaceSubClass && - MTP_PROTOCOL_STILL_IMAGE == itf_desc->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_IMAGE == itf_desc->bInterfaceClass && + MTP_SUBCLASS_STILL_IMAGE == itf_desc->bInterfaceSubClass && + MTP_PROTOCOL_PIMA_15470 == itf_desc->bInterfaceProtocol, 0); // mtp driver length is fixed uint16_t const mtpd_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); @@ -205,7 +205,7 @@ bool mtpd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t len = 4; _mtpd_device_status_res.wLength = len; // Cancel is synchronous, always answer OK - _mtpd_device_status_res.code = MTP_RESC_OK; + _mtpd_device_status_res.code = MTP_RESP_OK; TU_ASSERT( tud_control_xfer(rhport, request, (uint8_t *)&_mtpd_device_status_res , len) ); break; @@ -243,7 +243,7 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t { _mtpd_itf.phase = MTP_PHASE_RESPONSE; _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_OK; + _mtpd_gct.code = MTP_RESP_OK; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; _mtpd_gct.transaction_id = _mtpd_ctx.transaction_id; if (_mtpd_ctx.session_id != 0) @@ -413,55 +413,55 @@ mtp_phase_type_t mtpd_handle_cmd(void) { TU_ASSERT(_mtpd_gct.container_type == MTP_CONTAINER_TYPE_COMMAND_BLOCK); _mtpd_ctx.transaction_id = _mtpd_gct.transaction_id; - if (_mtpd_gct.code != MTP_OPEC_SEND_OBJECT) + if (_mtpd_gct.code != MTP_OP_SEND_OBJECT) _mtpd_soi.object_handle = 0; switch(_mtpd_gct.code) { - case MTP_OPEC_GET_DEVICE_INFO: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_DEVICE_INFO\n"); + case MTP_OP_GET_DEVICE_INFO: + TU_LOG_DRV(" MTP command: MTP_OP_GET_DEVICE_INFO\n"); return mtpd_handle_cmd_get_device_info(); - case MTP_OPEC_OPEN_SESSION: - TU_LOG_DRV(" MTP command: MTP_OPEC_OPEN_SESSION\n"); + case MTP_OP_OPEN_SESSION: + TU_LOG_DRV(" MTP command: MTP_OP_OPEN_SESSION\n"); return mtpd_handle_cmd_open_session(); - case MTP_OPEC_CLOSE_SESSION: - TU_LOG_DRV(" MTP command: MTP_OPEC_CLOSE_SESSION\n"); + case MTP_OP_CLOSE_SESSION: + TU_LOG_DRV(" MTP command: MTP_OP_CLOSE_SESSION\n"); return mtpd_handle_cmd_close_session(); - case MTP_OPEC_GET_STORAGE_IDS: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_STORAGE_IDS\n"); + case MTP_OP_GET_STORAGE_IDS: + TU_LOG_DRV(" MTP command: MTP_OP_GET_STORAGE_IDS\n"); return mtpd_handle_cmd_get_storage_ids(); - case MTP_OPEC_GET_STORAGE_INFO: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_STORAGE_INFO for ID=%lu\n", _mtpd_gct.data[0]); + case MTP_OP_GET_STORAGE_INFO: + TU_LOG_DRV(" MTP command: MTP_OP_GET_STORAGE_INFO for ID=%lu\n", _mtpd_gct.data[0]); return mtpd_handle_cmd_get_storage_info(); - case MTP_OPEC_GET_OBJECT_HANDLES: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_OBJECT_HANDLES\n"); + case MTP_OP_GET_OBJECT_HANDLES: + TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT_HANDLES\n"); return mtpd_handle_cmd_get_object_handles(); - case MTP_OPEC_GET_OBJECT_INFO: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_OBJECT_INFO\n"); + case MTP_OP_GET_OBJECT_INFO: + TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT_INFO\n"); return mtpd_handle_cmd_get_object_info(); - case MTP_OPEC_GET_OBJECT: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_OBJECT\n"); + case MTP_OP_GET_OBJECT: + TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT\n"); return mtpd_handle_cmd_get_object(); - case MTP_OPEC_DELETE_OBJECT: - TU_LOG_DRV(" MTP command: MTP_OPEC_DELETE_OBJECT\n"); + case MTP_OP_DELETE_OBJECT: + TU_LOG_DRV(" MTP command: MTP_OP_DELETE_OBJECT\n"); return mtpd_handle_cmd_delete_object(); - case MTP_OPEC_GET_DEVICE_PROP_DESC: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_DEVICE_PROP_DESC\n"); + 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(); - case MTP_OPEC_GET_DEVICE_PROP_VALUE: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_DEVICE_PROP_VALUE\n"); + 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(); - case MTP_OPEC_SEND_OBJECT_INFO: - TU_LOG_DRV(" MTP command: MTP_OPEC_SEND_OBJECT_INFO\n"); + case MTP_OP_SEND_OBJECT_INFO: + TU_LOG_DRV(" MTP command: MTP_OP_SEND_OBJECT_INFO\n"); return mtpd_handle_cmd_send_object_info(); - case MTP_OPEC_SEND_OBJECT: - TU_LOG_DRV(" MTP command: MTP_OPEC_SEND_OBJECT\n"); + case MTP_OP_SEND_OBJECT: + TU_LOG_DRV(" MTP command: MTP_OP_SEND_OBJECT\n"); return mtpd_handle_cmd_send_object(); - case MTP_OPEC_FORMAT_STORE: - TU_LOG_DRV(" MTP command: MTP_OPEC_FORMAT_STORE\n"); + case MTP_OP_FORMAT_STORE: + TU_LOG_DRV(" MTP command: MTP_OP_FORMAT_STORE\n"); return mtpd_handle_cmd_format_store(); default: - TU_LOG_DRV(" MTP command: MTP_OPEC_UNKNOWN_COMMAND %x!!!!\n", _mtpd_gct.code); + TU_LOG_DRV(" MTP command: MTP_OP_UNKNOWN_COMMAND %x!!!!\n", _mtpd_gct.code); return false; } return true; @@ -474,17 +474,17 @@ mtp_phase_type_t mtpd_handle_data(void) switch(_mtpd_gct.code) { - case MTP_OPEC_GET_OBJECT: - TU_LOG_DRV(" MTP command: MTP_OPEC_GET_OBJECT-DATA_IN\n"); + case MTP_OP_GET_OBJECT: + TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT-DATA_IN\n"); return mtpd_handle_dti_get_object(); - case MTP_OPEC_SEND_OBJECT_INFO: - TU_LOG_DRV(" MTP command: MTP_OPEC_SEND_OBJECT_INFO-DATA_OUT\n"); + case MTP_OP_SEND_OBJECT_INFO: + TU_LOG_DRV(" MTP command: MTP_OP_SEND_OBJECT_INFO-DATA_OUT\n"); return mtpd_handle_dto_send_object_info(); - case MTP_OPEC_SEND_OBJECT: - TU_LOG_DRV(" MTP command: MTP_OPEC_SEND_OBJECT-DATA_OUT\n"); + case MTP_OP_SEND_OBJECT: + TU_LOG_DRV(" MTP command: MTP_OP_SEND_OBJECT-DATA_OUT\n"); return mtpd_handle_dto_send_object(); default: - TU_LOG_DRV(" MTP command: MTP_OPEC_UNKNOWN_COMMAND %x!!!!\n", _mtpd_gct.code); + TU_LOG_DRV(" MTP command: MTP_OP_UNKNOWN_COMMAND %x!!!!\n", _mtpd_gct.code); return false; } return true; @@ -496,7 +496,7 @@ mtp_phase_type_t mtpd_handle_cmd_get_device_info(void) _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_device_info_t); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_DEVICE_INFO; + _mtpd_gct.code = MTP_OP_GET_DEVICE_INFO; mtp_device_info_t *d = (mtp_device_info_t *)_mtpd_gct.data; d->standard_version = 100; d->mtp_vendor_extension_id = 0x06; @@ -528,7 +528,7 @@ mtp_phase_type_t mtpd_handle_cmd_open_session(void) uint32_t session_id = _mtpd_gct.data[0]; mtp_response_t res = tud_mtp_storage_open_session(&session_id); - if (res == MTP_RESC_SESSION_ALREADY_OPEN) + if (res == MTP_RESP_SESSION_ALREADY_OPEN) { _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; @@ -540,13 +540,13 @@ mtp_phase_type_t mtpd_handle_cmd_open_session(void) } mtp_phase_type_t phase; - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_ctx.session_id = session_id; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_OK; + _mtpd_gct.code = MTP_RESP_OK; return MTP_PHASE_RESPONSE; } @@ -573,11 +573,11 @@ mtp_phase_type_t mtpd_handle_cmd_get_storage_ids(void) uint32_t storage_id; mtp_response_t res = tud_mtp_get_storage_id(&storage_id); mtp_phase_type_t phase; - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_storage_ids_t); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_STORAGE_IDS; + _mtpd_gct.code = MTP_OP_GET_STORAGE_IDS; mtp_storage_ids_t *d = (mtp_storage_ids_t *)_mtpd_gct.data; if (storage_id == 0) { @@ -603,11 +603,11 @@ mtp_phase_type_t mtpd_handle_cmd_get_storage_info(void) _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_storage_info_t); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_STORAGE_INFO; + _mtpd_gct.code = MTP_OP_GET_STORAGE_INFO; mtp_response_t res = tud_mtp_get_storage_info(storage_id, (mtp_storage_info_t *)_mtpd_gct.data); mtp_phase_type_t phase; - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_itf.queued_len = _mtpd_gct.container_length; return MTP_PHASE_DATA_IN; @@ -621,20 +621,20 @@ mtp_phase_type_t mtpd_handle_cmd_get_object_handles(void) _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(uint32_t); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_OBJECT_HANDLES; + _mtpd_gct.code = MTP_OP_GET_OBJECT_HANDLES; _mtpd_gct.data[0] = 0; mtp_phase_type_t phase; - if ((phase = mtpd_chk_generic(__func__, (object_format_code != 0), MTP_RESC_SPECIFICATION_BY_FORMAT_UNSUPPORTED, "specification by format unsupported")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (object_format_code != 0), MTP_RESP_SPECIFICATION_BY_FORMAT_UNSUPPORTED, "specification by format unsupported")) != MTP_PHASE_NONE) return phase; //list of all object handles on all storages, not managed - if ((phase = mtpd_chk_generic(__func__, (storage_id == 0xFFFFFFFF), MTP_RESC_OPERATION_NOT_SUPPORTED, "list of all object handles on all storages unsupported")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (storage_id == 0xFFFFFFFF), MTP_RESP_OPERATION_NOT_SUPPORTED, "list of all object handles on all storages unsupported")) != MTP_PHASE_NONE) return phase; tud_mtp_storage_object_done(); uint32_t next_child_handle = 0; while(true) { mtp_response_t res = tud_mtp_storage_association_get_object_handle(storage_id, parent_object_handle, &next_child_handle); - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; if (next_child_handle == 0) break; mtpd_gct_append_object_handle(next_child_handle); @@ -653,10 +653,10 @@ mtp_phase_type_t mtpd_handle_cmd_get_object_info(void) _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_object_info_t); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_OBJECT_INFO; + _mtpd_gct.code = MTP_OP_GET_OBJECT_INFO; mtp_response_t res = tud_mtp_storage_object_read_info(object_handle, (mtp_object_info_t *)_mtpd_gct.data); mtp_phase_type_t phase; - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_itf.queued_len = _mtpd_gct.container_length; return MTP_PHASE_DATA_IN; @@ -676,10 +676,10 @@ mtp_phase_type_t mtpd_handle_dti_get_object(void) mtp_phase_type_t phase; uint32_t file_size = 0; res = tud_mtp_storage_object_size(_mtpd_get_object_handle, &file_size); - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + file_size; _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_OBJECT; + _mtpd_gct.code = MTP_OP_GET_OBJECT; uint32_t buffer_size; uint32_t read_count; @@ -689,7 +689,7 @@ mtp_phase_type_t mtpd_handle_dti_get_object(void) // First data block: include container header buffer_size = ((MTP_MAX_PACKET_SIZE + MTP_GENERIC_DATA_BLOCK_LENGTH) / CFG_MTP_EP_SIZE) * CFG_MTP_EP_SIZE - MTP_GENERIC_DATA_BLOCK_LENGTH; res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&_mtpd_gct.data, buffer_size, &read_count); - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_itf.queued_len = MTP_GENERIC_DATA_BLOCK_LENGTH + read_count; } else @@ -697,7 +697,7 @@ mtp_phase_type_t mtpd_handle_dti_get_object(void) // Successive data block: consider only container data buffer_size = (MTP_MAX_PACKET_SIZE / CFG_MTP_EP_SIZE) * CFG_MTP_EP_SIZE; res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&_mtpd_gct.data, buffer_size, &read_count); - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_itf.queued_len = read_count; } @@ -718,10 +718,10 @@ mtp_phase_type_t mtpd_handle_cmd_delete_object(void) mtp_response_t res = tud_mtp_storage_object_delete(object_handle); mtp_phase_type_t phase; - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_OK; + _mtpd_gct.code = MTP_RESP_OK; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } @@ -735,11 +735,11 @@ mtp_phase_type_t mtpd_handle_cmd_get_device_prop_desc(void) switch(device_prop_code) { - case MTP_DEVP_DEVICE_FRIENDLY_NAME: + 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"); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_DEVICE_PROP_DESC; + _mtpd_gct.code = MTP_OP_GET_DEVICE_PROP_DESC; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_device_prop_desc_t); mtp_device_prop_desc_t *d = (mtp_device_prop_desc_t *)_mtpd_gct.data; d->device_property_code = (uint16_t)(device_prop_code); @@ -756,7 +756,7 @@ mtp_phase_type_t mtpd_handle_cmd_get_device_prop_desc(void) } _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_PARAMETER_NOT_SUPPORTED; + _mtpd_gct.code = MTP_RESP_PARAMETER_NOT_SUPPORTED; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } @@ -770,18 +770,18 @@ mtp_phase_type_t mtpd_handle_cmd_get_device_prop_value(void) _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OPEC_GET_DEVICE_PROP_VALUE; + _mtpd_gct.code = MTP_OP_GET_DEVICE_PROP_VALUE; switch(device_prop_code) { // TODO support more device properties - case MTP_DEVP_DEVICE_FRIENDLY_NAME: + case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: mtpd_gct_append_wstring(CFG_TUD_MODEL); _mtpd_itf.queued_len = _mtpd_gct.container_length; return MTP_PHASE_DATA_IN; default: _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_PARAMETER_NOT_SUPPORTED; + _mtpd_gct.code = MTP_RESP_PARAMETER_NOT_SUPPORTED; return MTP_PHASE_RESPONSE; } } @@ -800,7 +800,7 @@ mtp_phase_type_t mtpd_handle_dto_send_object_info(void) 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_t *)_mtpd_gct.data); mtp_phase_type_t phase; - if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESC_OK), res, "")) != MTP_PHASE_NONE) return 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; @@ -808,7 +808,7 @@ mtp_phase_type_t mtpd_handle_dto_send_object_info(void) // Response _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + 3 * sizeof(uint32_t); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_OK; + _mtpd_gct.code = MTP_RESP_OK; _mtpd_gct.data[0] = _mtpd_soi.storage_id; _mtpd_gct.data[1] = _mtpd_soi.parent_object_handle; _mtpd_gct.data[2] = _mtpd_soi.object_handle; @@ -835,7 +835,7 @@ mtp_phase_type_t mtpd_handle_dto_send_object(void) { 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_RESC_OK), res, "")) != MTP_PHASE_NONE) return phase; + if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; } if (!_mtpd_itf.xfer_completed) @@ -849,7 +849,7 @@ mtp_phase_type_t mtpd_handle_dto_send_object(void) _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_OK; + _mtpd_gct.code = MTP_RESP_OK; return MTP_PHASE_RESPONSE; } @@ -877,7 +877,7 @@ mtp_phase_type_t mtpd_chk_session_open(const char *func_name) { TU_LOG_DRV(" MTP error: %s session not open\n", func_name); _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESC_SESSION_NOT_OPEN; + _mtpd_gct.code = MTP_RESP_SESSION_NOT_OPEN; _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } diff --git a/src/device/usbd.h b/src/device/usbd.h index b89a0200b..921d5c0d0 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -279,7 +279,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Interface number, string index, EP Out & EP In address, EP size #define TUD_MTP_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_polling_interval, _epout, _epin, _epsize) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUSB_CLASS_IMAGE, MTP_SUBCLASS, MTP_PROTOCOL_STILL_IMAGE, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUSB_CLASS_IMAGE, MTP_SUBCLASS_STILL_IMAGE, MTP_PROTOCOL_PIMA_15470, _stridx,\ /* Endpoint Interrupt */\ 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_polling_interval,\ /* Endpoint Out */\ -- cgit v1.3.1 From 10298f0b275971db349c68049454994b15eabf46 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Sep 2025 14:14:36 +0700 Subject: refactor generic container to use EPBUF declaration simplify container field name --- src/class/mtp/mtp.h | 4 +- src/class/mtp/mtp_device.c | 443 ++++++++++++++++++++++++--------------------- src/device/usbd.c | 1 + 3 files changed, 241 insertions(+), 207 deletions(-) (limited to 'src/device') diff --git a/src/class/mtp/mtp.h b/src/class/mtp/mtp.h index b5db2cd6c..f697193d2 100644 --- a/src/class/mtp/mtp.h +++ b/src/class/mtp/mtp.h @@ -690,8 +690,8 @@ tu_static const uint16_t mtp_playback_formats[] = { // PTP/MTP Generic container typedef struct TU_ATTR_PACKED { - uint32_t container_length; - uint16_t container_type; + uint32_t len; + uint16_t type; uint16_t code; uint32_t transaction_id; uint32_t data[MTP_MAX_PACKET_SIZE / sizeof(uint32_t)]; diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c index d8db17e79..5aa2bf1f1 100644 --- a/src/class/mtp/mtp_device.c +++ b/src/class/mtp/mtp_device.c @@ -70,6 +70,10 @@ typedef struct } context; } mtpd_interface_t; +typedef struct { + TUD_EPBUF_TYPE_DEF(mtp_generic_container_t, container); +} mtpd_epbuf_t; + //--------------------------------------------------------------------+ // INTERNAL FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -102,7 +106,8 @@ static mtp_phase_type_t mtpd_handle_cmd_format_store(void); // MTP variable declaration //--------------------------------------------------------------------+ static mtpd_interface_t _mtpd_itf; -CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN static mtp_generic_container_t _mtpd_gct; +CFG_TUD_MEM_SECTION static mtpd_epbuf_t _mtpd_epbuf; + CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN static mtp_device_status_res_t _mtpd_device_status_res; CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint32_t _mtpd_get_object_handle; CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN static mtp_basic_object_info_t _mtpd_soi; @@ -122,8 +127,9 @@ bool mtpd_deinit(void) { } void mtpd_reset(uint8_t rhport) { + (void) rhport; tu_memclr(&_mtpd_itf, sizeof(mtpd_interface_t)); - tu_memclr(&_mtpd_gct, sizeof(mtp_generic_container_t)); + tu_memclr(&_mtpd_epbuf, sizeof(mtpd_epbuf_t)); tu_memclr(&_mtpd_soi, sizeof(mtp_basic_object_info_t)); _mtpd_get_object_handle = 0; } @@ -135,7 +141,7 @@ uint16_t mtpd_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16 MTP_PROTOCOL_PIMA_15470 == itf_desc->bInterfaceProtocol, 0); // mtp driver length is fixed - uint16_t const mtpd_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); + const uint16_t mtpd_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); // Max length must be at least 1 interface + 3 endpoints TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= mtpd_itf_size); @@ -152,7 +158,7 @@ uint16_t mtpd_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16 TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(ep_desc), 2, TUSB_XFER_BULK, &p_mtp->ep_out, &p_mtp->ep_in), 0); // Prepare rx on bulk out EP - TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, ((uint8_t *)(&_mtpd_gct)), CFG_MTP_EP_SIZE), 0); + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, (uint8_t *)(&_mtpd_epbuf.container), CFG_MTP_EP_SIZE), 0); return mtpd_itf_size; } @@ -179,7 +185,7 @@ bool mtpd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG_DRV(" MTP request: MTP_REQ_RESET\n"); tud_mtp_storage_reset(); // Prepare for a new command - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct)), CFG_MTP_EP_SIZE)); + TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, (uint8_t *)(&_mtpd_epbuf.container), CFG_MTP_EP_SIZE)); break; case MTP_REQ_GET_DEVICE_STATUS: { @@ -209,39 +215,42 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t return true; } + mtpd_interface_t* p_mtp = &_mtpd_itf; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + // IN transfer completed - if (ep_addr == _mtpd_itf.ep_in) { - if (_mtpd_itf.phase == MTP_PHASE_RESPONSE) { + if (ep_addr == p_mtp->ep_in) { + if (p_mtp->phase == MTP_PHASE_RESPONSE) { // IN transfer completed, prepare for a new command - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct)), CFG_MTP_EP_SIZE), 0); - _mtpd_itf.phase = MTP_PHASE_IDLE; - } else if (_mtpd_itf.phase == MTP_PHASE_DATA_IN) { - _mtpd_itf.xferred_len += xferred_bytes; - _mtpd_itf.handled_len = _mtpd_itf.xferred_len; + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, (uint8_t*) &_mtpd_epbuf.container, CFG_MTP_EP_SIZE), 0); + p_mtp->phase = MTP_PHASE_IDLE; + } else if (p_mtp->phase == MTP_PHASE_DATA_IN) { + p_mtp->xferred_len += xferred_bytes; + p_mtp->handled_len = p_mtp->xferred_len; // Check if transfer completed - if (_mtpd_itf.xferred_len >= _mtpd_itf.total_len && (xferred_bytes == 0 || (xferred_bytes % CFG_MTP_EP_SIZE) != 0)) { - _mtpd_itf.phase = MTP_PHASE_RESPONSE; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_OK; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; - _mtpd_gct.transaction_id = _mtpd_itf.context.transaction_id; - if (_mtpd_itf.context.session_id != 0) { - _mtpd_gct.data[0] = _mtpd_itf.context.session_id; - _mtpd_gct.container_length += sizeof(uint32_t); + 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->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = MTP_RESP_OK; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->transaction_id = p_mtp->context.transaction_id; + if (p_mtp->context.session_id != 0) { + p_container->data[0] = p_mtp->context.session_id; + p_container->len += sizeof(uint32_t); } - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_in, ((uint8_t *)(&_mtpd_gct)), (uint16_t)_mtpd_gct.container_length), 0); + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, (uint8_t*) &_mtpd_epbuf.container, (uint16_t)p_container->len), 0); } else { // Send next block of DATA // Send Zero-Length Packet - if (_mtpd_itf.xferred_len == _mtpd_itf.total_len) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_in, ((uint8_t *)(&_mtpd_gct.data)), 0 )); + if (p_mtp->xferred_len == p_mtp->total_len) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, ((uint8_t *)(&p_container->data)), 0 )); } else { - _mtpd_itf.phase = mtpd_handle_data(); - if (_mtpd_itf.phase == MTP_PHASE_RESPONSE) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_in, ((uint8_t *)(&_mtpd_gct)), (uint16_t)_mtpd_gct.container_length)); + p_mtp->phase = mtpd_handle_data(); + if (p_mtp->phase == MTP_PHASE_RESPONSE) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, (uint8_t*) &_mtpd_epbuf.container, (uint16_t)p_container->len)); } else { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_in, ((uint8_t *)(&_mtpd_gct.data)), (uint16_t)_mtpd_itf.queued_len)); + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, ((uint8_t *)(&p_container->data)), (uint16_t)p_mtp->queued_len)); } } } @@ -250,93 +259,93 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } } - if (ep_addr == _mtpd_itf.ep_out) { - if (_mtpd_itf.phase == MTP_PHASE_IDLE) { + if (ep_addr == p_mtp->ep_out) { + if (p_mtp->phase == MTP_PHASE_IDLE) { // A new command has been received. Ensure this is the last of the sequence. - _mtpd_itf.total_len = _mtpd_gct.container_length; + p_mtp->total_len = p_container->len; // Stall in case of unexpected block - if (_mtpd_gct.container_type != MTP_CONTAINER_TYPE_COMMAND_BLOCK) { + if (p_container->type != MTP_CONTAINER_TYPE_COMMAND_BLOCK) { return false; } - _mtpd_itf.phase = MTP_PHASE_COMMAND; - _mtpd_itf.total_len = _mtpd_gct.container_length; - _mtpd_itf.xferred_len = xferred_bytes; - _mtpd_itf.handled_len = 0; - _mtpd_itf.xfer_completed = false; - TU_ASSERT(_mtpd_itf.total_len < sizeof(mtp_generic_container_t)); + p_mtp->phase = MTP_PHASE_COMMAND; + p_mtp->total_len = p_container->len; + p_mtp->xferred_len = xferred_bytes; + p_mtp->handled_len = 0; + p_mtp->xfer_completed = false; + TU_ASSERT(p_mtp->total_len < sizeof(mtp_generic_container_t)); } - if (_mtpd_itf.phase == MTP_PHASE_COMMAND) { + if (p_mtp->phase == MTP_PHASE_COMMAND) { // A zero-length or a short packet termination is expected - if (xferred_bytes == CFG_MTP_EP_SIZE || (_mtpd_itf.total_len - _mtpd_itf.xferred_len) > 0) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct)) + _mtpd_itf.xferred_len, (uint16_t)(_mtpd_itf.total_len - _mtpd_itf.xferred_len))); + if (xferred_bytes == CFG_MTP_EP_SIZE || (p_mtp->total_len - p_mtp->xferred_len) > 0) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, (uint8_t*) &_mtpd_epbuf.container + p_mtp->xferred_len, (uint16_t)(p_mtp->total_len - p_mtp->xferred_len))); } else { // Handle command block - _mtpd_itf.phase = mtpd_handle_cmd(); - if (_mtpd_itf.phase == MTP_PHASE_RESPONSE) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_in, ((uint8_t *)(&_mtpd_gct)), (uint16_t)_mtpd_gct.container_length)); - } else if (_mtpd_itf.phase == MTP_PHASE_DATA_IN) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_in, ((uint8_t *)(&_mtpd_gct)), (uint16_t)_mtpd_itf.queued_len)); - _mtpd_itf.total_len = _mtpd_gct.container_length; - _mtpd_itf.xferred_len = 0; - _mtpd_itf.handled_len = 0; - _mtpd_itf.xfer_completed = false; - } else if (_mtpd_itf.phase == MTP_PHASE_DATA_OUT) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct)), CFG_MTP_EP_SIZE), 0); - _mtpd_itf.xferred_len = 0; - _mtpd_itf.handled_len = 0; - _mtpd_itf.xfer_completed = false; + p_mtp->phase = mtpd_handle_cmd(); + if (p_mtp->phase == MTP_PHASE_RESPONSE) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, (uint8_t*) &_mtpd_epbuf.container, (uint16_t)p_container->len)); + } else if (p_mtp->phase == MTP_PHASE_DATA_IN) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, (uint8_t*) &_mtpd_epbuf.container, (uint16_t)p_mtp->queued_len)); + p_mtp->total_len = p_container->len; + p_mtp->xferred_len = 0; + p_mtp->handled_len = 0; + p_mtp->xfer_completed = false; + } else if (p_mtp->phase == MTP_PHASE_DATA_OUT) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, (uint8_t*) &_mtpd_epbuf.container, CFG_MTP_EP_SIZE), 0); + p_mtp->xferred_len = 0; + p_mtp->handled_len = 0; + p_mtp->xfer_completed = false; } else { - usbd_edpt_stall(rhport, _mtpd_itf.ep_out); - usbd_edpt_stall(rhport, _mtpd_itf.ep_in); + usbd_edpt_stall(rhport, p_mtp->ep_out); + usbd_edpt_stall(rhport, p_mtp->ep_in); } } return true; } - if (_mtpd_itf.phase == MTP_PHASE_DATA_OUT) { + if (p_mtp->phase == MTP_PHASE_DATA_OUT) { // First block of data - if (_mtpd_itf.xferred_len == 0) { - _mtpd_itf.total_len = _mtpd_gct.container_length; - _mtpd_itf.handled_len = 0; - _mtpd_itf.xfer_completed = false; + if (p_mtp->xferred_len == 0) { + p_mtp->total_len = p_container->len; + p_mtp->handled_len = 0; + p_mtp->xfer_completed = false; } - _mtpd_itf.xferred_len += xferred_bytes; + p_mtp->xferred_len += xferred_bytes; // Stall in case of unexpected block - if (_mtpd_gct.container_type != MTP_CONTAINER_TYPE_DATA_BLOCK) { return false; } + if (p_container->type != MTP_CONTAINER_TYPE_DATA_BLOCK) { return false; } // A zero-length or a short packet termination if (xferred_bytes < CFG_MTP_EP_SIZE) { - _mtpd_itf.xfer_completed = true; + p_mtp->xfer_completed = true; // Handle data block - _mtpd_itf.phase = mtpd_handle_data(); - if (_mtpd_itf.phase == MTP_PHASE_DATA_IN || _mtpd_itf.phase == MTP_PHASE_RESPONSE) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_in, ((uint8_t *)(&_mtpd_gct)), (uint16_t)_mtpd_gct.container_length)); - } else if (_mtpd_itf.phase == MTP_PHASE_DATA_OUT) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct)), CFG_MTP_EP_SIZE), 0); - _mtpd_itf.xferred_len = 0; - _mtpd_itf.xfer_completed = false; + p_mtp->phase = mtpd_handle_data(); + if (p_mtp->phase == MTP_PHASE_DATA_IN || p_mtp->phase == MTP_PHASE_RESPONSE) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_in, (uint8_t*) &_mtpd_epbuf.container, (uint16_t)p_container->len)); + } else if (p_mtp->phase == MTP_PHASE_DATA_OUT) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, (uint8_t*) &_mtpd_epbuf.container, CFG_MTP_EP_SIZE), 0); + p_mtp->xferred_len = 0; + p_mtp->xfer_completed = false; } else { - usbd_edpt_stall(rhport, _mtpd_itf.ep_out); - usbd_edpt_stall(rhport, _mtpd_itf.ep_in); + usbd_edpt_stall(rhport, p_mtp->ep_out); + usbd_edpt_stall(rhport, p_mtp->ep_in); } } else { // Handle data block when container is full - if (_mtpd_itf.xferred_len - _mtpd_itf.handled_len >= MTP_MAX_PACKET_SIZE - CFG_MTP_EP_SIZE) { - _mtpd_itf.phase = mtpd_handle_data(); - _mtpd_itf.handled_len = _mtpd_itf.xferred_len; + 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-lenght 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 (_mtpd_itf.total_len == _mtpd_itf.xferred_len) { - TU_ASSERT(usbd_edpt_xfer(rhport, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct.data)), CFG_MTP_EP_SIZE), 0); - } else if (_mtpd_itf.handled_len == 0) { + 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, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct)) + _mtpd_itf.xferred_len, (uint16_t)TU_MIN(_mtpd_itf.total_len - _mtpd_itf.xferred_len, CFG_MTP_EP_SIZE))); + TU_ASSERT(usbd_edpt_xfer(rhport, p_mtp->ep_out, (uint8_t*) &_mtpd_epbuf.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, _mtpd_itf.ep_out, ((uint8_t *)(&_mtpd_gct.data)) + _mtpd_itf.xferred_len - _mtpd_itf.handled_len, (uint16_t)TU_MIN(_mtpd_itf.total_len - _mtpd_itf.xferred_len, CFG_MTP_EP_SIZE))); + 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))); } } } @@ -351,13 +360,14 @@ bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Decode command and prepare response mtp_phase_type_t mtpd_handle_cmd(void) { - TU_ASSERT(_mtpd_gct.container_type == MTP_CONTAINER_TYPE_COMMAND_BLOCK); - _mtpd_itf.context.transaction_id = _mtpd_gct.transaction_id; - if (_mtpd_gct.code != MTP_OP_SEND_OBJECT) { + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + TU_ASSERT(p_container->type == MTP_CONTAINER_TYPE_COMMAND_BLOCK); + _mtpd_itf.context.transaction_id = p_container->transaction_id; + if (p_container->code != MTP_OP_SEND_OBJECT) { _mtpd_soi.object_handle = 0; } - switch (_mtpd_gct.code) { + switch (p_container->code) { case MTP_OP_GET_DEVICE_INFO: TU_LOG_DRV(" MTP command: MTP_OP_GET_DEVICE_INFO\n"); return mtpd_handle_cmd_get_device_info(); @@ -371,7 +381,7 @@ mtp_phase_type_t mtpd_handle_cmd(void) { TU_LOG_DRV(" MTP command: MTP_OP_GET_STORAGE_IDS\n"); return mtpd_handle_cmd_get_storage_ids(); case MTP_OP_GET_STORAGE_INFO: - TU_LOG_DRV(" MTP command: MTP_OP_GET_STORAGE_INFO for ID=%lu\n", _mtpd_gct.data[0]); + TU_LOG_DRV(" MTP command: MTP_OP_GET_STORAGE_INFO for ID=%lu\n", p_container->data[0]); return mtpd_handle_cmd_get_storage_info(); case MTP_OP_GET_OBJECT_HANDLES: TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT_HANDLES\n"); @@ -401,7 +411,7 @@ mtp_phase_type_t mtpd_handle_cmd(void) { TU_LOG_DRV(" MTP command: MTP_OP_FORMAT_STORE\n"); return mtpd_handle_cmd_format_store(); default: - TU_LOG_DRV(" MTP command: MTP_OP_UNKNOWN_COMMAND %x!!!!\n", _mtpd_gct.code); + TU_LOG_DRV(" MTP command: MTP_OP_UNKNOWN_COMMAND %x!!!!\n", p_container->code); return false; } return true; @@ -409,10 +419,11 @@ mtp_phase_type_t mtpd_handle_cmd(void) { mtp_phase_type_t mtpd_handle_data(void) { - TU_ASSERT(_mtpd_gct.container_type == MTP_CONTAINER_TYPE_DATA_BLOCK); - _mtpd_itf.context.transaction_id = _mtpd_gct.transaction_id; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + TU_ASSERT(p_container->type == MTP_CONTAINER_TYPE_DATA_BLOCK); + _mtpd_itf.context.transaction_id = p_container->transaction_id; - switch(_mtpd_gct.code) + switch(p_container->code) { case MTP_OP_GET_OBJECT: TU_LOG_DRV(" MTP command: MTP_OP_GET_OBJECT-DATA_IN\n"); @@ -424,7 +435,7 @@ mtp_phase_type_t mtpd_handle_data(void) TU_LOG_DRV(" MTP command: MTP_OP_SEND_OBJECT-DATA_OUT\n"); return mtpd_handle_dto_send_object(); default: - TU_LOG_DRV(" MTP command: MTP_OP_UNKNOWN_COMMAND %x!!!!\n", _mtpd_gct.code); + TU_LOG_DRV(" MTP command: MTP_OP_UNKNOWN_COMMAND %x!!!!\n", p_container->code); return false; } return true; @@ -433,11 +444,12 @@ mtp_phase_type_t mtpd_handle_data(void) mtp_phase_type_t mtpd_handle_cmd_get_device_info(void) { TU_VERIFY_STATIC(sizeof(mtp_device_info_t) < MTP_MAX_PACKET_SIZE, "mtp_device_info_t shall fit in MTP_MAX_PACKET_SIZE"); + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_device_info_t); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_DEVICE_INFO; - mtp_device_info_t *d = (mtp_device_info_t *)_mtpd_gct.data; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_device_info_t); + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_DEVICE_INFO; + mtp_device_info_t *d = (mtp_device_info_t *)p_container->data; d->standard_version = 100; d->mtp_vendor_extension_id = 0x06; d->mtp_version = 100; @@ -459,22 +471,23 @@ mtp_phase_type_t mtpd_handle_cmd_get_device_info(void) mtpd_gct_append_wstring(CFG_MTP_DEVICE_VERSION); mtpd_gct_append_wstring(CFG_MTP_SERIAL_NUMBER); - _mtpd_itf.queued_len = _mtpd_gct.container_length; + _mtpd_itf.queued_len = p_container->len; return MTP_PHASE_DATA_IN; } mtp_phase_type_t mtpd_handle_cmd_open_session(void) { - uint32_t session_id = _mtpd_gct.data[0]; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t session_id = p_container->data[0]; mtp_response_t res = tud_mtp_storage_open_session(&session_id); if (res == MTP_RESP_SESSION_ALREADY_OPEN) { - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = res; - _mtpd_gct.container_length += sizeof(_mtpd_gct.data[0]); - _mtpd_gct.data[0] = session_id; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = res; + p_container->len += sizeof(p_container->data[0]); + p_container->data[0] = session_id; _mtpd_itf.context.session_id = session_id; return MTP_PHASE_RESPONSE; } @@ -484,24 +497,25 @@ mtp_phase_type_t mtpd_handle_cmd_open_session(void) _mtpd_itf.context.session_id = session_id; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_OK; + p_container->len = MTP_GENERIC_DATA_BLOCK_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_close_session(void) { - uint32_t session_id = _mtpd_gct.data[0]; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t session_id = p_container->data[0]; mtp_response_t res = tud_mtp_storage_close_session(session_id); _mtpd_itf.context.session_id = session_id; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = res; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = res; return MTP_PHASE_RESPONSE; } @@ -509,16 +523,17 @@ mtp_phase_type_t mtpd_handle_cmd_close_session(void) mtp_phase_type_t mtpd_handle_cmd_get_storage_ids(void) { TU_VERIFY_STATIC(sizeof(mtp_storage_ids_t) < MTP_MAX_PACKET_SIZE, "mtp_storage_ids_t shall fit in MTP_MAX_PACKET_SIZE"); + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; uint32_t storage_id; mtp_response_t res = tud_mtp_get_storage_id(&storage_id); mtp_phase_type_t phase; if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_storage_ids_t); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_STORAGE_IDS; - mtp_storage_ids_t *d = (mtp_storage_ids_t *)_mtpd_gct.data; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_storage_ids_t); + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_STORAGE_IDS; + mtp_storage_ids_t *d = (mtp_storage_ids_t *)p_container->data; if (storage_id == 0) { // Storage not accessible @@ -531,38 +546,39 @@ mtp_phase_type_t mtpd_handle_cmd_get_storage_ids(void) d->storage_ids[0] = storage_id; } - _mtpd_itf.queued_len = _mtpd_gct.container_length; + _mtpd_itf.queued_len = p_container->len; return MTP_PHASE_DATA_IN; } mtp_phase_type_t mtpd_handle_cmd_get_storage_info(void) { TU_VERIFY_STATIC(sizeof(mtp_storage_info_t) < MTP_MAX_PACKET_SIZE, "mtp_storage_info_t shall fit in MTP_MAX_PACKET_SIZE"); + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t storage_id = p_container->data[0]; - uint32_t storage_id = _mtpd_gct.data[0]; - - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_storage_info_t); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_STORAGE_INFO; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_storage_info_t); + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_STORAGE_INFO; - mtp_response_t res = tud_mtp_get_storage_info(storage_id, (mtp_storage_info_t *)_mtpd_gct.data); + mtp_response_t res = tud_mtp_get_storage_info(storage_id, (mtp_storage_info_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; - _mtpd_itf.queued_len = _mtpd_gct.container_length; + _mtpd_itf.queued_len = p_container->len; return MTP_PHASE_DATA_IN; } mtp_phase_type_t mtpd_handle_cmd_get_object_handles(void) { - uint32_t storage_id = _mtpd_gct.data[0]; - uint32_t object_format_code = _mtpd_gct.data[1]; // optional, not managed - uint32_t parent_object_handle = _mtpd_gct.data[2]; // folder specification, 0xffffffff=objects with no parent + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t storage_id = p_container->data[0]; + uint32_t object_format_code = p_container->data[1]; // optional, not managed + uint32_t parent_object_handle = p_container->data[2]; // folder specification, 0xffffffff=objects with no parent - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(uint32_t); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_OBJECT_HANDLES; - _mtpd_gct.data[0] = 0; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(uint32_t); + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_OBJECT_HANDLES; + p_container->data[0] = 0; mtp_phase_type_t phase; if ((phase = mtpd_chk_generic(__func__, (object_format_code != 0), MTP_RESP_SPECIFICATION_BY_FORMAT_UNSUPPORTED, "specification by format unsupported")) != MTP_PHASE_NONE) return phase; @@ -581,30 +597,31 @@ mtp_phase_type_t mtpd_handle_cmd_get_object_handles(void) } tud_mtp_storage_object_done(); - _mtpd_itf.queued_len = _mtpd_gct.container_length; + _mtpd_itf.queued_len = p_container->len; return MTP_PHASE_DATA_IN; } mtp_phase_type_t mtpd_handle_cmd_get_object_info(void) { TU_VERIFY_STATIC(sizeof(mtp_object_info_t) < MTP_MAX_PACKET_SIZE, "mtp_object_info_t shall fit in MTP_MAX_PACKET_SIZE"); + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t object_handle = p_container->data[0]; - uint32_t object_handle = _mtpd_gct.data[0]; - - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_object_info_t); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_OBJECT_INFO; - mtp_response_t res = tud_mtp_storage_object_read_info(object_handle, (mtp_object_info_t *)_mtpd_gct.data); + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_object_info_t); + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_OBJECT_INFO; + mtp_response_t res = tud_mtp_storage_object_read_info(object_handle, (mtp_object_info_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; - _mtpd_itf.queued_len = _mtpd_gct.container_length; + _mtpd_itf.queued_len = p_container->len; return MTP_PHASE_DATA_IN; } mtp_phase_type_t mtpd_handle_cmd_get_object(void) { - _mtpd_get_object_handle = _mtpd_gct.data[0]; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + _mtpd_get_object_handle = p_container->data[0]; // Continue with DATA-IN return mtpd_handle_dti_get_object(); @@ -615,11 +632,12 @@ mtp_phase_type_t mtpd_handle_dti_get_object(void) mtp_response_t res; mtp_phase_type_t phase; uint32_t file_size = 0; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; res = tud_mtp_storage_object_size(_mtpd_get_object_handle, &file_size); if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + file_size; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_OBJECT; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH + file_size; + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_OBJECT; uint32_t buffer_size; uint32_t read_count; @@ -628,7 +646,7 @@ mtp_phase_type_t mtpd_handle_dti_get_object(void) { // First data block: include container header buffer_size = ((MTP_MAX_PACKET_SIZE + MTP_GENERIC_DATA_BLOCK_LENGTH) / CFG_MTP_EP_SIZE) * CFG_MTP_EP_SIZE - MTP_GENERIC_DATA_BLOCK_LENGTH; - res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&_mtpd_gct.data, buffer_size, &read_count); + res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&p_container->data, buffer_size, &read_count); if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_itf.queued_len = MTP_GENERIC_DATA_BLOCK_LENGTH + read_count; } @@ -636,7 +654,7 @@ mtp_phase_type_t mtpd_handle_dti_get_object(void) { // Successive data block: consider only container data buffer_size = (MTP_MAX_PACKET_SIZE / CFG_MTP_EP_SIZE) * CFG_MTP_EP_SIZE; - res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&_mtpd_gct.data, buffer_size, &read_count); + res = tud_mtp_storage_object_read(_mtpd_get_object_handle, (void *)&p_container->data, buffer_size, &read_count); if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; _mtpd_itf.queued_len = read_count; } @@ -652,23 +670,25 @@ mtp_phase_type_t mtpd_handle_dti_get_object(void) mtp_phase_type_t mtpd_handle_cmd_delete_object(void) { - uint32_t object_handle = _mtpd_gct.data[0]; - uint32_t object_code_format = _mtpd_gct.data[1]; // not used + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t object_handle = p_container->data[0]; + uint32_t object_code_format = p_container->data[1]; // not used (void) object_code_format; mtp_response_t res = tud_mtp_storage_object_delete(object_handle); mtp_phase_type_t phase; if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_OK; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = MTP_RESP_OK; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } mtp_phase_type_t mtpd_handle_cmd_get_device_prop_desc(void) { - uint32_t device_prop_code = _mtpd_gct.data[0]; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t device_prop_code = p_container->data[0]; mtp_phase_type_t rt; if ((rt = mtpd_chk_session_open(__func__)) != MTP_PHASE_NONE) return rt; @@ -678,58 +698,60 @@ 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"); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_DEVICE_PROP_DESC; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_device_prop_desc_t); - mtp_device_prop_desc_t *d = (mtp_device_prop_desc_t *)_mtpd_gct.data; + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_DEVICE_PROP_DESC; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH + sizeof(mtp_device_prop_desc_t); + mtp_device_prop_desc_t *d = (mtp_device_prop_desc_t *)p_container->data; d->device_property_code = (uint16_t)(device_prop_code); d->datatype = MTP_TYPE_STR; d->get_set = MTP_MODE_GET; mtpd_gct_append_wstring(CFG_TUD_MODEL); // factory_def_value mtpd_gct_append_wstring(CFG_TUD_MODEL); // current_value_len mtpd_gct_append_uint8(0x00); // form_flag - _mtpd_itf.queued_len = _mtpd_gct.container_length; + _mtpd_itf.queued_len = p_container->len; return MTP_PHASE_DATA_IN; } default: break; } - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_PARAMETER_NOT_SUPPORTED; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = MTP_RESP_PARAMETER_NOT_SUPPORTED; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } mtp_phase_type_t mtpd_handle_cmd_get_device_prop_value(void) { - uint32_t device_prop_code = _mtpd_gct.data[0]; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t device_prop_code = p_container->data[0]; mtp_phase_type_t rt; if ((rt = mtpd_chk_session_open(__func__)) != MTP_PHASE_NONE) return rt; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_DATA_BLOCK; - _mtpd_gct.code = MTP_OP_GET_DEVICE_PROP_VALUE; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->code = MTP_OP_GET_DEVICE_PROP_VALUE; switch(device_prop_code) { // TODO support more device properties case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: mtpd_gct_append_wstring(CFG_TUD_MODEL); - _mtpd_itf.queued_len = _mtpd_gct.container_length; + _mtpd_itf.queued_len = p_container->len; return MTP_PHASE_DATA_IN; default: - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_PARAMETER_NOT_SUPPORTED; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = MTP_RESP_PARAMETER_NOT_SUPPORTED; return MTP_PHASE_RESPONSE; } } mtp_phase_type_t mtpd_handle_cmd_send_object_info(void) { - _mtpd_soi.storage_id = _mtpd_gct.data[0]; - _mtpd_soi.parent_object_handle = (_mtpd_gct.data[1] == 0xFFFFFFFF ? 0 : _mtpd_gct.data[1]); + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + _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; @@ -737,8 +759,9 @@ mtp_phase_type_t mtpd_handle_cmd_send_object_info(void) mtp_phase_type_t mtpd_handle_dto_send_object_info(void) { + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; 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_t *)_mtpd_gct.data); + 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); mtp_phase_type_t phase; if ((phase = mtpd_chk_generic(__func__, (res != MTP_RESP_OK), res, "")) != MTP_PHASE_NONE) return phase; @@ -746,12 +769,12 @@ mtp_phase_type_t mtpd_handle_dto_send_object_info(void) _mtpd_soi.object_handle = new_object_handle; // Response - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH + 3 * sizeof(uint32_t); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_OK; - _mtpd_gct.data[0] = _mtpd_soi.storage_id; - _mtpd_gct.data[1] = _mtpd_soi.parent_object_handle; - _mtpd_gct.data[2] = _mtpd_soi.object_handle; + p_container->len = MTP_GENERIC_DATA_BLOCK_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; } @@ -763,7 +786,8 @@ mtp_phase_type_t mtpd_handle_cmd_send_object(void) mtp_phase_type_t mtpd_handle_dto_send_object(void) { - uint8_t *buffer = (uint8_t *)&_mtpd_gct.data; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + 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) @@ -787,23 +811,24 @@ mtp_phase_type_t mtpd_handle_dto_send_object(void) // Send completed tud_mtp_storage_object_done(); - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_OK; + p_container->len = MTP_GENERIC_DATA_BLOCK_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) { - uint32_t storage_id = _mtpd_gct.data[0]; - uint32_t file_system_format = _mtpd_gct.data[1]; // not used + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint32_t storage_id = p_container->data[0]; + uint32_t file_system_format = p_container->data[1]; // not used (void) file_system_format; mtp_response_t res = tud_mtp_storage_format(storage_id); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = res; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = res; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } @@ -813,12 +838,13 @@ mtp_phase_type_t mtpd_handle_cmd_format_store(void) mtp_phase_type_t mtpd_chk_session_open(const char *func_name) { (void)func_name; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; if (_mtpd_itf.context.session_id == 0) { TU_LOG_DRV(" MTP error: %s session not open\n", func_name); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = MTP_RESP_SESSION_NOT_OPEN; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = MTP_RESP_SESSION_NOT_OPEN; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } return MTP_PHASE_NONE; @@ -828,12 +854,13 @@ mtp_phase_type_t mtpd_chk_generic(const char *func_name, const bool err_cd, cons { (void)func_name; (void)message; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; if (err_cd) { TU_LOG_DRV(" MTP error in %s: (%x) %s\n", func_name, ret_code, message); - _mtpd_gct.container_type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; - _mtpd_gct.code = ret_code; - _mtpd_gct.container_length = MTP_GENERIC_DATA_BLOCK_LENGTH; + p_container->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->code = ret_code; + p_container->len = MTP_GENERIC_DATA_BLOCK_LENGTH; return MTP_PHASE_RESPONSE; } return MTP_PHASE_NONE; @@ -860,31 +887,34 @@ void mtpd_wc16cpy(uint8_t *dest, const char *src) //--------------------------------------------------------------------+ bool mtpd_gct_append_uint8(const uint8_t value) { - uint8_t *p_value = ((uint8_t *)&_mtpd_gct) + _mtpd_gct.container_length; - _mtpd_gct.container_length += sizeof(uint8_t); + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint8_t *p_value = ((uint8_t *)p_container) + p_container->len; + p_container->len += sizeof(uint8_t); // Verify space requirement (8 bit string length, number of wide characters including terminator) - TU_ASSERT(_mtpd_gct.container_length < sizeof(mtp_generic_container_t)); + TU_ASSERT(p_container->len < sizeof(mtp_generic_container_t)); *p_value = value; return true; } bool mtpd_gct_append_object_handle(const uint32_t object_handle) { - _mtpd_gct.container_length += sizeof(uint32_t); - TU_ASSERT(_mtpd_gct.container_length < sizeof(mtp_generic_container_t)); - _mtpd_gct.data[0]++; - _mtpd_gct.data[_mtpd_gct.data[0]] = object_handle; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + p_container->len += sizeof(uint32_t); + TU_ASSERT(p_container->len < sizeof(mtp_generic_container_t)); + p_container->data[0]++; + p_container->data[p_container->data[0]] = object_handle; return true; } bool mtpd_gct_append_wstring(const char *s) { + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; size_t len = strlen(s) + 1; TU_ASSERT(len <= UINT8_MAX); - uint8_t *p_len = ((uint8_t *)&_mtpd_gct)+_mtpd_gct.container_length; - _mtpd_gct.container_length += sizeof(uint8_t) + sizeof(wchar16_t) * len; + uint8_t *p_len = ((uint8_t *)p_container)+p_container->len; + p_container->len += sizeof(uint8_t) + sizeof(wchar16_t) * len; // Verify space requirement (8 bit string length, number of wide characters including terminator) - TU_ASSERT(_mtpd_gct.container_length < sizeof(mtp_generic_container_t)); + TU_ASSERT(p_container->len < sizeof(mtp_generic_container_t)); *p_len = (uint8_t)len; uint8_t *p_str = p_len + sizeof(uint8_t); mtpd_wc16cpy(p_str, s); @@ -893,12 +923,13 @@ bool mtpd_gct_append_wstring(const char *s) bool mtpd_gct_get_string(uint16_t *offset_data, char *string, const uint16_t max_size) { - uint16_t size = *(((uint8_t *)&_mtpd_gct.data) + *offset_data); + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + uint16_t size = *(((uint8_t *)&p_container->data) + *offset_data); if (size > max_size) size = max_size; - TU_ASSERT(*offset_data + size < sizeof(_mtpd_gct.data)); + TU_ASSERT(*offset_data + size < sizeof(p_container->data)); - uint8_t *s = ((uint8_t *)&_mtpd_gct.data) + *offset_data + sizeof(uint8_t); + uint8_t *s = ((uint8_t *)&p_container->data) + *offset_data + sizeof(uint8_t); for(uint16_t i = 0; i < size; i++) { string[i] = *s; @@ -910,19 +941,21 @@ bool mtpd_gct_get_string(uint16_t *offset_data, char *string, const uint16_t max bool mtpd_gct_append_array(uint32_t array_size, const void *data, size_t type_size) { - TU_ASSERT(_mtpd_gct.container_length + sizeof(uint32_t) + array_size * type_size < sizeof(_mtpd_gct.data)); - uint8_t *p = ((uint8_t *)&_mtpd_gct) + _mtpd_gct.container_length; + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; + TU_ASSERT(p_container->len + sizeof(uint32_t) + array_size * type_size < sizeof(p_container->data)); + uint8_t *p = ((uint8_t *)p_container) + p_container->len; memcpy(p, &array_size, sizeof(uint32_t)); p += sizeof(uint32_t); memcpy(p, data, array_size * type_size); - _mtpd_gct.container_length += sizeof(uint32_t) + array_size * type_size; + p_container->len += sizeof(uint32_t) + array_size * type_size; return true; } bool mtpd_gct_append_date(struct tm *timeinfo) { + mtp_generic_container_t* p_container = &_mtpd_epbuf.container; // strftime is not supported by all platform, this implementation is just for reference - int len = snprintf(_mtp_datestr, sizeof(_mtpd_gct.data) - _mtpd_gct.container_length, "%04d%02d%02dT%02d%02d%02dZ", + int len = snprintf(_mtp_datestr, sizeof(p_container->data) - p_container->len, "%04d%02d%02dT%02d%02d%02dZ", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, diff --git a/src/device/usbd.c b/src/device/usbd.c index 8620c3b6f..e5542914a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -331,6 +331,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = mtpd_open, .control_xfer_cb = mtpd_control_xfer_cb, .xfer_cb = mtpd_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif -- cgit v1.3.1 From 369a1ff5153a472327d2847c7bc7386309486b34 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 17 Sep 2025 22:37:45 +0200 Subject: Update weak callbacks to new syntax Signed-off-by: HiFiPhile --- hw/bsp/board_api.h | 6 +- src/class/bth/bth_device.c | 130 ++++++++++++++++++++------------------- src/class/bth/bth_device.h | 8 +-- src/class/cdc/cdc_device.c | 60 +++++++++++++----- src/class/cdc/cdc_device.h | 14 ++--- src/class/cdc/cdc_host.c | 39 +++++++----- src/class/cdc/cdc_host.h | 8 +-- src/class/dfu/dfu_device.c | 27 +++++--- src/class/dfu/dfu_device.h | 6 +- src/class/hid/hid_host.c | 84 +++++++++++++++++-------- src/class/hid/hid_host.h | 12 ++-- src/class/midi/midi_device.c | 12 +++- src/class/midi/midi_device.h | 4 +- src/class/msc/msc_device.c | 111 ++++++++++++++++++++------------- src/class/msc/msc_device.h | 16 ++--- src/class/msc/msc_host.c | 19 ++++-- src/class/msc/msc_host.h | 4 +- src/class/usbtmc/usbtmc_device.c | 29 ++++++--- src/class/usbtmc/usbtmc_device.h | 8 +-- src/class/vendor/vendor_device.c | 22 +++++-- src/class/vendor/vendor_device.h | 4 +- src/class/video/video_device.c | 33 +++++++--- src/class/video/video_device.h | 6 +- src/common/tusb_common.h | 8 +-- src/device/dcd.h | 2 +- src/device/usbd.c | 13 ++-- src/device/usbd_pvt.h | 2 +- src/host/usbh.c | 25 +++++--- src/host/usbh.h | 6 +- src/host/usbh_pvt.h | 2 +- src/typec/usbc.c | 25 ++++++-- src/typec/usbc.h | 4 +- 32 files changed, 467 insertions(+), 282 deletions(-) (limited to 'src/device') diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 328fe9363..111829b4f 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -72,10 +72,10 @@ extern "C" { void board_init(void); // Init board after tinyusb is initialized -void board_init_after_tusb(void) TU_ATTR_WEAK; +void board_init_after_tusb(void); // Jump to bootloader -void board_reset_to_bootloader(void) TU_ATTR_WEAK; +void board_reset_to_bootloader(void); // Turn LED on or off void board_led_write(bool state); @@ -89,7 +89,7 @@ void board_led_write(bool state); uint32_t board_button_read(void); // Get board unique ID for USB serial number. Return number of bytes. Note max_len is typically 16 -TU_ATTR_WEAK size_t board_get_unique_id(uint8_t id[], size_t max_len); +size_t board_get_unique_id(uint8_t id[], size_t max_len); // Get characters from UART. Return number of read bytes int board_uart_read(uint8_t *buf, int len); diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 45cbf2d98..3f1529cb6 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -43,7 +43,7 @@ typedef struct { uint8_t ep_acl_in; uint16_t ep_acl_in_pkt_sz; uint8_t ep_acl_out; - uint8_t ep_voice[2]; // Not used yet + uint8_t ep_voice[2];// Not used yet uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; // Previous amount of bytes sent when issuing ZLP @@ -61,8 +61,7 @@ typedef struct { static btd_interface_t _btd_itf; CFG_TUD_MEM_SECTION static btd_epbuf_t _btd_epbuf; -static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) -{ +static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) { uint8_t const rhport = 0; // skip if previous transfer not complete @@ -73,6 +72,27 @@ static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) return true; } +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len) { + (void) hci_cmd; + (void) cmd_len; +} + +TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len) { + (void) acl_data; + (void) data_len; +} + +TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes) { + (void) sent_bytes; +} + +TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes) { + (void) sent_bytes; +} + //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -82,13 +102,11 @@ static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) // WRITE API //--------------------------------------------------------------------+ -bool tud_bt_event_send(void *event, uint16_t event_len) -{ +bool tud_bt_event_send(void *event, uint16_t event_len) { return bt_tx_data(_btd_itf.ep_ev, event, event_len); } -bool tud_bt_acl_data_send(void *event, uint16_t event_len) -{ +bool tud_bt_acl_data_send(void *event, uint16_t event_len) { return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); } @@ -103,13 +121,11 @@ bool btd_deinit(void) { return true; } -void btd_reset(uint8_t rhport) -{ - (void)rhport; +void btd_reset(uint8_t rhport) { + (void) rhport; } -uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ +uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { tusb_desc_endpoint_t const *desc_ep; uint16_t drv_len = 0; // Size of single alternative of ISO interface @@ -118,8 +134,9 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); // Ensure this is BT Primary Controller TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, + 0); TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size); @@ -131,10 +148,10 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); _btd_itf.ep_ev = desc_ep->bEndpointAddress; - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep); // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, (uint8_t const *)desc_ep, 2, + TU_ASSERT(usbd_open_edpt_pair(rhport, (uint8_t const *) desc_ep, 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, &_btd_itf.ep_acl_in), 0); @@ -146,10 +163,10 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ _btd_itf.ep_acl_in_pkt_sz = tu_edpt_packet_size(desc_ep_acl_in); break; } - desc_ep_acl_in = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep_acl_in); + desc_ep_acl_in = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep_acl_in); } - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(desc_ep)); + itf_desc = (tusb_desc_interface_t const *) tu_desc_next(tu_desc_next(desc_ep)); // Prepare for incoming data from host TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); @@ -158,13 +175,14 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ // Ensure this is still BT Primary Controller TU_ASSERT(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, + 0); TU_ASSERT(itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size + drv_len); uint8_t dir; - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); dir = tu_edpt_dir(desc_ep->bEndpointAddress); @@ -172,7 +190,7 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ // Store endpoint size for alternative _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep); TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); dir = tu_edpt_dir(desc_ep->bEndpointAddress); _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; @@ -182,29 +200,30 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { // Make sure rest of alternatives matches - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); + itf_desc = (tusb_desc_interface_t const *) tu_desc_next(desc_ep); if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) - { + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) { // Not an Iso interface instance break; } TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); dir = tu_edpt_dir(desc_ep->bEndpointAddress); // Verify that alternative endpoint are same as first ones TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, + 0); _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep); dir = tu_edpt_dir(desc_ep->bEndpointAddress); // Verify that alternative endpoint are same as first ones TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, + 0); _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); drv_len += iso_alt_itf_size; } @@ -215,44 +234,32 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) -{ - (void)rhport; +bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { + (void) rhport; - if ( stage == CONTROL_STAGE_SETUP ) - { + if (stage == CONTROL_STAGE_SETUP) { if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) { // HCI command packet addressing for single function Primary Controllers // also compatible with historical mode if enabled TU_VERIFY((request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0) || (CFG_TUD_BTH_HISTORICAL_COMPATIBLE && request->bRequest == 0xe0)); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) - { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) - { + } else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) { // TODO: Set interface it would involve changing size of endpoint size - } - else - { + } else { // HCI command packet for Primary Controller function in a composite device TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); } - } - else return false; + } else + return false; return tud_control_xfer(rhport, request, &_btd_epbuf.hci_cmd, sizeof(bt_hci_cmd_t)); - } - else if ( stage == CONTROL_STAGE_DATA ) - { + } else if (stage == CONTROL_STAGE_DATA) { // Handle class request only TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - if (tud_bt_hci_cmd_cb) { - tud_bt_hci_cmd_cb(&_btd_epbuf.hci_cmd, tu_min16(request->wLength, sizeof(bt_hci_cmd_t))); - } + tud_bt_hci_cmd_cb(&_btd_epbuf.hci_cmd, tu_min16(request->wLength, sizeof(bt_hci_cmd_t))); } return true; @@ -261,19 +268,14 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { // received new data from host - if (ep_addr == _btd_itf.ep_acl_out) - { - if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_epbuf.epout_buf, xferred_bytes); + if (ep_addr == _btd_itf.ep_acl_out) { + tud_bt_acl_data_received_cb(_btd_epbuf.epout_buf, xferred_bytes); // prepare for next data TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); - } - else if (ep_addr == _btd_itf.ep_ev) - { - if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); - } - else if (ep_addr == _btd_itf.ep_acl_in) - { + } else if (ep_addr == _btd_itf.ep_ev) { + tud_bt_event_sent_cb((uint16_t) xferred_bytes); + } else if (ep_addr == _btd_itf.ep_acl_in) { if ((result == XFER_RESULT_SUCCESS) && (xferred_bytes > 0) && ((xferred_bytes & (_btd_itf.ep_acl_in_pkt_sz - 1)) == 0)) { // Save number of transferred bytes @@ -281,12 +283,12 @@ bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, // Send zero-length packet tud_bt_acl_data_send(NULL, 0); - } else if (tud_bt_acl_data_sent_cb) { + } else { if (xferred_bytes == 0) { xferred_bytes = _btd_itf.prev_xferred_bytes; _btd_itf.prev_xferred_bytes = 0; } - tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); + tud_bt_acl_data_sent_cb((uint16_t) xferred_bytes); } } diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index 4f6350839..68f073bff 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -67,23 +67,23 @@ typedef struct TU_ATTR_PACKED // Part E, 5.4.1. // Length of the command is from 3 bytes (2 bytes for OpCode, // 1 byte for parameter total length) to 258. -TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); +void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); // Invoked when ACL data was received over USB from Bluetooth host. // Detailed format is described in Bluetooth core specification Vol 2, // Part E, 5.4.2. // Length is from 4 bytes, (12 bits for Handle, 4 bits for flags // and 16 bits for data total length) to endpoint size. -TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); +void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); // Called when event sent with tud_bt_event_send() was delivered to BT stack. // Controller can release/reuse buffer with Event packet at this point. -TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); +void tud_bt_event_sent_cb(uint16_t sent_bytes); // Called when ACL data that was sent with tud_bt_acl_data_send() // was delivered to BT stack. // Controller can release/reuse buffer with ACL packet at this point. -TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); +void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); // Bluetooth controller calls this function when it wants to send even packet // as described in Bluetooth core specification Vol 2, Part E, 5.4.4. diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 4e4e01eaf..f1c4a3bbf 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -119,6 +119,42 @@ static bool _prep_out_transaction(uint8_t itf) { } } +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf) { + (void) itf; +} + +TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { + (void) itf; + (void) wanted_char; +} + +TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf) { + (void) itf; +} + +TU_ATTR_WEAK void tud_cdc_notify_complete_cb(uint8_t itf) { + (void) itf; +} + +TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { + (void) itf; + (void) dtr; + (void) rts; +} + +TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) { + (void) itf; + (void) p_line_coding; +} + +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { + (void) itf; + (void) duration_ms; +} + //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ @@ -419,9 +455,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ TU_LOG_DRV(" Set Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); } else if (stage == CONTROL_STAGE_ACK) { - if (tud_cdc_line_coding_cb) { - tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } + tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); } break; @@ -456,9 +490,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if (tud_cdc_line_state_cb) { - tud_cdc_line_state_cb(itf, dtr, rts); - } + tud_cdc_line_state_cb(itf, dtr, rts); } break; @@ -467,9 +499,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ tud_control_status(rhport, request); } else if (stage == CONTROL_STAGE_ACK) { TU_LOG_DRV(" Send Break\r\n"); - if (tud_cdc_send_break_cb) { - tud_cdc_send_break_cb(itf, request->wValue); - } + tud_cdc_send_break_cb(itf, request->wValue); } break; @@ -501,7 +531,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, p_epbuf->epout, (uint16_t) xferred_bytes); // Check for wanted char and invoke callback if needed - if (tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1)) { + if (((signed char) p_cdc->wanted_char) != -1) { for (uint32_t i = 0; i < xferred_bytes; i++) { if ((p_cdc->wanted_char == p_epbuf->epout[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); @@ -510,7 +540,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) { + if (!tu_fifo_empty(&p_cdc->rx_ff)) { tud_cdc_rx_cb(itf); } @@ -523,9 +553,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if (ep_addr == p_cdc->ep_in) { // invoke transmit callback to possibly refill tx fifo - if (tud_cdc_tx_complete_cb) { - tud_cdc_tx_complete_cb(itf); - } + tud_cdc_tx_complete_cb(itf); if (0 == tud_cdc_n_write_flush(itf)) { // If there is no data left, a ZLP should be sent if @@ -540,9 +568,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Sent notification to host if (ep_addr == p_cdc->ep_notify) { - if (tud_cdc_notify_complete_cb) { - tud_cdc_notify_complete_cb(itf); - } + tud_cdc_notify_complete_cb(itf); } return true; diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index a34e07e1d..9673b9807 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -220,28 +220,28 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_write_clear(void) { //--------------------------------------------------------------------+ // Invoked when received new data -TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); +void tud_cdc_rx_cb(uint8_t itf); // Invoked when received `wanted_char` -TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); +void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); // Invoked when a TX is complete and therefore space becomes available in TX buffer -TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); +void tud_cdc_tx_complete_cb(uint8_t itf); // Invoked when a notification is sent to host -TU_ATTR_WEAK void tud_cdc_notify_complete_cb(uint8_t itf); +void tud_cdc_notify_complete_cb(uint8_t itf); // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE -TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); // Invoked when line coding is change via SET_LINE_CODING -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); +void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); // Invoked when received send break // \param[in] itf interface for which send break was received. // \param[in] duration_ms the length of time, in milliseconds, of the break signal. If a value of FFFFh, then the // device will send a break until another SendBreak request is received with value 0000h. -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); +void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f9a37ed35..beef03eff 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -391,6 +391,25 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons static bool open_ep_stream_pair(cdch_interface_t * p_cdc , tusb_desc_endpoint_t const *desc_ep); +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tuh_cdc_mount_cb(uint8_t idx) { + (void) idx; +} + +TU_ATTR_WEAK void tuh_cdc_umount_cb(uint8_t idx) { + (void) idx; +} + +TU_ATTR_WEAK void tuh_cdc_rx_cb(uint8_t idx) { + (void) idx; +} + +TU_ATTR_WEAK void tuh_cdc_tx_complete_cb(uint8_t idx) { + (void) idx; +} + //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ @@ -657,9 +676,7 @@ void cdch_close(uint8_t daddr) { TU_LOG_CDC(p_cdc, "close"); // Invoke application callback - if (tuh_cdc_umount_cb) { - tuh_cdc_umount_cb(idx); - } + tuh_cdc_umount_cb(idx); p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; @@ -680,9 +697,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t if (ep_addr == p_cdc->stream.tx.ep_addr) { // invoke tx complete callback to possibly refill tx fifo - if (tuh_cdc_tx_complete_cb) { - tuh_cdc_tx_complete_cb(idx); - } + tuh_cdc_tx_complete_cb(idx); if (0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx)) { // If there is no data left, a ZLP should be sent if: @@ -697,18 +712,14 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t if (xferred_bytes > 2) { tu_edpt_stream_read_xfer_complete_with_buf(&p_cdc->stream.rx, p_cdc->stream.rx.ep_buf + 2, xferred_bytes - 2); - if (tuh_cdc_rx_cb) { - tuh_cdc_rx_cb(idx); // invoke receive callback - } + tuh_cdc_rx_cb(idx); // invoke receive callback } } else #endif { tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - if (tuh_cdc_rx_cb) { - tuh_cdc_rx_cb(idx); // invoke receive callback - } + tuh_cdc_rx_cb(idx); // invoke receive callback } // prepare for next transfer if needed @@ -794,9 +805,7 @@ static void set_config_complete(cdch_interface_t *p_cdc, bool success) { if (success) { const uint8_t idx = get_idx_by_ptr(p_cdc); p_cdc->mounted = true; - if (tuh_cdc_mount_cb) { - tuh_cdc_mount_cb(idx); - } + tuh_cdc_mount_cb(idx); // Prepare for incoming data tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); } else { diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 37bfca270..bf6711d7e 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -230,16 +230,16 @@ TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_disconnect_sync(u // Invoked when a device with CDC interface is mounted // idx is index of cdc interface in the internal pool. -TU_ATTR_WEAK extern void tuh_cdc_mount_cb(uint8_t idx); +extern void tuh_cdc_mount_cb(uint8_t idx); // Invoked when a device with CDC interface is unmounted -TU_ATTR_WEAK extern void tuh_cdc_umount_cb(uint8_t idx); +extern void tuh_cdc_umount_cb(uint8_t idx); // Invoked when received new data -TU_ATTR_WEAK extern void tuh_cdc_rx_cb(uint8_t idx); +extern void tuh_cdc_rx_cb(uint8_t idx); // Invoked when a TX is complete and therefore space becomes available in TX buffer -TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx); +extern void tuh_cdc_tx_complete_cb(uint8_t idx); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index d9e2d3f2f..0d2b63b57 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -76,6 +76,24 @@ static bool reply_getstatus(uint8_t rhport, const tusb_control_request_t* reques static bool process_download_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request); static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request); +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_dfu_detach_cb(void) { +} + +TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt) { + (void) alt; +} + +TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) { + (void) alt; + (void) block_num; + (void) data; + (void) length; + return 0; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ @@ -234,9 +252,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control if (stage == CONTROL_STAGE_SETUP) { tud_control_status(rhport, request); } else if (stage == CONTROL_STAGE_ACK) { - if (tud_dfu_detach_cb) { - tud_dfu_detach_cb(); - } + tud_dfu_detach_cb(); } break; @@ -258,16 +274,13 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control reset_state(); tud_control_status(rhport, request); } else if (stage == CONTROL_STAGE_ACK) { - if (tud_dfu_abort_cb) { - tud_dfu_abort_cb(_dfu_ctx.alt); - } + tud_dfu_abort_cb(_dfu_ctx.alt); } break; case DFU_REQUEST_UPLOAD: if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); - TU_VERIFY(tud_dfu_upload_cb); TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); const uint16_t xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_epbuf.transfer_buf, diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 00c22ea8b..e59e61ce9 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -74,13 +74,13 @@ void tud_dfu_manifest_cb(uint8_t alt); // Invoked when received DFU_UPLOAD request // Application must populate data with up to length bytes and // Return the number of written bytes -TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); +uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received -TU_ATTR_WEAK void tud_dfu_detach_cb(void); +void tud_dfu_detach_cb(void); // Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); +void tud_dfu_abort_cb(uint8_t alt); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a44c83433..da776d04c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -70,6 +70,50 @@ CFG_TUH_MEM_SECTION static hidh_epbuf_t _hidh_epbuf[CFG_TUH_HID]; static uint8_t _hidh_default_protocol = HID_PROTOCOL_BOOT; +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report_desc, uint16_t desc_len) { + (void) dev_addr; + (void) idx; + (void) report_desc; + (void) desc_len; +} + +TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t idx) { + (void) dev_addr; + (void) idx; +} + +TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len) { + (void) dev_addr; + (void) idx; + (void) report; + (void) len; +} + +TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len) { + (void) dev_addr; + (void) idx; + (void) report_id; + (void) report_type; + (void) len; +} + +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len) { + (void) dev_addr; + (void) idx; + (void) report_id; + (void) report_type; + (void) len; +} + +TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol) { + (void) dev_addr; + (void) idx; + (void) protocol; +} + //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ @@ -183,9 +227,7 @@ static void set_protocol_complete(tuh_xfer_t* xfer) { p_hid->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue); } - if (tuh_hid_set_protocol_complete_cb) { - tuh_hid_set_protocol_complete_cb(daddr, idx, p_hid->protocol_mode); - } + tuh_hid_set_protocol_complete_cb(daddr, idx, p_hid->protocol_mode); } void tuh_hid_set_default_protocol(uint8_t protocol) { @@ -230,16 +272,14 @@ bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) { static void get_report_complete(tuh_xfer_t* xfer) { TU_LOG_DRV("HID Get Report complete\r\n"); - if (tuh_hid_get_report_complete_cb) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); - uint8_t const report_type = tu_u16_high(xfer->setup->wValue); + uint8_t const report_type = tu_u16_high(xfer->setup->wValue); uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - tuh_hid_get_report_complete_cb(xfer->daddr, idx, report_id, report_type, - (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); - } + tuh_hid_get_report_complete_cb(xfer->daddr, idx, report_id, report_type, + (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); } bool tuh_hid_get_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) { @@ -274,16 +314,14 @@ bool tuh_hid_get_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t r static void set_report_complete(tuh_xfer_t* xfer) { TU_LOG_DRV("HID Set Report complete\r\n"); - if (tuh_hid_set_report_complete_cb) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); - uint8_t const report_type = tu_u16_high(xfer->setup->wValue); - uint8_t const report_id = tu_u16_low(xfer->setup->wValue); + uint8_t const report_type = tu_u16_high(xfer->setup->wValue); + uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - tuh_hid_set_report_complete_cb(xfer->daddr, idx, report_id, report_type, - (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); - } + tuh_hid_set_report_complete_cb(xfer->daddr, idx, report_id, report_type, + (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); } bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) { @@ -448,9 +486,7 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t TU_LOG3_MEM(epbuf->epin, xferred_bytes, 2); tuh_hid_report_received_cb(daddr, idx, epbuf->epin, (uint16_t) xferred_bytes); } else { - if (tuh_hid_report_sent_cb) { - tuh_hid_report_sent_cb(daddr, idx, epbuf->epout, (uint16_t) xferred_bytes); - } + tuh_hid_report_sent_cb(daddr, idx, epbuf->epout, (uint16_t) xferred_bytes); } return true; @@ -461,9 +497,7 @@ void hidh_close(uint8_t daddr) { hidh_interface_t* p_hid = &_hidh_itf[i]; if (p_hid->daddr == daddr) { TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i); - if (tuh_hid_umount_cb) { - tuh_hid_umount_cb(daddr, i); - } + tuh_hid_umount_cb(daddr, i); tu_memclr(p_hid, sizeof(hidh_interface_t)); } } @@ -625,7 +659,7 @@ static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t con p_hid->mounted = true; // enumeration is complete - if (tuh_hid_mount_cb) tuh_hid_mount_cb(daddr, idx, desc_report, desc_len); + tuh_hid_mount_cb(daddr, idx, desc_report, desc_len); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(daddr, p_hid->itf_num); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 9681c704b..032827af1 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -145,28 +145,28 @@ bool tuh_hid_send_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, const // can be used to parse common/simple enough descriptor. // Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped // therefore report_desc = NULL, desc_len = 0 -TU_ATTR_WEAK void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report_desc, uint16_t desc_len); +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted -TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t idx); +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t idx); // Invoked when received report from device via interrupt endpoint // Note: if there is report ID (composite), it is 1st byte of report void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); // Invoked when sent report to device successfully via interrupt endpoint -TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); +void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); // Invoked when Get Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response -TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); +void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response -TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); +void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); // Invoked when Set Protocol request is complete -TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol); +void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 0bbb3caf4..7dac7c4a5 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -107,6 +107,14 @@ static void _prep_out_transaction(uint8_t idx) { } } + +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf) { + (void) itf; +} + //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -528,9 +536,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 tu_fifo_write_n(&p_midi->rx_ff, _midid_epbuf[idx].epout, (uint16_t)xferred_bytes); // invoke receive callback if available - if (tud_midi_rx_cb) { - tud_midi_rx_cb(idx); - } + tud_midi_rx_cb(idx); // prepare for next // TODO for now ep_out is not used by public API therefore there is no race condition, diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 3e89cc0a3..c2c6e9859 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -116,9 +116,9 @@ static inline bool tud_midi_receive(uint8_t packet[4]) } //--------------------------------------------------------------------+ -// Application Callback API (weak is optional) +// Application Callback API (optional) //--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); +void tud_midi_rx_cb(uint8_t itf); //--------------------------------------------------------------------+ // Inline Functions diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a32014c2d..b0eafd5da 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -223,6 +223,53 @@ static bool proc_stage_status(mscd_interface_t *p_msc) { return true; } +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun) { + (void) lun; +} + +TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun) { + (void) lun; +} + +TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]) { + (void) lun; + (void) scsi_cmd; +} + +TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void) { + return 1; +} + +TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { + (void) lun; + (void) power_condition; + (void) start; + (void) load_eject; + return true; +} + +TU_ATTR_WEAK bool tud_msc_prevent_allow_medium_removal_cb(uint8_t lun, uint8_t prohibit_removal, uint8_t control) { + (void) lun; + (void) prohibit_removal; + (void) control; + return true; +} + +TU_ATTR_WEAK int32_t tud_msc_request_sense_cb(uint8_t lun, void* buffer, uint16_t bufsize) { + (void) lun; + (void) buffer; + (void) bufsize; + return sizeof(scsi_sense_fixed_resp_t); +} + +TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun) { + (void) lun; + return true; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ @@ -403,10 +450,7 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG_DRV(" MSC Get Max Lun\r\n"); TU_VERIFY(request->wValue == 0 && request->wLength == 1); - uint8_t maxlun = 1; - if (tud_msc_get_maxlun_cb) { - maxlun = tud_msc_get_maxlun_cb(); - } + uint8_t maxlun = tud_msc_get_maxlun_cb(); TU_VERIFY(maxlun); maxlun--; // MAX LUN is minus 1 by specs tud_control_xfer(rhport, request, &maxlun, 1); @@ -584,21 +628,15 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // if complete_cb() is invoked after queuing the status. switch (p_cbw->command[0]) { case SCSI_CMD_READ_10: - if (tud_msc_read10_complete_cb) { - tud_msc_read10_complete_cb(p_cbw->lun); - } + tud_msc_read10_complete_cb(p_cbw->lun); break; case SCSI_CMD_WRITE_10: - if (tud_msc_write10_complete_cb) { - tud_msc_write10_complete_cb(p_cbw->lun); - } + tud_msc_write10_complete_cb(p_cbw->lun); break; default: - if (tud_msc_scsi_complete_cb) { - tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); - } + tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); break; } @@ -648,16 +686,14 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ case SCSI_CMD_START_STOP_UNIT: resplen = 0; - if (tud_msc_start_stop_cb) { - scsi_start_stop_unit_t const* start_stop = (scsi_start_stop_unit_t const*)scsi_cmd; - if (!tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject)) { - // Failed status response - resplen = -1; + scsi_start_stop_unit_t const* start_stop = (scsi_start_stop_unit_t const*)scsi_cmd; + if (!tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject)) { + // Failed status response + resplen = -1; - // set default sense if not set by callback - if (p_msc->sense_key == 0) { - set_sense_medium_not_present(lun); - } + // set default sense if not set by callback + if (p_msc->sense_key == 0) { + set_sense_medium_not_present(lun); } } break; @@ -665,16 +701,14 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: resplen = 0; - if (tud_msc_prevent_allow_medium_removal_cb) { - scsi_prevent_allow_medium_removal_t const* prevent_allow = (scsi_prevent_allow_medium_removal_t const*)scsi_cmd; - if (!tud_msc_prevent_allow_medium_removal_cb(lun, prevent_allow->prohibit_removal, prevent_allow->control)) { - // Failed status response - resplen = -1; + scsi_prevent_allow_medium_removal_t const* prevent_allow = (scsi_prevent_allow_medium_removal_t const*)scsi_cmd; + if (!tud_msc_prevent_allow_medium_removal_cb(lun, prevent_allow->prohibit_removal, prevent_allow->control)) { + // Failed status response + resplen = -1; - // set default sense if not set by callback - if (p_msc->sense_key == 0) { - set_sense_medium_not_present(lun); - } + // set default sense if not set by callback + if (p_msc->sense_key == 0) { + set_sense_medium_not_present(lun); } } break; @@ -767,10 +801,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ .block_descriptor_len = 0 // no block descriptor are included }; - bool writable = true; - if (tud_msc_is_writable_cb) { - writable = tud_msc_is_writable_cb(lun); - } + bool writable = tud_msc_is_writable_cb(lun); mode_resp.write_protected = !writable; @@ -794,9 +825,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &sense_rsp, (size_t) resplen)); // request sense callback could overwrite the sense data - if (tud_msc_request_sense_cb) { - resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t)bufsize); - } + resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t)bufsize); // Clear sense data after copy tud_msc_set_sense(lun, 0, 0, 0); @@ -854,11 +883,7 @@ static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { static void proc_write10_cmd(mscd_interface_t* p_msc) { msc_cbw_t const* p_cbw = &p_msc->cbw; - bool writable = true; - - if (tud_msc_is_writable_cb) { - writable = tud_msc_is_writable_cb(p_cbw->lun); - } + bool writable = tud_msc_is_writable_cb(p_cbw->lun); if (!writable) { // Not writable, complete this SCSI op with error diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 144b74f71..7d898e988 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -128,30 +128,30 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, /*------------- Optional callbacks -------------*/ // Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation -TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); +uint8_t tud_msc_get_maxlun_cb(void); // Invoked when received Start Stop Unit command // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage // - Start = 1 : active mode, if load_eject = 1 : load disk storage -TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); //Invoked when we receive the Prevent / Allow Medium Removal command -TU_ATTR_WEAK bool tud_msc_prevent_allow_medium_removal_cb(uint8_t lun, uint8_t prohibit_removal, uint8_t control); +bool tud_msc_prevent_allow_medium_removal_cb(uint8_t lun, uint8_t prohibit_removal, uint8_t control); // Invoked when received REQUEST_SENSE -TU_ATTR_WEAK int32_t tud_msc_request_sense_cb(uint8_t lun, void* buffer, uint16_t bufsize); +int32_t tud_msc_request_sense_cb(uint8_t lun, void* buffer, uint16_t bufsize); // Invoked when Read10 command is complete -TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); +void tud_msc_read10_complete_cb(uint8_t lun); // Invoke when Write10 command is complete, can be used to flush flash caching -TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun); +void tud_msc_write10_complete_cb(uint8_t lun); // Invoked when command in tud_msc_scsi_cb is complete -TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); +void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); // Invoked to check if device is writable as part of SCSI WRITE10 -TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); +bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ef0635bbe..eb69ae400 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -87,6 +87,17 @@ TU_ATTR_ALWAYS_INLINE static inline msch_epbuf_t* get_epbuf(uint8_t daddr) { return &_msch_epbuf[daddr - 1]; } +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr) { + (void) dev_addr; +} + +TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr) { + (void) dev_addr; +} + //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ @@ -304,9 +315,7 @@ void msch_close(uint8_t dev_addr) { // invoke Application Callback if (p_msc->mounted) { - if (tuh_msc_umount_cb) { - tuh_msc_umount_cb(dev_addr); - } + tuh_msc_umount_cb(dev_addr); } tu_memclr(p_msc, sizeof(msch_interface_t)); @@ -497,9 +506,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_dat // Mark enumeration is complete p_msc->mounted = true; - if (tuh_msc_mount_cb) { - tuh_msc_mount_cb(dev_addr); - } + tuh_msc_mount_cb(dev_addr); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 09d777066..b5fd55547 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -109,10 +109,10 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r //------------- Application Callback -------------// // Invoked when a device with MassStorage interface is mounted -TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); +void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); +void tuh_msc_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 7ec939b64..3f6bedd4c 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -159,6 +159,25 @@ TU_VERIFY_STATIC(USBTMCD_BUFFER_SIZE >= 32u, "USBTMC dev buffer size too small") static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); + +// USBTMC Device Callbacks weak implementations +TU_ATTR_WEAK bool tud_usbtmc_notification_complete_cb(void) { + return true; +} + +TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult) { + (void) msg; + (void) tmcResult; + return true; +} + +#if (CFG_TUD_USBTMC_ENABLE_488) +TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg) { + (void) msg; + return true; +} +#endif + #ifndef NDEBUG tu_static uint8_t termChar; #endif @@ -262,16 +281,10 @@ void usbtmcd_init_cb(void) { usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); #ifndef NDEBUG #if CFG_TUD_USBTMC_ENABLE_488 - if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { - TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL, ); - } // Per USB488 spec: table 8 TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly, ); TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly, ); #endif - if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { - TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL, ); - } #endif usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); @@ -587,9 +600,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_ASSERT(false); } } else if (ep_addr == usbtmc_state.ep_int_in) { - if (tud_usbtmc_notification_complete_cb) { - TU_VERIFY(tud_usbtmc_notification_complete_cb()); - } + TU_VERIFY(tud_usbtmc_notification_complete_cb()); return true; } return false; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index b85ef12b5..8238f579f 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -75,15 +75,15 @@ bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); // The interrupt-IN endpoint buffer was transmitted to the host. Use // tud_usbtmc_transmit_notification_data to send another notification. -TU_ATTR_WEAK bool tud_usbtmc_notification_complete_cb(void); +bool tud_usbtmc_notification_complete_cb(void); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); +bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_TUD_USBTMC_ENABLE_488) uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); +bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); +//void tud_usbtmc_app_go_to_local_cb(); #endif // Called from app diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index b0332b0fe..27724b194 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -67,6 +67,20 @@ typedef struct { CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR]; +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf, uint8_t const* buffer, uint16_t bufsize) { + (void) itf; + (void) buffer; + (void) bufsize; +} + +TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) { + (void) itf; + (void) sent_bytes; +} + //-------------------------------------------------------------------- // Application API //-------------------------------------------------------------------- @@ -259,16 +273,12 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint tu_edpt_stream_read_xfer_complete(&p_vendor->rx.stream, xferred_bytes); // Invoked callback if any - if (tud_vendor_rx_cb) { - tud_vendor_rx_cb(itf, p_epbuf->epout, (uint16_t) xferred_bytes); - } + tud_vendor_rx_cb(itf, p_epbuf->epout, (uint16_t) xferred_bytes); tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream); } else if ( ep_addr == p_vendor->tx.stream.ep_addr ) { // Send complete - if (tud_vendor_tx_cb) { - tud_vendor_tx_cb(itf, (uint16_t) xferred_bytes); - } + tud_vendor_tx_cb(itf, (uint16_t) xferred_bytes); #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 // try to send more if possible diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 149ae2d56..5fe4fc9ff 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -119,9 +119,9 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) { //--------------------------------------------------------------------+ // Invoked when received new data -TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +void tud_vendor_rx_cb(uint8_t itf, uint8_t const* buffer, uint16_t bufsize); // Invoked when last rx transfer finished -TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes); +void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes); //--------------------------------------------------------------------+ // Inline Functions diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index 3124d5596..5c00cc358 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -192,6 +192,28 @@ static char const* const tu_str_video_vs_control_selector[] = { #endif +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + (void) ctl_idx; + (void) stm_idx; +} + +TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod) { + (void) ctl_idx; + (void) power_mod; + return VIDEO_ERROR_NONE; +} + +TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, + video_probe_and_commit_control_t const *parameters) { + (void) ctl_idx; + (void) stm_idx; + (void) parameters; + return VIDEO_ERROR_NONE; +} + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -902,7 +924,7 @@ static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); } else if (stage == CONTROL_STAGE_DATA) { - if (tud_video_power_mode_cb) return tud_video_power_mode_cb(ctl_idx, self->power_mode); + return tud_video_power_mode_cb(ctl_idx, self->power_mode); } return VIDEO_ERROR_NONE; @@ -1104,10 +1126,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, TU_VERIFY(_update_streaming_parameters(stm, param), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); /* Set the negotiated value */ stm->max_payload_transfer_size = param->dwMaxPayloadTransferSize; - int ret = VIDEO_ERROR_NONE; - if (tud_video_commit_cb) { - ret = tud_video_commit_cb(stm->index_vc, stm->index_vs, param); - } + int ret = tud_video_commit_cb(stm->index_vc, stm->index_vs, param); if (VIDEO_ERROR_NONE == ret) { stm->state = VS_STATE_COMMITTED; stm->buffer = NULL; @@ -1419,9 +1438,7 @@ bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 stm->buffer = NULL; stm->bufsize = 0; stm->offset = 0; - if (tud_video_frame_xfer_complete_cb) { - tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); - } + tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); } return true; } diff --git a/src/class/video/video_device.h b/src/class/video/video_device.h index 648a221d5..2b41c3bfe 100644 --- a/src/class/video/video_device.h +++ b/src/class/video/video_device.h @@ -61,7 +61,7 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu * * @param[in] ctl_idx Destination control interface index * @param[in] stm_idx Destination streaming interface index */ -TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); +void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -72,7 +72,7 @@ TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fa * @param[in] ctl_idx Destination control interface index * @param[in] stm_idx Destination streaming interface index * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); +int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); /** Invoked when VS_COMMIT_CONTROL(SET_CUR) request received * @@ -80,7 +80,7 @@ TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod * @param[in] stm_idx Destination streaming interface index * @param[in] parameters Video streaming parameters * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, +int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, video_probe_and_commit_control_t const *parameters); //--------------------------------------------------------------------+ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index e35d3e6fe..9c4699362 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -89,14 +89,14 @@ extern uint32_t tusb_time_millis_api(void); extern void tusb_time_delay_ms_api(uint32_t ms); // flush data cache -TU_ATTR_WEAK extern void tusb_app_dcache_flush(uintptr_t addr, uint32_t data_size); +extern void tusb_app_dcache_flush(uintptr_t addr, uint32_t data_size); // invalidate data cache -TU_ATTR_WEAK extern void tusb_app_dcache_invalidate(uintptr_t addr, uint32_t data_size); +extern void tusb_app_dcache_invalidate(uintptr_t addr, uint32_t data_size); // Optional physical <-> virtual address translation -TU_ATTR_WEAK extern void* tusb_app_virt_to_phys(void *virt_addr); -TU_ATTR_WEAK extern void* tusb_app_phys_to_virt(void *phys_addr); +extern void* tusb_app_virt_to_phys(void *virt_addr); +extern void* tusb_app_phys_to_virt(void *phys_addr); //--------------------------------------------------------------------+ // Internal Inline Functions diff --git a/src/device/dcd.h b/src/device/dcd.h index 789552d47..400f62bff 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -162,7 +162,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer // Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack // This API is optional, may be useful for register-based for transferring data. -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Stall endpoint, any queuing transfer should be removed from endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index b09d02fbd..6b5c3d846 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -393,6 +393,13 @@ void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) { + (void) driver_count; + return NULL; +} //--------------------------------------------------------------------+ // Debug @@ -516,10 +523,8 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_ASSERT(_usbd_q); // Get application driver if available - if (usbd_app_driver_get_cb) { - _app_driver = usbd_app_driver_get_cb(&_app_driver_count); - TU_ASSERT(_app_driver_count + BUILTIN_DRIVER_COUNT <= UINT8_MAX); - } + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + TU_ASSERT(_app_driver_count + BUILTIN_DRIVER_COUNT <= UINT8_MAX); // Init class drivers for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index f1797bf0d..a688cf497 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -64,7 +64,7 @@ typedef struct { // Invoked when initializing device stack to get additional class drivers. // Can be implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active -usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; +usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count); typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/src/host/usbh.c b/src/host/usbh.c index d09874d6e..fafcc0fef 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -88,6 +88,19 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si return false; } +TU_ATTR_WEAK usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) { + (void) driver_count; + return NULL; +} + +TU_ATTR_WEAK void tuh_mount_cb(uint8_t daddr) { + (void) daddr; +} + +TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr) { + (void) daddr; +} + //--------------------------------------------------------------------+ // Data Structure //--------------------------------------------------------------------+ @@ -481,9 +494,7 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { #endif // Get application driver if available - if (usbh_app_driver_get_cb) { - _app_driver = usbh_app_driver_get_cb(&_app_driver_count); - } + _app_driver = usbh_app_driver_get_cb(&_app_driver_count); // Device tu_memclr(_usbh_devices, sizeof(_usbh_devices)); @@ -1319,9 +1330,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub #endif { // Invoke callback before closing driver (maybe call it later ?) - if (tuh_umount_cb) { - tuh_umount_cb(daddr); - } + tuh_umount_cb(daddr); } // Close class driver @@ -1910,9 +1919,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { TU_LOG_USBH("HUB address = %u is mounted\r\n", dev_addr); }else { // Invoke callback if available - if (tuh_mount_cb) { - tuh_mount_cb(dev_addr); - } + tuh_mount_cb(dev_addr); } } } diff --git a/src/host/usbh.h b/src/host/usbh.h index 1e9bb26bc..8d48bf90d 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -123,13 +123,13 @@ void tuh_enum_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc bool tuh_enum_descriptor_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config); // Invoked when a device is mounted (configured) -TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); +void tuh_mount_cb (uint8_t daddr); // Invoked when a device failed to mount during enumeration process -// TU_ATTR_WEAK void tuh_mount_failed_cb (uint8_t daddr); +// void tuh_mount_failed_cb (uint8_t daddr); // Invoked when a device is unmounted (detached) -TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr); +void tuh_umount_cb(uint8_t daddr); // Invoked when there is a new usb event, which need to be processed by tuh_task()/tuh_task_ext() void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index cb092e5f3..9d91e52e8 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -58,7 +58,7 @@ typedef struct { // Invoked when initializing host stack to get additional class drivers. // Can be implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active -usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; +usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count); // Call by class driver to tell USBH that it has complete the enumeration void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); diff --git a/src/typec/usbc.c b/src/typec/usbc.c index fdf2a0cd6..20abd1700 100644 --- a/src/typec/usbc.c +++ b/src/typec/usbc.c @@ -59,6 +59,23 @@ bool usbc_msg_send(uint8_t rhport, pd_header_t const* header, void const* data); bool parse_msg_data(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end); bool parse_msg_control(uint8_t rhport, pd_header_t const* header); +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK bool tuc_pd_data_received_cb(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end) { + (void) rhport; + (void) header; + (void) dobj; + (void) p_end; + return false; +} + +TU_ATTR_WEAK bool tuc_pd_control_received_cb(uint8_t rhport, pd_header_t const* header) { + (void) rhport; + (void) header; + return false; +} + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -136,17 +153,13 @@ void tuc_task_ext(uint32_t timeout_ms, bool in_isr) { } bool parse_msg_data(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end) { - if (tuc_pd_data_received_cb) { - tuc_pd_data_received_cb(rhport, header, dobj, p_end); - } + tuc_pd_data_received_cb(rhport, header, dobj, p_end); return true; } bool parse_msg_control(uint8_t rhport, pd_header_t const* header) { - if (tuc_pd_control_received_cb) { - tuc_pd_control_received_cb(rhport, header); - } + tuc_pd_control_received_cb(rhport, header); return true; } diff --git a/src/typec/usbc.h b/src/typec/usbc.h index 9fbff9bc6..448542aab 100644 --- a/src/typec/usbc.h +++ b/src/typec/usbc.h @@ -74,8 +74,8 @@ extern void tcd_int_handler(uint8_t rhport); // Callbacks //--------------------------------------------------------------------+ -TU_ATTR_WEAK bool tuc_pd_data_received_cb(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end); -TU_ATTR_WEAK bool tuc_pd_control_received_cb(uint8_t rhport, pd_header_t const* header); +bool tuc_pd_data_received_cb(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end); +bool tuc_pd_control_received_cb(uint8_t rhport, pd_header_t const* header); //--------------------------------------------------------------------+ // -- cgit v1.3.1 From e621f2f77b19dce0a9f288ebd608ebf98d2f817b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 18 Sep 2025 19:09:10 +0200 Subject: set driver count to 0 Signed-off-by: HiFiPhile --- src/device/usbd.c | 2 +- src/host/usbh.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 6b5c3d846..5792359f6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -397,7 +397,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ TU_ATTR_WEAK usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) { - (void) driver_count; + *driver_count = 0; return NULL; } diff --git a/src/host/usbh.c b/src/host/usbh.c index fafcc0fef..6bafde368 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -89,7 +89,7 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si } TU_ATTR_WEAK usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) { - (void) driver_count; + *driver_count = 0; return NULL; } -- cgit v1.3.1 From 0961e06845591792031b69515bc56f2e5b3fa60d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 18 Sep 2025 19:14:27 +0200 Subject: Add usbd_edpt_xfer_fifo stub Signed-off-by: HiFiPhile --- src/device/usbd.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 5792359f6..b1aef0b38 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -401,6 +401,11 @@ TU_ATTR_WEAK usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_c return NULL; } +TU_ATTR_WEAK bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { + (void) rhport; (void) ep_addr; (void) ff; (void) total_bytes; + return false; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ -- cgit v1.3.1 From 981dc982ce2e8b37041e47d0c17f479d08f11bd6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 Oct 2025 15:57:59 +0700 Subject: mtp example work with highspeed device --- examples/device/mtp/src/usb_descriptors.c | 72 ++++++++++++++++++++++++++++--- src/device/usbd.h | 2 +- 2 files changed, 68 insertions(+), 6 deletions(-) (limited to 'src/device') diff --git a/examples/device/mtp/src/usb_descriptors.c b/examples/device/mtp/src/usb_descriptors.c index ddda4d686..cabb96439 100644 --- a/examples/device/mtp/src/usb_descriptors.c +++ b/examples/device/mtp/src/usb_descriptors.c @@ -109,18 +109,79 @@ enum #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MTP_DESC_LEN) -uint8_t const desc_fs_configuration[] = { +// full speed configuration +const uint8_t desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + // Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size TUD_MTP_DESCRIPTOR(ITF_NUM_MTP, 4, EPNUM_MTP_EVT, 64, 1, EPNUM_MTP_OUT, EPNUM_MTP_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + +// high speed configuration +uint8_t const desc_hs_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + // Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size + TUD_MTP_DESCRIPTOR(ITF_NUM_MTP, 4, EPNUM_MTP_EVT, 64, 1, EPNUM_MTP_OUT, EPNUM_MTP_IN, 512), +}; + +// other speed configuration +uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const *tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const *) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + memcpy(desc_other_speed_config, + (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, + CONFIG_TOTAL_LEN); + desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; + return desc_other_speed_config; +} + +#endif // highspeed + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { +const uint8_t*tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; +#else return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ @@ -173,11 +234,12 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { } const char *str = string_desc_arr[index]; - // Cap at max char chr_count = strlen(str); - size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if ( chr_count > max_count ) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/src/device/usbd.h b/src/device/usbd.h index 1dc3761d9..a4104e47d 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -276,7 +276,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Length of template descriptor: 30 bytes #define TUD_MTP_DESC_LEN (9 + 7 + 7 + 7) -// Interface number, string index, EP Out & EP In address, EP size +// Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size #define TUD_MTP_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_polling_interval, _epout, _epin, _epsize) \ /* Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUSB_CLASS_IMAGE, MTP_SUBCLASS_STILL_IMAGE, MTP_PROTOCOL_PIMA_15470, _stridx,\ -- cgit v1.3.1