├── .gitignore ├── icon.jpg ├── README.md ├── source ├── log.cpp ├── MtpRequestPacket.cpp ├── MtpEventPacket.cpp ├── MtpResponsePacket.cpp ├── USBSerialInterface.cpp ├── USBMtpInterface.cpp ├── nxlink.cpp ├── MtpStorage.cpp ├── MtpStorageInfo.cpp ├── MtpUtils.cpp ├── MtpDeviceInfo.cpp ├── MtpObjectInfo.cpp ├── MtpPacket.cpp ├── MtpStringBuffer.cpp ├── main.cpp ├── MtpDataPacket.cpp ├── usb.c ├── MtpProperty.cpp └── MtpDebug.cpp ├── include ├── nxlink.h ├── MtpUtils.h ├── MtpDebug.h ├── log.h ├── MtpEventPacket.h ├── MtpResponsePacket.h ├── usb.h ├── MtpRequestPacket.h ├── MtpStorageInfo.h ├── MtpDeviceInfo.h ├── MtpStringBuffer.h ├── MtpObjectInfo.h ├── USBSerialInterface.h ├── MtpStorage.h ├── MtpPacket.h ├── USBMtpInterface.h ├── MtpTypes.h ├── MtpProperty.h ├── MtpDataPacket.h ├── MtpDatabase.h ├── MtpServer.h └── mtp.h ├── mtp-server-nx.json ├── Makefile └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | /build 3 | *.elf 4 | *.nacp 5 | *.nro 6 | -------------------------------------------------------------------------------- /icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/retronx-team/mtp-server-nx/HEAD/icon.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mtp-server-nx 2 | A port of https://manpages.ubuntu.com/manpages/xenial/man1/mtp-server.1.html for Nintendo Switch 3 | 4 | ## Author 5 | Gillou68310 6 | 7 | ## Known Issues 8 | - Startup takes long with a lot of Files on the SD Card, due to scanning 9 | - Transfer speed can still be improved 10 | - Untested on Horizon < 6.1 11 | 12 | ## License 13 | Apache 2.0 14 | -------------------------------------------------------------------------------- /source/log.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "log.h" 18 | 19 | int verbose_level = 0; 20 | 21 | char log_level_color[5][16] = 22 | { 23 | "\033[37m", // White 24 | "\033[32m", // Green 25 | "\033[93m", // Yellow 26 | "\033[31m", // Red 27 | "\033[35m" // Purple 28 | }; -------------------------------------------------------------------------------- /include/nxlink.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __NXLINK_H 18 | #define __NXLINK_H 19 | 20 | #include "USBSerialInterface.h" 21 | 22 | extern int nxlink; 23 | 24 | void nxlinkStdioInitialise(USBSerialInterface* usb); 25 | void nxlinkStdioClose(USBSerialInterface* usb); 26 | 27 | #endif /* __NXLINK_H */ 28 | -------------------------------------------------------------------------------- /include/MtpUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_UTILS_H 18 | #define _MTP_UTILS_H 19 | 20 | #include 21 | 22 | namespace android { 23 | 24 | bool parseDateTime(const char* dateTime, time_t& outSeconds); 25 | void formatDateTime(time_t seconds, char* buffer, int bufferLength); 26 | 27 | }; // namespace android 28 | 29 | #endif // _MTP_UTILS_H 30 | -------------------------------------------------------------------------------- /include/MtpDebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_DEBUG_H 18 | #define _MTP_DEBUG_H 19 | 20 | #include "MtpTypes.h" 21 | 22 | namespace android { 23 | 24 | class MtpDebug { 25 | public: 26 | static const char* getOperationCodeName(MtpOperationCode code); 27 | static const char* getFormatCodeName(MtpObjectFormat code); 28 | static const char* getObjectPropCodeName(MtpPropertyCode code); 29 | static const char* getDevicePropCodeName(MtpPropertyCode code); 30 | }; 31 | 32 | }; // namespace android 33 | 34 | #endif // _MTP_DEBUG_H 35 | -------------------------------------------------------------------------------- /source/MtpRequestPacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpRequestPacket" 18 | 19 | #include 20 | #include 21 | 22 | #include "MtpRequestPacket.h" 23 | 24 | namespace android { 25 | 26 | MtpRequestPacket::MtpRequestPacket() 27 | : MtpPacket(512) 28 | { 29 | } 30 | 31 | MtpRequestPacket::~MtpRequestPacket() { 32 | } 33 | 34 | int MtpRequestPacket::read(USBMtpInterface* usb) { 35 | int ret = usb->read((char*)mBuffer, mBufferSize); 36 | if (ret >= 0) 37 | mPacketSize = ret; 38 | else 39 | mPacketSize = 0; 40 | return ret; 41 | } 42 | 43 | } // namespace android 44 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __LOGGING_H 18 | #define __LOGGING_H 19 | 20 | #include 21 | #include "nxlink.h" 22 | 23 | #define VERBOSE 0 24 | #define INFO 1 25 | #define WARNING 2 26 | #define ERROR 3 27 | #define FATAL 4 28 | 29 | extern int verbose_level; 30 | extern char log_level_color[5][16]; 31 | 32 | #define LOG(level) std::cout << "\n" << (nxlink ? log_level_color[level] : "") 33 | 34 | #define VLOG_IS_ON(verboselevel) (verboselevel <= verbose_level) 35 | #define VLOG(verboselevel) if(VLOG_IS_ON(verboselevel)) std::cout << "\n" << (nxlink ? log_level_color[VERBOSE]: "" ) 36 | 37 | #endif /* __LOGGING_H */ 38 | -------------------------------------------------------------------------------- /source/MtpEventPacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpEventPacket" 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "MtpEventPacket.h" 26 | 27 | namespace android { 28 | 29 | MtpEventPacket::MtpEventPacket() 30 | : MtpPacket(512) 31 | { 32 | } 33 | 34 | MtpEventPacket::~MtpEventPacket() { 35 | } 36 | 37 | int MtpEventPacket::write(USBMtpInterface* usb) { 38 | putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize); 39 | putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_EVENT); 40 | 41 | int ret = usb->sendEvent((const char*)mBuffer, mPacketSize); 42 | return (ret < 0 ? ret : 0); 43 | } 44 | 45 | } // namespace android 46 | 47 | -------------------------------------------------------------------------------- /source/MtpResponsePacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpResponsePacket" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "MtpResponsePacket.h" 25 | 26 | namespace android { 27 | 28 | MtpResponsePacket::MtpResponsePacket() 29 | : MtpPacket(512) 30 | { 31 | } 32 | 33 | MtpResponsePacket::~MtpResponsePacket() { 34 | } 35 | 36 | int MtpResponsePacket::write(USBMtpInterface* usb) { 37 | putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize); 38 | putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_RESPONSE); 39 | int ret = usb->write((const char*)mBuffer, mPacketSize); 40 | return (ret < 0 ? ret : 0); 41 | } 42 | 43 | } // namespace android 44 | 45 | -------------------------------------------------------------------------------- /include/MtpEventPacket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_EVENT_PACKET_H 18 | #define _MTP_EVENT_PACKET_H 19 | 20 | #include "MtpPacket.h" 21 | #include "mtp.h" 22 | 23 | namespace android { 24 | 25 | class MtpEventPacket : public MtpPacket { 26 | 27 | public: 28 | MtpEventPacket(); 29 | virtual ~MtpEventPacket(); 30 | 31 | // write our data to the given file descriptor 32 | int write(USBMtpInterface* usb); 33 | 34 | inline MtpEventCode getEventCode() const { return getContainerCode(); } 35 | inline void setEventCode(MtpEventCode code) 36 | { return setContainerCode(code); } 37 | }; 38 | 39 | }; // namespace android 40 | 41 | #endif // _MTP_EVENT_PACKET_H 42 | -------------------------------------------------------------------------------- /include/MtpResponsePacket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_RESPONSE_PACKET_H 18 | #define _MTP_RESPONSE_PACKET_H 19 | 20 | #include "MtpPacket.h" 21 | #include "mtp.h" 22 | 23 | namespace android { 24 | 25 | class MtpResponsePacket : public MtpPacket { 26 | 27 | public: 28 | MtpResponsePacket(); 29 | virtual ~MtpResponsePacket(); 30 | 31 | // write our data to the given file descriptor 32 | int write(USBMtpInterface* usb); 33 | 34 | inline MtpResponseCode getResponseCode() const { return getContainerCode(); } 35 | inline void setResponseCode(MtpResponseCode code) 36 | { return setContainerCode(code); } 37 | }; 38 | 39 | }; // namespace android 40 | 41 | #endif // _MTP_RESPONSE_PACKET_H 42 | -------------------------------------------------------------------------------- /include/usb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __USB_H 18 | #define __USB_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include 25 | 26 | typedef struct { 27 | struct usb_interface_descriptor *interface_desc; 28 | struct usb_endpoint_descriptor *endpoint_desc[4]; 29 | const char *string_descriptor; 30 | } UsbInterfaceDesc; 31 | 32 | typedef enum { 33 | UsbDirection_Read = 0, 34 | UsbDirection_Write = 1, 35 | } UsbDirection; 36 | 37 | Result usbInitialize(struct usb_device_descriptor *device_descriptor, u32 num_interfaces, const UsbInterfaceDesc *infos); 38 | void usbExit(void); 39 | size_t usbTransfer(u32 interface, u32 endpoint, UsbDirection dir, void* buffer, size_t size, u64 timeout); 40 | 41 | #ifdef __cplusplus 42 | } // extern "C" 43 | #endif 44 | 45 | #endif /* __USB_H */ 46 | -------------------------------------------------------------------------------- /include/MtpRequestPacket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_REQUEST_PACKET_H 18 | #define _MTP_REQUEST_PACKET_H 19 | 20 | #include "MtpPacket.h" 21 | #include "mtp.h" 22 | 23 | namespace android { 24 | 25 | class MtpRequestPacket : public MtpPacket { 26 | 27 | public: 28 | MtpRequestPacket(); 29 | virtual ~MtpRequestPacket(); 30 | 31 | // fill our buffer with data from the given file descriptor 32 | int read(USBMtpInterface* usb); 33 | 34 | inline MtpOperationCode getOperationCode() const { return getContainerCode(); } 35 | inline void setOperationCode(MtpOperationCode code) 36 | { return setContainerCode(code); } 37 | }; 38 | 39 | }; // namespace android 40 | 41 | #endif // _MTP_REQUEST_PACKET_H 42 | -------------------------------------------------------------------------------- /source/USBSerialInterface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "USBSerialInterface.h" 18 | 19 | #define EP_IN 0 20 | #define EP_OUT 1 21 | 22 | USBSerialInterface::USBSerialInterface(int index, UsbInterfaceDesc *info) 23 | { 24 | interface_index = index; 25 | info->interface_desc = &serial_interface_descriptor; 26 | info->endpoint_desc[EP_IN] = &serial_endpoint_descriptor_in; 27 | info->endpoint_desc[EP_OUT] = &serial_endpoint_descriptor_out; 28 | info->string_descriptor = NULL; 29 | } 30 | 31 | USBSerialInterface::~USBSerialInterface() { 32 | } 33 | 34 | ssize_t USBSerialInterface::read(char *ptr, size_t len) 35 | { 36 | return usbTransfer(interface_index, EP_OUT, UsbDirection_Read, (void*)ptr, len, UINT64_MAX); 37 | } 38 | ssize_t USBSerialInterface::write(const char *ptr, size_t len) 39 | { 40 | return usbTransfer(interface_index, EP_IN, UsbDirection_Write, (void*)ptr, len, UINT64_MAX); 41 | } 42 | -------------------------------------------------------------------------------- /include/MtpStorageInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_STORAGE_INFO_H 18 | #define _MTP_STORAGE_INFO_H 19 | 20 | #include "MtpTypes.h" 21 | 22 | namespace android { 23 | 24 | class MtpDataPacket; 25 | 26 | class MtpStorageInfo { 27 | public: 28 | MtpStorageID mStorageID; 29 | uint16_t mStorageType; 30 | uint16_t mFileSystemType; 31 | uint16_t mAccessCapability; 32 | uint64_t mMaxCapacity; 33 | uint64_t mFreeSpaceBytes; 34 | uint32_t mFreeSpaceObjects; 35 | char* mStorageDescription; 36 | char* mVolumeIdentifier; 37 | 38 | public: 39 | MtpStorageInfo(MtpStorageID id); 40 | virtual ~MtpStorageInfo(); 41 | 42 | void read(MtpDataPacket& packet); 43 | 44 | void print(); 45 | }; 46 | 47 | }; // namespace android 48 | 49 | #endif // _MTP_STORAGE_INFO_H 50 | -------------------------------------------------------------------------------- /source/USBMtpInterface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "USBMtpInterface.h" 18 | 19 | #define EP_IN 0 20 | #define EP_OUT 1 21 | #define EP_INT 2 22 | 23 | USBMtpInterface::USBMtpInterface(int index, UsbInterfaceDesc *info) 24 | { 25 | interface_index = index; 26 | info->interface_desc = &mtp_interface_descriptor; 27 | info->endpoint_desc[EP_IN] = &mtp_endpoint_descriptor_in; 28 | info->endpoint_desc[EP_OUT] = &mtp_endpoint_descriptor_out; 29 | info->endpoint_desc[EP_INT] = &mtp_endpoint_descriptor_interrupt; 30 | info->string_descriptor = mtp_string_descriptor; 31 | } 32 | 33 | USBMtpInterface::~USBMtpInterface() { 34 | } 35 | 36 | ssize_t USBMtpInterface::read(char *ptr, size_t len) 37 | { 38 | return usbTransfer(interface_index, EP_OUT, UsbDirection_Read, (void*)ptr, len, 1000000000LL); 39 | } 40 | ssize_t USBMtpInterface::write(const char *ptr, size_t len) 41 | { 42 | return usbTransfer(interface_index, EP_IN, UsbDirection_Write, (void*)ptr, len, UINT64_MAX); 43 | } 44 | ssize_t USBMtpInterface::sendEvent(const char *ptr, size_t len) 45 | { 46 | return usbTransfer(interface_index, EP_INT, UsbDirection_Write, (void*)ptr, len, UINT64_MAX); 47 | } -------------------------------------------------------------------------------- /include/MtpDeviceInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_DEVICE_INFO_H 18 | #define _MTP_DEVICE_INFO_H 19 | 20 | struct stat; 21 | 22 | namespace android { 23 | 24 | class MtpDataPacket; 25 | 26 | class MtpDeviceInfo { 27 | public: 28 | uint16_t mStandardVersion; 29 | uint32_t mVendorExtensionID; 30 | uint16_t mVendorExtensionVersion; 31 | char* mVendorExtensionDesc; 32 | uint16_t mFunctionalCode; 33 | UInt16List* mOperations; 34 | UInt16List* mEvents; 35 | MtpDevicePropertyList* mDeviceProperties; 36 | MtpObjectFormatList* mCaptureFormats; 37 | MtpObjectFormatList* mPlaybackFormats; 38 | char* mManufacturer; 39 | char* mModel; 40 | char* mVersion; 41 | char* mSerial; 42 | 43 | public: 44 | MtpDeviceInfo(); 45 | virtual ~MtpDeviceInfo(); 46 | 47 | void read(MtpDataPacket& packet); 48 | 49 | void print(); 50 | }; 51 | 52 | }; // namespace android 53 | 54 | #endif // _MTP_DEVICE_INFO_H 55 | -------------------------------------------------------------------------------- /source/nxlink.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "log.h" 22 | 23 | int nxlink = 0; 24 | 25 | static USBSerialInterface* _usb; 26 | 27 | static ssize_t write_stdout(struct _reent *r,void *fd,const char *ptr, size_t len) 28 | { 29 | return _usb->write(ptr, len); 30 | } 31 | 32 | static const devoptab_t dotab_stdout = { 33 | "usb", 34 | 0, 35 | NULL, 36 | NULL, 37 | write_stdout, 38 | NULL, 39 | NULL, 40 | NULL 41 | }; 42 | 43 | void nxlinkStdioInitialise(USBSerialInterface* usb) 44 | { 45 | if(usb != NULL) 46 | { 47 | _usb = usb; 48 | devoptab_list[STD_OUT] = &dotab_stdout; 49 | devoptab_list[STD_ERR] = &dotab_stdout; 50 | setvbuf(stdout, NULL , _IONBF, 0); 51 | setvbuf(stderr, NULL , _IONBF, 0); 52 | 53 | // Wait for start command 54 | char start[7]; 55 | while(strcmp(start, "#START#") != 0) 56 | { 57 | usb->read(start, 7); 58 | } 59 | } 60 | } 61 | 62 | void nxlinkStdioClose(USBSerialInterface* usb) 63 | { 64 | if(usb != NULL) 65 | { 66 | const char *stop = "#STOP#"; 67 | usb->write(stop, 6); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /include/MtpStringBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_STRING_BUFFER_H 18 | #define _MTP_STRING_BUFFER_H 19 | 20 | #include 21 | 22 | namespace android { 23 | 24 | class MtpDataPacket; 25 | 26 | // Represents a utf8 string, with a maximum of 255 characters 27 | class MtpStringBuffer { 28 | 29 | private: 30 | // mBuffer contains string in UTF8 format 31 | // maximum 3 bytes/character, with 1 extra for zero termination 32 | uint8_t mBuffer[255 * 3 + 1]; 33 | int mCharCount; 34 | int mByteCount; 35 | 36 | public: 37 | MtpStringBuffer(); 38 | MtpStringBuffer(const char* src); 39 | MtpStringBuffer(const uint16_t* src); 40 | MtpStringBuffer(const MtpStringBuffer& src); 41 | virtual ~MtpStringBuffer(); 42 | 43 | void set(const char* src); 44 | void set(const uint16_t* src); 45 | 46 | void readFromPacket(MtpDataPacket* packet); 47 | void writeToPacket(MtpDataPacket* packet) const; 48 | 49 | inline int getCharCount() const { return mCharCount; } 50 | inline int getByteCount() const { return mByteCount; } 51 | 52 | inline operator const char*() const { return (const char *)mBuffer; } 53 | }; 54 | 55 | }; // namespace android 56 | 57 | #endif // _MTP_STRING_BUFFER_H 58 | -------------------------------------------------------------------------------- /include/MtpObjectInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_OBJECT_INFO_H 18 | #define _MTP_OBJECT_INFO_H 19 | 20 | #include "MtpTypes.h" 21 | 22 | namespace android { 23 | 24 | class MtpDataPacket; 25 | 26 | class MtpObjectInfo { 27 | public: 28 | MtpObjectHandle mHandle; 29 | MtpStorageID mStorageID; 30 | MtpObjectFormat mFormat; 31 | uint16_t mProtectionStatus; 32 | uint32_t mCompressedSize; 33 | MtpObjectFormat mThumbFormat; 34 | uint32_t mThumbCompressedSize; 35 | uint32_t mThumbPixWidth; 36 | uint32_t mThumbPixHeight; 37 | uint32_t mImagePixWidth; 38 | uint32_t mImagePixHeight; 39 | uint32_t mImagePixDepth; 40 | MtpObjectHandle mParent; 41 | uint16_t mAssociationType; 42 | uint32_t mAssociationDesc; 43 | uint32_t mSequenceNumber; 44 | char* mName; 45 | time_t mDateCreated; 46 | time_t mDateModified; 47 | char* mKeywords; 48 | 49 | public: 50 | MtpObjectInfo(MtpObjectHandle handle); 51 | virtual ~MtpObjectInfo(); 52 | 53 | void read(MtpDataPacket& packet); 54 | 55 | void print(); 56 | }; 57 | 58 | }; // namespace android 59 | 60 | #endif // _MTP_OBJECT_INFO_H 61 | -------------------------------------------------------------------------------- /include/USBSerialInterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __USB_SERIAL_INTERFACE_H 18 | #define __USB_SERIAL_INTERFACE_H 19 | 20 | #include "usb.h" 21 | 22 | class USBSerialInterface { 23 | private: 24 | 25 | int interface_index; 26 | 27 | struct usb_interface_descriptor serial_interface_descriptor = { 28 | .bLength = USB_DT_INTERFACE_SIZE, 29 | .bDescriptorType = USB_DT_INTERFACE, 30 | .bNumEndpoints = 2, 31 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 32 | .bInterfaceSubClass = USB_CLASS_VENDOR_SPEC, 33 | .bInterfaceProtocol = USB_CLASS_VENDOR_SPEC, 34 | }; 35 | 36 | struct usb_endpoint_descriptor serial_endpoint_descriptor_in = { 37 | .bLength = USB_DT_ENDPOINT_SIZE, 38 | .bDescriptorType = USB_DT_ENDPOINT, 39 | .bEndpointAddress = USB_ENDPOINT_IN, 40 | .bmAttributes = USB_TRANSFER_TYPE_BULK, 41 | .wMaxPacketSize = 0x200, 42 | }; 43 | 44 | struct usb_endpoint_descriptor serial_endpoint_descriptor_out = { 45 | .bLength = USB_DT_ENDPOINT_SIZE, 46 | .bDescriptorType = USB_DT_ENDPOINT, 47 | .bEndpointAddress = USB_ENDPOINT_OUT, 48 | .bmAttributes = USB_TRANSFER_TYPE_BULK, 49 | .wMaxPacketSize = 0x200, 50 | }; 51 | 52 | public: 53 | 54 | USBSerialInterface(int index, UsbInterfaceDesc *info); 55 | virtual ~USBSerialInterface(); 56 | 57 | ssize_t read(char *ptr, size_t len); 58 | ssize_t write(const char *ptr, size_t len); 59 | }; 60 | 61 | #endif /* __USB_SERIAL_INTERFACE_H */ 62 | -------------------------------------------------------------------------------- /include/MtpStorage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_STORAGE_H 18 | #define _MTP_STORAGE_H 19 | 20 | #include "MtpTypes.h" 21 | #include "mtp.h" 22 | 23 | namespace android { 24 | 25 | class MtpDatabase; 26 | 27 | class MtpStorage { 28 | 29 | private: 30 | MtpStorageID mStorageID; 31 | MtpString mFilePath; 32 | MtpString mDescription; 33 | uint64_t mMaxCapacity; 34 | uint64_t mMaxFileSize; 35 | // amount of free space to leave unallocated 36 | uint64_t mReserveSpace; 37 | bool mRemovable; 38 | 39 | public: 40 | MtpStorage(MtpStorageID id, const char* filePath, 41 | const char* description, uint64_t reserveSpace, 42 | bool removable, uint64_t maxFileSize); 43 | virtual ~MtpStorage(); 44 | 45 | inline MtpStorageID getStorageID() const { return mStorageID; } 46 | int getType() const; 47 | int getFileSystemType() const; 48 | int getAccessCapability() const; 49 | uint64_t getMaxCapacity(); 50 | uint64_t getFreeSpace(); 51 | const char* getDescription() const; 52 | inline const char* getPath() const { return mFilePath.c_str(); } 53 | inline bool isRemovable() const { return mRemovable; } 54 | inline uint64_t getMaxFileSize() const { return mMaxFileSize; } 55 | }; 56 | 57 | }; // namespace android 58 | 59 | #endif // _MTP_STORAGE_H 60 | -------------------------------------------------------------------------------- /include/MtpPacket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_PACKET_H 18 | #define _MTP_PACKET_H 19 | 20 | #include "MtpTypes.h" 21 | #include "USBMtpInterface.h" 22 | 23 | namespace android { 24 | 25 | class MtpPacket { 26 | 27 | protected: 28 | uint8_t* mBuffer; 29 | // current size of the buffer 30 | int mBufferSize; 31 | // number of bytes to add when resizing the buffer 32 | int mAllocationIncrement; 33 | // size of the data in the packet 34 | int mPacketSize; 35 | 36 | public: 37 | MtpPacket(int bufferSize); 38 | virtual ~MtpPacket(); 39 | 40 | // sets packet size to the default container size and sets buffer to zero 41 | virtual void reset(); 42 | 43 | void allocate(int length); 44 | void dump(); 45 | void copyFrom(const MtpPacket& src); 46 | 47 | uint16_t getContainerCode() const; 48 | void setContainerCode(uint16_t code); 49 | 50 | uint16_t getContainerType() const; 51 | 52 | MtpTransactionID getTransactionID() const; 53 | void setTransactionID(MtpTransactionID id); 54 | 55 | uint32_t getParameter(int index) const; 56 | void setParameter(int index, uint32_t value); 57 | 58 | protected: 59 | uint16_t getUInt16(int offset) const; 60 | uint32_t getUInt32(int offset) const; 61 | void putUInt16(int offset, uint16_t value); 62 | void putUInt32(int offset, uint32_t value); 63 | }; 64 | 65 | }; // namespace android 66 | 67 | #endif // _MTP_PACKET_H 68 | -------------------------------------------------------------------------------- /include/USBMtpInterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __USB_MTP_INTERFACE_H 18 | #define __USB_MTP_INTERFACE_H 19 | 20 | #include "usb.h" 21 | 22 | class USBMtpInterface { 23 | private: 24 | 25 | int interface_index; 26 | 27 | struct usb_interface_descriptor mtp_interface_descriptor = { 28 | .bLength = USB_DT_INTERFACE_SIZE, 29 | .bDescriptorType = USB_DT_INTERFACE, 30 | .bNumEndpoints = 3, 31 | .bInterfaceClass = 6, 32 | .bInterfaceSubClass = 1, 33 | .bInterfaceProtocol = 1, 34 | }; 35 | struct usb_endpoint_descriptor mtp_endpoint_descriptor_in = { 36 | .bLength = USB_DT_ENDPOINT_SIZE, 37 | .bDescriptorType = USB_DT_ENDPOINT, 38 | .bEndpointAddress = USB_ENDPOINT_IN, 39 | .bmAttributes = USB_TRANSFER_TYPE_BULK, 40 | .wMaxPacketSize = 0x200, 41 | }; 42 | struct usb_endpoint_descriptor mtp_endpoint_descriptor_out = { 43 | .bLength = USB_DT_ENDPOINT_SIZE, 44 | .bDescriptorType = USB_DT_ENDPOINT, 45 | .bEndpointAddress = USB_ENDPOINT_OUT, 46 | .bmAttributes = USB_TRANSFER_TYPE_BULK, 47 | .wMaxPacketSize = 0x200, 48 | }; 49 | struct usb_endpoint_descriptor mtp_endpoint_descriptor_interrupt = { 50 | .bLength = USB_DT_ENDPOINT_SIZE, 51 | .bDescriptorType = USB_DT_ENDPOINT, 52 | .bEndpointAddress = USB_ENDPOINT_IN, 53 | .bmAttributes = USB_TRANSFER_TYPE_INTERRUPT, 54 | .wMaxPacketSize = 0x1c, 55 | .bInterval = 6, 56 | }; 57 | 58 | const char * mtp_string_descriptor = "MTP"; 59 | 60 | public: 61 | 62 | USBMtpInterface(int index, UsbInterfaceDesc *info); 63 | virtual ~USBMtpInterface(); 64 | 65 | ssize_t read(char *ptr, size_t len); 66 | ssize_t write(const char *ptr, size_t len); 67 | ssize_t sendEvent(const char *ptr, size_t len); 68 | }; 69 | 70 | #endif /* __USB_MTP_INTERFACE_H */ 71 | -------------------------------------------------------------------------------- /source/MtpStorage.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpStorage" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "MtpDebug.h" 29 | #include "MtpDatabase.h" 30 | #include "MtpStorage.h" 31 | #include "log.h" 32 | 33 | namespace android { 34 | 35 | MtpStorage::MtpStorage(MtpStorageID id, const char* filePath, 36 | const char* description, uint64_t reserveSpace, 37 | bool removable, uint64_t maxFileSize) 38 | : mStorageID(id), 39 | mFilePath(filePath), 40 | mDescription(description), 41 | mMaxCapacity(0), 42 | mMaxFileSize(maxFileSize), 43 | mReserveSpace(reserveSpace), 44 | mRemovable(removable) 45 | { 46 | VLOG(2) << "MtpStorage id: " << id << " path: " << filePath; 47 | } 48 | 49 | MtpStorage::~MtpStorage() { 50 | } 51 | 52 | int MtpStorage::getType() const { 53 | return (mRemovable ? MTP_STORAGE_REMOVABLE_RAM : MTP_STORAGE_FIXED_RAM); 54 | } 55 | 56 | int MtpStorage::getFileSystemType() const { 57 | return MTP_STORAGE_FILESYSTEM_HIERARCHICAL; 58 | } 59 | 60 | int MtpStorage::getAccessCapability() const { 61 | return MTP_STORAGE_READ_WRITE; 62 | } 63 | 64 | uint64_t MtpStorage::getMaxCapacity() { 65 | if (mMaxCapacity == 0) { 66 | struct statvfs stat; 67 | if (statvfs(getPath(), &stat)) 68 | return -1; 69 | mMaxCapacity = (uint64_t)stat.f_blocks * (uint64_t)stat.f_bsize; 70 | } 71 | return mMaxCapacity; 72 | } 73 | 74 | uint64_t MtpStorage::getFreeSpace() { 75 | struct statvfs stat; 76 | if (statvfs(getPath(), &stat)) 77 | return -1; 78 | uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize; 79 | return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0); 80 | } 81 | 82 | const char* MtpStorage::getDescription() const { 83 | return mDescription.c_str(); 84 | } 85 | 86 | } // namespace android 87 | -------------------------------------------------------------------------------- /source/MtpStorageInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpStorageInfo" 18 | 19 | #include 20 | #include 21 | 22 | #include "MtpDebug.h" 23 | #include "MtpDataPacket.h" 24 | #include "MtpStorageInfo.h" 25 | #include "MtpStringBuffer.h" 26 | 27 | #include "log.h" 28 | 29 | namespace android { 30 | 31 | MtpStorageInfo::MtpStorageInfo(MtpStorageID id) 32 | : mStorageID(id), 33 | mStorageType(0), 34 | mFileSystemType(0), 35 | mAccessCapability(0), 36 | mMaxCapacity(0), 37 | mFreeSpaceBytes(0), 38 | mFreeSpaceObjects(0), 39 | mStorageDescription(NULL), 40 | mVolumeIdentifier(NULL) 41 | { 42 | } 43 | 44 | MtpStorageInfo::~MtpStorageInfo() { 45 | if (mStorageDescription) 46 | free(mStorageDescription); 47 | if (mVolumeIdentifier) 48 | free(mVolumeIdentifier); 49 | } 50 | 51 | void MtpStorageInfo::read(MtpDataPacket& packet) { 52 | MtpStringBuffer string; 53 | 54 | // read the device info 55 | mStorageType = packet.getUInt16(); 56 | mFileSystemType = packet.getUInt16(); 57 | mAccessCapability = packet.getUInt16(); 58 | mMaxCapacity = packet.getUInt64(); 59 | mFreeSpaceBytes = packet.getUInt64(); 60 | mFreeSpaceObjects = packet.getUInt32(); 61 | 62 | packet.getString(string); 63 | mStorageDescription = strdup((const char *)string); 64 | packet.getString(string); 65 | mVolumeIdentifier = strdup((const char *)string); 66 | } 67 | 68 | void MtpStorageInfo::print() { 69 | VLOG(2) << "Storage Info " << std::hex << mStorageID << std::dec << ":" 70 | << "\n\tmStorageType: " << mStorageType 71 | << "\n\tmFileSystemType: " << mFileSystemType 72 | << "\n\tmAccessCapability: " << mAccessCapability; 73 | VLOG(2) << "\tmMaxCapacity: " << mMaxCapacity 74 | << "\n\tmFreeSpaceBytes: " << mFreeSpaceBytes 75 | << "\n\tmFreeSpaceObjects: " << mFreeSpaceObjects; 76 | VLOG(2) << "\tmStorageDescription: " << mStorageDescription 77 | << "\n\tmVolumeIdentifier: " << mVolumeIdentifier; 78 | } 79 | 80 | } // namespace android 81 | -------------------------------------------------------------------------------- /source/MtpUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpUtils" 18 | 19 | #include 20 | #include 21 | 22 | // #include 23 | #include "MtpUtils.h" 24 | 25 | namespace android { 26 | 27 | /* 28 | DateTime strings follow a compatible subset of the definition found in ISO 8601, and 29 | take the form of a Unicode string formatted as: "YYYYMMDDThhmmss.s". In this 30 | representation, YYYY shall be replaced by the year, MM replaced by the month (01-12), 31 | DD replaced by the day (01-31), T is a constant character 'T' delimiting time from date, 32 | hh is replaced by the hour (00-23), mm is replaced by the minute (00-59), and ss by the 33 | second (00-59). The ".s" is optional, and represents tenths of a second. 34 | */ 35 | 36 | bool parseDateTime(const char* dateTime, time_t& outSeconds) { 37 | int year, month, day, hour, minute, second; 38 | struct tm tm; 39 | 40 | if (sscanf(dateTime, "%04d%02d%02dT%02d%02d%02d", 41 | &year, &month, &day, &hour, &minute, &second) != 6) 42 | return false; 43 | const char* tail = dateTime + 15; 44 | // skip optional tenth of second 45 | if (tail[0] == '.' && tail[1]) 46 | tail += 2; 47 | //FIXME - support +/-hhmm 48 | bool useUTC = (tail[0] == 'Z'); 49 | 50 | // hack to compute timezone 51 | time_t dummy; 52 | tzset(); 53 | localtime_r(&dummy, &tm); 54 | 55 | tm.tm_sec = second; 56 | tm.tm_min = minute; 57 | tm.tm_hour = hour; 58 | tm.tm_mday = day; 59 | tm.tm_mon = month - 1; // mktime uses months in 0 - 11 range 60 | tm.tm_year = year - 1900; 61 | tm.tm_wday = 0; 62 | tm.tm_isdst = -1; 63 | outSeconds = mktime(&tm); 64 | /*if (useUTC) 65 | outSeconds = mktime(&tm); 66 | else 67 | outSeconds = mktime_tz(&tm, tm.tm_zone);*/ 68 | 69 | return true; 70 | } 71 | 72 | void formatDateTime(time_t seconds, char* buffer, int bufferLength) { 73 | struct tm tm; 74 | 75 | localtime_r(&seconds, &tm); 76 | snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d", 77 | tm.tm_year + 1900, 78 | tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range 79 | tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); 80 | } 81 | 82 | } // namespace android 83 | -------------------------------------------------------------------------------- /include/MtpTypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_TYPES_H 18 | #define _MTP_TYPES_H 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace android { 29 | 30 | typedef int32_t int128_t[4]; 31 | typedef uint32_t uint128_t[4]; 32 | 33 | typedef uint16_t MtpOperationCode; 34 | typedef uint16_t MtpResponseCode; 35 | typedef uint16_t MtpEventCode; 36 | typedef uint32_t MtpSessionID; 37 | typedef uint32_t MtpStorageID; 38 | typedef uint32_t MtpTransactionID; 39 | typedef uint16_t MtpPropertyCode; 40 | typedef uint16_t MtpDataType; 41 | typedef uint16_t MtpObjectFormat; 42 | typedef MtpPropertyCode MtpDeviceProperty; 43 | typedef MtpPropertyCode MtpObjectProperty; 44 | 45 | // object handles are unique across all storage but only within a single session. 46 | // object handles cannot be reused after an object is deleted. 47 | // values 0x00000000 and 0xFFFFFFFF are reserved for special purposes. 48 | typedef uint32_t MtpObjectHandle; 49 | 50 | // Special values 51 | #define MTP_PARENT_ROOT 0xFFFFFFFF // parent is root of the storage 52 | #define kInvalidObjectHandle 0xFFFFFFFF 53 | 54 | class MtpStorage; 55 | class MtpDevice; 56 | class MtpProperty; 57 | 58 | template 59 | using Vector = std::vector; 60 | 61 | typedef std::vector MtpStorageList; 62 | typedef std::vector MtpDeviceList; 63 | typedef std::vector MtpPropertyList; 64 | 65 | typedef std::vector UInt8List; 66 | typedef std::vector UInt16List; 67 | typedef std::vector UInt32List; 68 | typedef std::vector UInt64List; 69 | typedef std::vector Int8List; 70 | typedef std::vector Int16List; 71 | typedef std::vector Int32List; 72 | typedef std::vector Int64List; 73 | 74 | typedef UInt16List MtpObjectPropertyList; 75 | typedef UInt16List MtpDevicePropertyList; 76 | typedef UInt16List MtpObjectFormatList; 77 | typedef UInt32List MtpObjectHandleList; 78 | typedef UInt16List MtpObjectPropertyList; 79 | typedef UInt32List MtpStorageIDList; 80 | 81 | typedef std::string MtpString; 82 | 83 | typedef std::mutex MtpMutex; 84 | typedef std::lock_guard MtpAutolock; 85 | 86 | }; // namespace android 87 | 88 | #endif // _MTP_TYPES_H 89 | -------------------------------------------------------------------------------- /source/MtpDeviceInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpDeviceInfo" 18 | 19 | #include 20 | 21 | #include "MtpDebug.h" 22 | #include "MtpDataPacket.h" 23 | #include "MtpDeviceInfo.h" 24 | #include "MtpStringBuffer.h" 25 | 26 | #include "log.h" 27 | 28 | namespace android { 29 | 30 | MtpDeviceInfo::MtpDeviceInfo() 31 | : mStandardVersion(0), 32 | mVendorExtensionID(0), 33 | mVendorExtensionVersion(0), 34 | mVendorExtensionDesc(NULL), 35 | mFunctionalCode(0), 36 | mOperations(NULL), 37 | mEvents(NULL), 38 | mDeviceProperties(NULL), 39 | mCaptureFormats(NULL), 40 | mPlaybackFormats(NULL), 41 | mManufacturer(NULL), 42 | mModel(NULL), 43 | mVersion(NULL), 44 | mSerial(NULL) 45 | { 46 | } 47 | 48 | MtpDeviceInfo::~MtpDeviceInfo() { 49 | if (mVendorExtensionDesc) 50 | free(mVendorExtensionDesc); 51 | delete mOperations; 52 | delete mEvents; 53 | delete mDeviceProperties; 54 | delete mCaptureFormats; 55 | delete mPlaybackFormats; 56 | if (mManufacturer) 57 | free(mManufacturer); 58 | if (mModel) 59 | free(mModel); 60 | if (mVersion) 61 | free(mVersion); 62 | if (mSerial) 63 | free(mSerial); 64 | } 65 | 66 | void MtpDeviceInfo::read(MtpDataPacket& packet) { 67 | MtpStringBuffer string; 68 | 69 | // read the device info 70 | mStandardVersion = packet.getUInt16(); 71 | mVendorExtensionID = packet.getUInt32(); 72 | mVendorExtensionVersion = packet.getUInt16(); 73 | 74 | packet.getString(string); 75 | mVendorExtensionDesc = strdup((const char *)string); 76 | 77 | mFunctionalCode = packet.getUInt16(); 78 | mOperations = packet.getAUInt16(); 79 | mEvents = packet.getAUInt16(); 80 | mDeviceProperties = packet.getAUInt16(); 81 | mCaptureFormats = packet.getAUInt16(); 82 | mPlaybackFormats = packet.getAUInt16(); 83 | 84 | packet.getString(string); 85 | mManufacturer = strdup((const char *)string); 86 | packet.getString(string); 87 | mModel = strdup((const char *)string); 88 | packet.getString(string); 89 | mVersion = strdup((const char *)string); 90 | packet.getString(string); 91 | mSerial = strdup((const char *)string); 92 | } 93 | 94 | void MtpDeviceInfo::print() { 95 | VLOG(2) << "Device Info:" 96 | << "\n\tmStandardVersion: " << mStandardVersion 97 | << "\n\tmVendorExtensionID: " << mVendorExtensionID 98 | << "\n\tmVendorExtensionVersion: " << mVendorExtensionVersion 99 | << "\n\tmVendorExtensionDesc: " << mVendorExtensionDesc 100 | << "\n\tmFunctionalCode: " << mFunctionalCode 101 | << "\n\tmManufacturer: " << mManufacturer 102 | << "\n\tmModel: " << mModel 103 | << "\n\tmVersion: " << mVersion 104 | << "\n\tmSerial: " << mSerial; 105 | } 106 | 107 | } // namespace android 108 | -------------------------------------------------------------------------------- /include/MtpProperty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_PROPERTY_H 18 | #define _MTP_PROPERTY_H 19 | 20 | #include "MtpTypes.h" 21 | 22 | namespace android { 23 | 24 | class MtpDataPacket; 25 | 26 | struct MtpPropertyValue { 27 | union { 28 | int8_t i8; 29 | uint8_t u8; 30 | int16_t i16; 31 | uint16_t u16; 32 | int32_t i32; 33 | uint32_t u32; 34 | int64_t i64; 35 | uint64_t u64; 36 | int128_t i128; 37 | uint128_t u128; 38 | } u; 39 | // string in UTF8 format 40 | char* str; 41 | }; 42 | 43 | class MtpProperty { 44 | public: 45 | MtpPropertyCode mCode; 46 | MtpDataType mType; 47 | bool mWriteable; 48 | MtpPropertyValue mDefaultValue; 49 | MtpPropertyValue mCurrentValue; 50 | 51 | // for array types 52 | int mDefaultArrayLength; 53 | MtpPropertyValue* mDefaultArrayValues; 54 | int mCurrentArrayLength; 55 | MtpPropertyValue* mCurrentArrayValues; 56 | 57 | enum { 58 | kFormNone = 0, 59 | kFormRange = 1, 60 | kFormEnum = 2, 61 | kFormDateTime = 3, 62 | }; 63 | 64 | uint32_t mGroupCode; 65 | uint8_t mFormFlag; 66 | 67 | // for range form 68 | MtpPropertyValue mMinimumValue; 69 | MtpPropertyValue mMaximumValue; 70 | MtpPropertyValue mStepSize; 71 | 72 | // for enum form 73 | int mEnumLength; 74 | MtpPropertyValue* mEnumValues; 75 | 76 | public: 77 | MtpProperty(); 78 | MtpProperty(MtpPropertyCode propCode, 79 | MtpDataType type, 80 | bool writeable = false, 81 | int defaultValue = 0); 82 | virtual ~MtpProperty(); 83 | 84 | inline MtpPropertyCode getPropertyCode() const { return mCode; } 85 | 86 | void read(MtpDataPacket& packet); 87 | void write(MtpDataPacket& packet); 88 | 89 | void setDefaultValue(const uint16_t* string); 90 | void setCurrentValue(const uint16_t* string); 91 | 92 | void setFormRange(int min, int max, int step); 93 | void setFormEnum(const int* values, int count); 94 | void setFormDateTime(); 95 | 96 | void print(); 97 | void print(MtpPropertyValue& value, MtpString& buffer); 98 | 99 | inline bool isDeviceProperty() const { 100 | return ( ((mCode & 0xF000) == 0x5000) 101 | || ((mCode & 0xF800) == 0xD000)); 102 | } 103 | 104 | private: 105 | void readValue(MtpDataPacket& packet, MtpPropertyValue& value); 106 | void writeValue(MtpDataPacket& packet, MtpPropertyValue& value); 107 | MtpPropertyValue* readArrayValues(MtpDataPacket& packet, int& length); 108 | void writeArrayValues(MtpDataPacket& packet, 109 | MtpPropertyValue* values, int length); 110 | }; 111 | 112 | }; // namespace android 113 | 114 | #endif // _MTP_PROPERTY_H 115 | -------------------------------------------------------------------------------- /source/MtpObjectInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpObjectInfo" 18 | 19 | #include 20 | #include 21 | 22 | #include "MtpDebug.h" 23 | #include "MtpDataPacket.h" 24 | #include "MtpObjectInfo.h" 25 | #include "MtpStringBuffer.h" 26 | #include "MtpUtils.h" 27 | 28 | #include "log.h" 29 | 30 | namespace android { 31 | 32 | MtpObjectInfo::MtpObjectInfo(MtpObjectHandle handle) 33 | : mHandle(handle), 34 | mStorageID(0), 35 | mFormat(0), 36 | mProtectionStatus(0), 37 | mCompressedSize(0), 38 | mThumbFormat(0), 39 | mThumbCompressedSize(0), 40 | mThumbPixWidth(0), 41 | mThumbPixHeight(0), 42 | mImagePixWidth(0), 43 | mImagePixHeight(0), 44 | mImagePixDepth(0), 45 | mParent(0), 46 | mAssociationType(0), 47 | mAssociationDesc(0), 48 | mSequenceNumber(0), 49 | mName(NULL), 50 | mDateCreated(0), 51 | mDateModified(0), 52 | mKeywords(NULL) 53 | { 54 | } 55 | 56 | MtpObjectInfo::~MtpObjectInfo() { 57 | if (mName) 58 | free(mName); 59 | if (mKeywords) 60 | free(mKeywords); 61 | } 62 | 63 | void MtpObjectInfo::read(MtpDataPacket& packet) { 64 | MtpStringBuffer string; 65 | time_t time; 66 | 67 | mStorageID = packet.getUInt32(); 68 | mFormat = packet.getUInt16(); 69 | mProtectionStatus = packet.getUInt16(); 70 | mCompressedSize = packet.getUInt32(); 71 | mThumbFormat = packet.getUInt16(); 72 | mThumbCompressedSize = packet.getUInt32(); 73 | mThumbPixWidth = packet.getUInt32(); 74 | mThumbPixHeight = packet.getUInt32(); 75 | mImagePixWidth = packet.getUInt32(); 76 | mImagePixHeight = packet.getUInt32(); 77 | mImagePixDepth = packet.getUInt32(); 78 | mParent = packet.getUInt32(); 79 | mAssociationType = packet.getUInt16(); 80 | mAssociationDesc = packet.getUInt32(); 81 | mSequenceNumber = packet.getUInt32(); 82 | 83 | packet.getString(string); 84 | mName = strdup((const char *)string); 85 | 86 | packet.getString(string); 87 | if (parseDateTime((const char*)string, time)) 88 | mDateCreated = time; 89 | 90 | packet.getString(string); 91 | if (parseDateTime((const char*)string, time)) 92 | mDateModified = time; 93 | 94 | packet.getString(string); 95 | mKeywords = strdup((const char *)string); 96 | } 97 | 98 | void MtpObjectInfo::print() { 99 | VLOG(2) << "MtpObject Info " << mHandle << ": " << mName; 100 | VLOG(2) << " mStorageID: " << std::hex << mStorageID 101 | << " mFormat: " << mFormat << std::dec 102 | << " mProtectionStatus: " << mProtectionStatus; 103 | VLOG(2) << " mCompressedSize: " << mCompressedSize 104 | << " mThumbFormat: " << std::hex << mThumbFormat << std::dec 105 | << " mThumbCompressedSize: " << mThumbCompressedSize; 106 | VLOG(2) << " mThumbPixWidth: " << mThumbPixWidth 107 | << " mThumbPixHeight: " << mThumbPixHeight; 108 | VLOG(2) << " mImagePixWidth: " << mImagePixWidth 109 | << " mImagePixHeight: " << mImagePixHeight 110 | << " mImagePixDepth: " << mImagePixDepth; 111 | VLOG(2) << " mParent: " << std::hex << mParent 112 | << " mAssociationType: " << mAssociationType << std::dec 113 | << " mAssociationDesc: " << mAssociationDesc; 114 | VLOG(2) << " mSequenceNumber: " << mSequenceNumber 115 | << " mDateCreated: " << mDateCreated 116 | << " mDateModified: " << mDateModified 117 | << " mKeywords: " << mKeywords; 118 | } 119 | 120 | } // namespace android 121 | -------------------------------------------------------------------------------- /include/MtpDataPacket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_DATA_PACKET_H 18 | #define _MTP_DATA_PACKET_H 19 | 20 | #include "MtpPacket.h" 21 | #include "mtp.h" 22 | 23 | namespace android { 24 | 25 | class MtpStringBuffer; 26 | 27 | class MtpDataPacket : public MtpPacket { 28 | private: 29 | // current offset for get/put methods 30 | int mOffset; 31 | 32 | public: 33 | MtpDataPacket(); 34 | virtual ~MtpDataPacket(); 35 | 36 | virtual void reset(); 37 | 38 | void setOperationCode(MtpOperationCode code); 39 | void setTransactionID(MtpTransactionID id); 40 | 41 | inline const uint8_t* getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; } 42 | inline uint8_t getUInt8() { return (uint8_t)mBuffer[mOffset++]; } 43 | inline int8_t getInt8() { return (int8_t)mBuffer[mOffset++]; } 44 | uint16_t getUInt16(); 45 | inline int16_t getInt16() { return (int16_t)getUInt16(); } 46 | uint32_t getUInt32(); 47 | inline int32_t getInt32() { return (int32_t)getUInt32(); } 48 | uint64_t getUInt64(); 49 | inline int64_t getInt64() { return (int64_t)getUInt64(); } 50 | void getUInt128(uint128_t& value); 51 | inline void getInt128(int128_t& value) { getUInt128((uint128_t&)value); } 52 | void getString(MtpStringBuffer& string); 53 | 54 | Int8List* getAInt8(); 55 | UInt8List* getAUInt8(); 56 | Int16List* getAInt16(); 57 | UInt16List* getAUInt16(); 58 | Int32List* getAInt32(); 59 | UInt32List* getAUInt32(); 60 | Int64List* getAInt64(); 61 | UInt64List* getAUInt64(); 62 | 63 | void putInt8(int8_t value); 64 | void putUInt8(uint8_t value); 65 | void putInt16(int16_t value); 66 | void putUInt16(uint16_t value); 67 | void putInt32(int32_t value); 68 | void putUInt32(uint32_t value); 69 | void putInt64(int64_t value); 70 | void putUInt64(uint64_t value); 71 | void putInt128(const int128_t& value); 72 | void putUInt128(const uint128_t& value); 73 | void putInt128(int64_t value); 74 | void putUInt128(uint64_t value); 75 | 76 | void putAInt8(const int8_t* values, int count); 77 | void putAUInt8(const uint8_t* values, int count); 78 | void putAInt16(const int16_t* values, int count); 79 | void putAUInt16(const uint16_t* values, int count); 80 | void putAUInt16(const UInt16List* values); 81 | void putAInt32(const int32_t* values, int count); 82 | void putAUInt32(const uint32_t* values, int count); 83 | void putAUInt32(const UInt32List* list); 84 | void putAInt64(const int64_t* values, int count); 85 | void putAUInt64(const uint64_t* values, int count); 86 | void putString(const MtpStringBuffer& string); 87 | void putString(const char* string); 88 | void putString(const uint16_t* string); 89 | inline void putEmptyString() { putUInt8(0); } 90 | inline void putEmptyArray() { putUInt32(0); } 91 | 92 | // fill our buffer with data from the given file descriptor 93 | int read(USBMtpInterface* usb); 94 | int read(USBMtpInterface* usb, uint32_t length); 95 | 96 | // write our data to the given file descriptor 97 | int write(USBMtpInterface* usb); 98 | int writeData(USBMtpInterface* usb, void* data, uint32_t length); 99 | 100 | inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; } 101 | inline uint32_t getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); } 102 | void* getData(int& outLength) const; 103 | }; 104 | 105 | }; // namespace android 106 | 107 | #endif // _MTP_DATA_PACKET_H 108 | -------------------------------------------------------------------------------- /source/MtpPacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpPacket" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "MtpDebug.h" 24 | #include "MtpPacket.h" 25 | #include "mtp.h" 26 | 27 | #include "log.h" 28 | 29 | namespace android { 30 | 31 | MtpPacket::MtpPacket(int bufferSize) 32 | : mBuffer(NULL), 33 | mBufferSize(bufferSize), 34 | mAllocationIncrement(bufferSize), 35 | mPacketSize(0) 36 | { 37 | mBuffer = (uint8_t *)malloc(bufferSize); 38 | if (!mBuffer) { 39 | LOG(FATAL) << "out of memory!"; 40 | } 41 | } 42 | 43 | MtpPacket::~MtpPacket() { 44 | if (mBuffer) 45 | free(mBuffer); 46 | } 47 | 48 | void MtpPacket::reset() { 49 | allocate(MTP_CONTAINER_HEADER_SIZE); 50 | mPacketSize = MTP_CONTAINER_HEADER_SIZE; 51 | memset(mBuffer, 0, mBufferSize); 52 | } 53 | 54 | void MtpPacket::allocate(int length) { 55 | if (length > mBufferSize) { 56 | int newLength = length + mAllocationIncrement; 57 | mBuffer = (uint8_t *)realloc(mBuffer, newLength); 58 | if (!mBuffer) { 59 | LOG(FATAL) << "out of memory!"; 60 | } 61 | mBufferSize = newLength; 62 | } 63 | } 64 | 65 | void MtpPacket::dump() { 66 | #define DUMP_BYTES_PER_ROW 16 67 | char buffer[500]; 68 | char* bufptr = buffer; 69 | 70 | for (int i = 0; i < mPacketSize; i++) { 71 | sprintf(bufptr, "%02X ", mBuffer[i]); 72 | bufptr += strlen(bufptr); 73 | if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) { 74 | VLOG(3) << buffer; 75 | bufptr = buffer; 76 | } 77 | } 78 | if (bufptr != buffer) { 79 | // print last line 80 | VLOG(3) << buffer; 81 | } 82 | } 83 | 84 | void MtpPacket::copyFrom(const MtpPacket& src) { 85 | int length = src.mPacketSize; 86 | allocate(length); 87 | mPacketSize = length; 88 | memcpy(mBuffer, src.mBuffer, length); 89 | } 90 | 91 | uint16_t MtpPacket::getUInt16(int offset) const { 92 | return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; 93 | } 94 | 95 | uint32_t MtpPacket::getUInt32(int offset) const { 96 | return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | 97 | ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; 98 | } 99 | 100 | void MtpPacket::putUInt16(int offset, uint16_t value) { 101 | mBuffer[offset++] = (uint8_t)(value & 0xFF); 102 | mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); 103 | } 104 | 105 | void MtpPacket::putUInt32(int offset, uint32_t value) { 106 | mBuffer[offset++] = (uint8_t)(value & 0xFF); 107 | mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); 108 | mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); 109 | mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); 110 | } 111 | 112 | uint16_t MtpPacket::getContainerCode() const { 113 | return getUInt16(MTP_CONTAINER_CODE_OFFSET); 114 | } 115 | 116 | void MtpPacket::setContainerCode(uint16_t code) { 117 | putUInt16(MTP_CONTAINER_CODE_OFFSET, code); 118 | } 119 | 120 | uint16_t MtpPacket::getContainerType() const { 121 | return getUInt16(MTP_CONTAINER_TYPE_OFFSET); 122 | } 123 | 124 | MtpTransactionID MtpPacket::getTransactionID() const { 125 | return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET); 126 | } 127 | 128 | void MtpPacket::setTransactionID(MtpTransactionID id) { 129 | putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id); 130 | } 131 | 132 | uint32_t MtpPacket::getParameter(int index) const { 133 | if (index < 1 || index > 5) { 134 | LOG(ERROR) << "index " << index << " out of range in MtpPacket::getParameter"; 135 | return 0; 136 | } 137 | return getUInt32(MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t)); 138 | } 139 | 140 | void MtpPacket::setParameter(int index, uint32_t value) { 141 | if (index < 1 || index > 5) { 142 | LOG(ERROR) << "index " << index << " out of range in MtpPacket::setParameter"; 143 | return; 144 | } 145 | int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t); 146 | if (mPacketSize < offset + sizeof(uint32_t)) 147 | mPacketSize = offset + sizeof(uint32_t); 148 | putUInt32(offset, value); 149 | } 150 | 151 | } // namespace android 152 | -------------------------------------------------------------------------------- /source/MtpStringBuffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpStringBuffer" 18 | 19 | #include 20 | 21 | #include "MtpDataPacket.h" 22 | #include "MtpStringBuffer.h" 23 | 24 | namespace android { 25 | 26 | MtpStringBuffer::MtpStringBuffer() 27 | : mCharCount(0), 28 | mByteCount(1) 29 | { 30 | mBuffer[0] = 0; 31 | } 32 | 33 | MtpStringBuffer::MtpStringBuffer(const char* src) 34 | : mCharCount(0), 35 | mByteCount(1) 36 | { 37 | set(src); 38 | } 39 | 40 | MtpStringBuffer::MtpStringBuffer(const uint16_t* src) 41 | : mCharCount(0), 42 | mByteCount(1) 43 | { 44 | set(src); 45 | } 46 | 47 | MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src) 48 | : mCharCount(src.mCharCount), 49 | mByteCount(src.mByteCount) 50 | { 51 | memcpy(mBuffer, src.mBuffer, mByteCount); 52 | } 53 | 54 | 55 | MtpStringBuffer::~MtpStringBuffer() { 56 | } 57 | 58 | void MtpStringBuffer::set(const char* src) { 59 | int length = strlen(src); 60 | if (length >= sizeof(mBuffer)) 61 | length = sizeof(mBuffer) - 1; 62 | memcpy(mBuffer, src, length); 63 | 64 | // count the characters 65 | int count = 0; 66 | char ch; 67 | while ((ch = *src++) != 0) { 68 | if ((ch & 0x80) == 0) { 69 | // single byte character 70 | } else if ((ch & 0xE0) == 0xC0) { 71 | // two byte character 72 | if (! *src++) { 73 | // last character was truncated, so ignore last byte 74 | length--; 75 | break; 76 | } 77 | } else if ((ch & 0xF0) == 0xE0) { 78 | // 3 byte char 79 | if (! *src++) { 80 | // last character was truncated, so ignore last byte 81 | length--; 82 | break; 83 | } 84 | if (! *src++) { 85 | // last character was truncated, so ignore last two bytes 86 | length -= 2; 87 | break; 88 | } 89 | } 90 | count++; 91 | } 92 | 93 | mByteCount = length + 1; 94 | mBuffer[length] = 0; 95 | mCharCount = count; 96 | } 97 | 98 | void MtpStringBuffer::set(const uint16_t* src) { 99 | int count = 0; 100 | uint16_t ch; 101 | uint8_t* dest = mBuffer; 102 | 103 | while ((ch = *src++) != 0 && count < 255) { 104 | if (ch >= 0x0800) { 105 | *dest++ = (uint8_t)(0xE0 | (ch >> 12)); 106 | *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); 107 | *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 108 | } else if (ch >= 0x80) { 109 | *dest++ = (uint8_t)(0xC0 | (ch >> 6)); 110 | *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 111 | } else { 112 | *dest++ = ch; 113 | } 114 | count++; 115 | } 116 | *dest++ = 0; 117 | mCharCount = count; 118 | mByteCount = dest - mBuffer; 119 | } 120 | 121 | void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) { 122 | int count = packet->getUInt8(); 123 | uint8_t* dest = mBuffer; 124 | for (int i = 0; i < count; i++) { 125 | uint16_t ch = packet->getUInt16(); 126 | if (ch >= 0x0800) { 127 | *dest++ = (uint8_t)(0xE0 | (ch >> 12)); 128 | *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); 129 | *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 130 | } else if (ch >= 0x80) { 131 | *dest++ = (uint8_t)(0xC0 | (ch >> 6)); 132 | *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 133 | } else { 134 | *dest++ = ch; 135 | } 136 | } 137 | *dest++ = 0; 138 | mCharCount = count; 139 | mByteCount = dest - mBuffer; 140 | } 141 | 142 | void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const { 143 | int count = mCharCount; 144 | const uint8_t* src = mBuffer; 145 | packet->putUInt8(count > 0 ? count + 1 : 0); 146 | 147 | // expand utf8 to 16 bit chars 148 | for (int i = 0; i < count; i++) { 149 | uint16_t ch; 150 | uint16_t ch1 = *src++; 151 | if ((ch1 & 0x80) == 0) { 152 | // single byte character 153 | ch = ch1; 154 | } else if ((ch1 & 0xE0) == 0xC0) { 155 | // two byte character 156 | uint16_t ch2 = *src++; 157 | ch = ((ch1 & 0x1F) << 6) | (ch2 & 0x3F); 158 | } else { 159 | // three byte character 160 | uint16_t ch2 = *src++; 161 | uint16_t ch3 = *src++; 162 | ch = ((ch1 & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F); 163 | } 164 | packet->putUInt16(ch); 165 | } 166 | // only terminate with zero if string is not empty 167 | if (count > 0) 168 | packet->putUInt16(0); 169 | } 170 | 171 | } // namespace android 172 | -------------------------------------------------------------------------------- /source/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * Copyright (C) 2019 Gillou68310 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "SwitchMtpDatabase.h" 25 | #include "MtpServer.h" 26 | #include "MtpStorage.h" 27 | 28 | #include "log.h" 29 | 30 | using namespace android; 31 | 32 | #ifdef WANT_SYSMODULE 33 | extern "C" 34 | { 35 | #define INNER_HEAP_SIZE 0x80000 36 | extern u32 __start__; 37 | 38 | size_t nx_inner_heap_size = INNER_HEAP_SIZE; 39 | char nx_inner_heap[INNER_HEAP_SIZE]; 40 | 41 | void __libnx_initheap(void); 42 | void __appInit(void); 43 | void __appExit(void); 44 | } 45 | 46 | u32 __nx_applet_type = AppletType_None; 47 | 48 | void __libnx_initheap(void) 49 | { 50 | void *addr = nx_inner_heap; 51 | size_t size = nx_inner_heap_size; 52 | 53 | extern char *fake_heap_start; 54 | extern char *fake_heap_end; 55 | 56 | fake_heap_start = (char *)addr; 57 | fake_heap_end = (char *)addr + size; 58 | } 59 | 60 | void __appInit(void) 61 | { 62 | smInitialize(); 63 | Result rc = setsysInitialize(); 64 | if (R_SUCCEEDED(rc)) { 65 | SetSysFirmwareVersion fw; 66 | rc = setsysGetFirmwareVersion(&fw); 67 | if (R_SUCCEEDED(rc)) 68 | hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro)); 69 | setsysExit(); 70 | } 71 | fsInitialize(); 72 | hidInitialize(); 73 | fsdevMountSdmc(); 74 | } 75 | 76 | MtpServer* serverExit = NULL; 77 | 78 | void __appExit(void) 79 | { 80 | serverExit->stop(); 81 | usbExit(); 82 | hidExit(); 83 | fsExit(); 84 | smExit(); 85 | } 86 | #endif // WANT_SYSMODULE 87 | 88 | static void stop_thread(MtpServer* server) 89 | { 90 | #ifdef WANT_APPLET 91 | padConfigureInput(8, HidNpadStyleSet_NpadStandard); 92 | 93 | PadState pad; 94 | padInitializeAny(&pad); 95 | 96 | while (appletMainLoop()) 97 | { 98 | padUpdate(&pad); 99 | u64 kDown = padGetButtonsDown(&pad); 100 | 101 | if (kDown & HidNpadButton_B) 102 | { 103 | server->stop(); 104 | break; 105 | } 106 | } 107 | #endif // WANT_APPLET 108 | 109 | #ifdef WANT_SYSMODULE 110 | serverExit = server; 111 | #endif // WANT_SYSMODULE 112 | } 113 | 114 | int main(int argc, char* argv[]) 115 | { 116 | int c; 117 | struct option long_options[] = 118 | { 119 | {"nxlink", no_argument, &nxlink, 1}, 120 | {"verbose", required_argument, 0, 'v'}, 121 | {0, 0, 0, 0} 122 | }; 123 | 124 | while(1) 125 | { 126 | int option_index = 0; 127 | c = getopt_long (argc, argv, "v:", long_options, &option_index); 128 | if (c == -1) 129 | break; 130 | 131 | switch (c) 132 | { 133 | case 'v': 134 | verbose_level = atoi(optarg); 135 | break; 136 | default: 137 | break; 138 | } 139 | } 140 | 141 | #ifdef WANT_APPLET 142 | consoleInit(NULL); 143 | std::cout << "MTP Server is running." << std::endl; 144 | std::cout << "> Press B to exit."; 145 | #endif // WANT_APPLET 146 | 147 | struct usb_device_descriptor device_descriptor = { 148 | .bLength = USB_DT_DEVICE_SIZE, 149 | .bDescriptorType = USB_DT_DEVICE, 150 | .bcdUSB = 0x0110, 151 | .bDeviceClass = 0x00, 152 | .bDeviceSubClass = 0x00, 153 | .bDeviceProtocol = 0x00, 154 | .bMaxPacketSize0 = 0x40, 155 | .idVendor = 0x057e, 156 | .idProduct = 0x4000, 157 | .bcdDevice = 0x0100, 158 | .bNumConfigurations = 0x01 159 | }; 160 | 161 | UsbInterfaceDesc infos[2]; 162 | int num_interface = 0; 163 | USBMtpInterface *mtp_interface = NULL; 164 | USBSerialInterface *serial_interface = NULL; 165 | 166 | mtp_interface = new USBMtpInterface(num_interface, &infos[num_interface]); 167 | num_interface++; 168 | 169 | if(nxlink) 170 | { 171 | serial_interface = new USBSerialInterface(num_interface, &infos[num_interface]); 172 | num_interface++; 173 | } 174 | 175 | usbInitialize(&device_descriptor, num_interface, infos); 176 | nxlinkStdioInitialise(serial_interface); 177 | 178 | MtpStorage* storage = new MtpStorage( 179 | MTP_STORAGE_REMOVABLE_RAM, 180 | "sdmc:/", 181 | "sdcard", 182 | 1024U * 1024U * 100U, /* 100 MB reserved space, to avoid filling the disk */ 183 | false, 184 | 1024U * 1024U * 1024U * 4U - 1 /* ~4GB arbitrary max file size */); 185 | 186 | MtpDatabase* mtp_database = new SwitchMtpDatabase(); 187 | 188 | mtp_database->addStoragePath("sdmc:/", 189 | "sdcard", 190 | MTP_STORAGE_REMOVABLE_RAM, true); 191 | 192 | MtpServer* server = new MtpServer( 193 | mtp_interface, 194 | mtp_database, 195 | false, 196 | 0, 197 | 0, 198 | 0); 199 | 200 | std::thread th(stop_thread, server); 201 | server->addStorage(storage); 202 | server->run(); 203 | th.join(); 204 | 205 | nxlinkStdioClose(serial_interface); 206 | consoleExit(NULL); 207 | usbExit(); 208 | return 0; 209 | } 210 | -------------------------------------------------------------------------------- /mtp-server-nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mtp-server-nx", 3 | "title_id": "0x00FF00006D7470FF", 4 | "title_id_range_min": "0x00FF00006D7470FF", 5 | "title_id_range_max": "0x00FF00006D7470FF", 6 | "main_thread_stack_size": "0x004000", 7 | "main_thread_priority": 44, 8 | "default_cpu_id": 3, 9 | "process_category": 0, 10 | "is_retail": true, 11 | "pool_partition": 2, 12 | "is_64_bit": true, 13 | "address_space_type": 1, 14 | "filesystem_access": { 15 | "permissions": "0xffffffffffffffff" 16 | }, 17 | "service_access": ["*"], 18 | "service_host": ["*"], 19 | "kernel_capabilities": [{ 20 | "type": "kernel_flags", 21 | "value": { 22 | "highest_thread_priority": 63, 23 | "lowest_thread_priority": 24, 24 | "lowest_cpu_id": 3, 25 | "highest_cpu_id": 3 26 | } 27 | }, { 28 | "type": "syscalls", 29 | "value": { 30 | "svcUnknown": "0x00", 31 | "svcSetHeapSize": "0x01", 32 | "svcSetMemoryPermission": "0x02", 33 | "svcSetMemoryAttribute": "0x03", 34 | "svcMapMemory": "0x04", 35 | "svcUnmapMemory": "0x05", 36 | "svcQueryMemory": "0x06", 37 | "svcExitProcess": "0x07", 38 | "svcCreateThread": "0x08", 39 | "svcStartThread": "0x09", 40 | "svcExitThread": "0x0a", 41 | "svcSleepThread": "0x0b", 42 | "svcGetThreadPriority": "0x0c", 43 | "svcSetThreadPriority": "0x0d", 44 | "svcGetThreadCoreMask": "0x0e", 45 | "svcSetThreadCoreMask": "0x0f", 46 | "svcGetCurrentProcessorNumber": "0x10", 47 | "svcSignalEvent": "0x11", 48 | "svcClearEvent": "0x12", 49 | "svcMapSharedMemory": "0x13", 50 | "svcUnmapSharedMemory": "0x14", 51 | "svcCreateTransferMemory": "0x15", 52 | "svcCloseHandle": "0x16", 53 | "svcResetSignal": "0x17", 54 | "svcWaitSynchronization": "0x18", 55 | "svcCancelSynchronization": "0x19", 56 | "svcArbitrateLock": "0x1a", 57 | "svcArbitrateUnlock": "0x1b", 58 | "svcWaitProcessWideKeyAtomic": "0x1c", 59 | "svcSignalProcessWideKey": "0x1d", 60 | "svcGetSystemTick": "0x1e", 61 | "svcConnectToNamedPort": "0x1f", 62 | "svcSendSyncRequestLight": "0x20", 63 | "svcSendSyncRequest": "0x21", 64 | "svcSendSyncRequestWithUserBuffer": "0x22", 65 | "svcSendAsyncRequestWithUserBuffer": "0x23", 66 | "svcGetProcessId": "0x24", 67 | "svcGetThreadId": "0x25", 68 | "svcBreak": "0x26", 69 | "svcOutputDebugString": "0x27", 70 | "svcReturnFromException": "0x28", 71 | "svcGetInfo": "0x29", 72 | "svcFlushEntireDataCache": "0x2a", 73 | "svcFlushDataCache": "0x2b", 74 | "svcMapPhysicalMemory": "0x2c", 75 | "svcUnmapPhysicalMemory": "0x2d", 76 | "svcGetFutureThreadInfo": "0x2e", 77 | "svcGetLastThreadInfo": "0x2f", 78 | "svcGetResourceLimitLimitValue": "0x30", 79 | "svcGetResourceLimitCurrentValue": "0x31", 80 | "svcSetThreadActivity": "0x32", 81 | "svcGetThreadContext3": "0x33", 82 | "svcWaitForAddress": "0x34", 83 | "svcSignalToAddress": "0x35", 84 | "svcUnknown": "0x36", 85 | "svcUnknown": "0x37", 86 | "svcUnknown": "0x38", 87 | "svcUnknown": "0x39", 88 | "svcUnknown": "0x3a", 89 | "svcUnknown": "0x3b", 90 | "svcDumpInfo": "0x3c", 91 | "svcDumpInfoNew": "0x3d", 92 | "svcUnknown": "0x3e", 93 | "svcUnknown": "0x3f", 94 | "svcCreateSession": "0x40", 95 | "svcAcceptSession": "0x41", 96 | "svcReplyAndReceiveLight": "0x42", 97 | "svcReplyAndReceive": "0x43", 98 | "svcReplyAndReceiveWithUserBuffer": "0x44", 99 | "svcCreateEvent": "0x45", 100 | "svcUnknown": "0x46", 101 | "svcUnknown": "0x47", 102 | "svcMapPhysicalMemoryUnsafe": "0x48", 103 | "svcUnmapPhysicalMemoryUnsafe": "0x49", 104 | "svcSetUnsafeLimit": "0x4a", 105 | "svcCreateCodeMemory": "0x4b", 106 | "svcControlCodeMemory": "0x4c", 107 | "svcSleepSystem": "0x4d", 108 | "svcReadWriteRegister": "0x4e", 109 | "svcSetProcessActivity": "0x4f", 110 | "svcCreateSharedMemory": "0x50", 111 | "svcMapTransferMemory": "0x51", 112 | "svcUnmapTransferMemory": "0x52", 113 | "svcCreateInterruptEvent": "0x53", 114 | "svcQueryPhysicalAddress": "0x54", 115 | "svcQueryIoMapping": "0x55", 116 | "svcCreateDeviceAddressSpace": "0x56", 117 | "svcAttachDeviceAddressSpace": "0x57", 118 | "svcDetachDeviceAddressSpace": "0x58", 119 | "svcMapDeviceAddressSpaceByForce": "0x59", 120 | "svcMapDeviceAddressSpaceAligned": "0x5a", 121 | "svcMapDeviceAddressSpace": "0x5b", 122 | "svcUnmapDeviceAddressSpace": "0x5c", 123 | "svcInvalidateProcessDataCache": "0x5d", 124 | "svcStoreProcessDataCache": "0x5e", 125 | "svcFlushProcessDataCache": "0x5f", 126 | "svcDebugActiveProcess": "0x60", 127 | "svcBreakDebugProcess": "0x61", 128 | "svcTerminateDebugProcess": "0x62", 129 | "svcGetDebugEvent": "0x63", 130 | "svcContinueDebugEvent": "0x64", 131 | "svcGetProcessList": "0x65", 132 | "svcGetThreadList": "0x66", 133 | "svcGetDebugThreadContext": "0x67", 134 | "svcSetDebugThreadContext": "0x68", 135 | "svcQueryDebugProcessMemory": "0x69", 136 | "svcReadDebugProcessMemory": "0x6a", 137 | "svcWriteDebugProcessMemory": "0x6b", 138 | "svcSetHardwareBreakPoint": "0x6c", 139 | "svcGetDebugThreadParam": "0x6d", 140 | "svcUnknown": "0x6e", 141 | "svcGetSystemInfo": "0x6f", 142 | "svcCreatePort": "0x70", 143 | "svcManageNamedPort": "0x71", 144 | "svcConnectToPort": "0x72", 145 | "svcSetProcessMemoryPermission": "0x73", 146 | "svcMapProcessMemory": "0x74", 147 | "svcUnmapProcessMemory": "0x75", 148 | "svcQueryProcessMemory": "0x76", 149 | "svcMapProcessCodeMemory": "0x77", 150 | "svcUnmapProcessCodeMemory": "0x78", 151 | "svcCreateProcess": "0x79", 152 | "svcStartProcess": "0x7a", 153 | "svcTerminateProcess": "0x7b", 154 | "svcGetProcessInfo": "0x7c", 155 | "svcCreateResourceLimit": "0x7d", 156 | "svcSetResourceLimitLimitValue": "0x7e", 157 | "svcCallSecureMonitor": "0x7f" 158 | } 159 | }, { 160 | "type": "min_kernel_version", 161 | "value": "0x0030" 162 | }, { 163 | "type": "handle_table_size", 164 | "value": 1023 165 | }, { 166 | "type": "debug_flags", 167 | "value": { 168 | "allow_debug": false, 169 | "force_debug": true 170 | } 171 | }] 172 | } 173 | -------------------------------------------------------------------------------- /include/MtpDatabase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_DATABASE_H 18 | #define _MTP_DATABASE_H 19 | 20 | #include "MtpTypes.h" 21 | #include "MtpServer.h" 22 | 23 | namespace android { 24 | 25 | class MtpDataPacket; 26 | class MtpProperty; 27 | class MtpObjectInfo; 28 | 29 | class MtpDatabase { 30 | public: 31 | virtual ~MtpDatabase() {} 32 | 33 | virtual bool isHandleValid(MtpObjectHandle handle) = 0; 34 | 35 | // called to add a path to include in the database. 36 | virtual void addStoragePath(const MtpString& path, 37 | const MtpString& displayName, 38 | MtpStorageID storage, 39 | bool hidden) = 0; 40 | 41 | // Called to remove database entries for a storage. 42 | virtual void removeStorage(MtpStorageID storage) = 0; 43 | 44 | // called from SendObjectInfo to reserve a database entry for the incoming file 45 | virtual MtpObjectHandle beginSendObject(const MtpString& path, 46 | MtpObjectFormat format, 47 | MtpObjectHandle parent, 48 | MtpStorageID storage, 49 | uint64_t size, 50 | time_t modified) = 0; 51 | 52 | // called to report success or failure of the SendObject file transfer 53 | // success should signal a notification of the new object's creation, 54 | // failure should remove the database entry created in beginSendObject 55 | virtual void endSendObject(const MtpString& path, 56 | MtpObjectHandle handle, 57 | MtpObjectFormat format, 58 | bool succeeded) = 0; 59 | 60 | virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID, 61 | MtpObjectFormat format, 62 | MtpObjectHandle parent) = 0; 63 | 64 | virtual int getNumObjects(MtpStorageID storageID, 65 | MtpObjectFormat format, 66 | MtpObjectHandle parent) = 0; 67 | 68 | // callee should delete[] the results from these 69 | // results can be NULL 70 | virtual MtpObjectFormatList* getSupportedPlaybackFormats() = 0; 71 | virtual MtpObjectFormatList* getSupportedCaptureFormats() = 0; 72 | virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format) = 0; 73 | virtual MtpDevicePropertyList* getSupportedDeviceProperties() = 0; 74 | 75 | virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle, 76 | MtpObjectProperty property, 77 | MtpDataPacket& packet) = 0; 78 | 79 | virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle, 80 | MtpObjectProperty property, 81 | MtpDataPacket& packet) = 0; 82 | 83 | virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property, 84 | MtpDataPacket& packet) = 0; 85 | 86 | virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property, 87 | MtpDataPacket& packet) = 0; 88 | 89 | virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property) = 0; 90 | 91 | virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle, 92 | uint32_t format, uint32_t property, 93 | int groupCode, int depth, 94 | MtpDataPacket& packet) = 0; 95 | 96 | virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle, 97 | MtpObjectInfo& info) = 0; 98 | 99 | virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) = 0; 100 | 101 | virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle, 102 | MtpString& outFilePath, 103 | int64_t& outFileLength, 104 | MtpObjectFormat& outFormat) = 0; 105 | 106 | virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0; 107 | 108 | virtual MtpResponseCode moveFile(MtpObjectHandle handle, 109 | MtpObjectHandle new_parent) = 0; 110 | 111 | virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle) = 0; 112 | 113 | virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle, 114 | MtpObjectHandleList* references) = 0; 115 | 116 | virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property, 117 | MtpObjectFormat format) = 0; 118 | 119 | virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property) = 0; 120 | 121 | virtual void sessionStarted(MtpServer* server) = 0; 122 | 123 | virtual void sessionEnded() = 0; 124 | }; 125 | 126 | }; // namespace android 127 | 128 | #endif // _MTP_DATABASE_H 129 | -------------------------------------------------------------------------------- /include/MtpServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_SERVER_H 18 | #define _MTP_SERVER_H 19 | 20 | #include "MtpRequestPacket.h" 21 | #include "MtpDataPacket.h" 22 | #include "MtpResponsePacket.h" 23 | #include "MtpEventPacket.h" 24 | #include "mtp.h" 25 | #include "MtpUtils.h" 26 | #include "USBMtpInterface.h" 27 | 28 | #include 29 | 30 | namespace android { 31 | 32 | class MtpDatabase; 33 | class MtpStorage; 34 | 35 | class MtpServer { 36 | 37 | private: 38 | // USB interface 39 | USBMtpInterface* mUSB; 40 | 41 | MtpDatabase* mDatabase; 42 | 43 | // keep state whether the server should be running 44 | bool mRunning; 45 | 46 | // appear as a PTP device 47 | bool mPtp; 48 | 49 | // group to own new files and folders 50 | int mFileGroup; 51 | // permissions for new files and directories 52 | int mFilePermission; 53 | int mDirectoryPermission; 54 | 55 | // current session ID 56 | MtpSessionID mSessionID; 57 | // true if we have an open session and mSessionID is valid 58 | bool mSessionOpen; 59 | 60 | MtpRequestPacket mRequest; 61 | MtpDataPacket mData; 62 | MtpResponsePacket mResponse; 63 | MtpEventPacket mEvent; 64 | 65 | MtpStorageList mStorages; 66 | 67 | // handle for new object, set by SendObjectInfo and used by SendObject 68 | MtpObjectHandle mSendObjectHandle; 69 | MtpObjectFormat mSendObjectFormat; 70 | MtpString mSendObjectFilePath; 71 | size_t mSendObjectFileSize; 72 | 73 | MtpMutex mMutex; 74 | 75 | // represents an MTP object that is being edited using the android extensions 76 | // for direct editing (BeginEditObject, SendPartialObject, TruncateObject and EndEditObject) 77 | class ObjectEdit { 78 | public: 79 | MtpObjectHandle mHandle; 80 | MtpString mPath; 81 | uint64_t mSize; 82 | MtpObjectFormat mFormat; 83 | int mFD; 84 | 85 | ObjectEdit(MtpObjectHandle handle, const MtpString& path, uint64_t size, 86 | MtpObjectFormat format, int fd) 87 | : mHandle(handle), mPath(path), mSize(size), mFormat(format), mFD(fd) { 88 | } 89 | 90 | virtual ~ObjectEdit() { 91 | close(mFD); 92 | } 93 | }; 94 | Vector mObjectEditList; 95 | 96 | public: 97 | MtpServer(USBMtpInterface* usb, MtpDatabase* database, bool ptp, 98 | int fileGroup, int filePerm, int directoryPerm); 99 | virtual ~MtpServer(); 100 | 101 | MtpStorage* getStorage(MtpStorageID id); 102 | inline bool hasStorage() { return mStorages.size() > 0; } 103 | bool hasStorage(MtpStorageID id); 104 | void addStorage(MtpStorage* storage); 105 | void removeStorage(MtpStorage* storage); 106 | 107 | void run(); 108 | void stop(); 109 | 110 | void sendObjectAdded(MtpObjectHandle handle); 111 | void sendObjectRemoved(MtpObjectHandle handle); 112 | void sendObjectInfoChanged(MtpObjectHandle handle); 113 | void sendObjectPropChanged(MtpObjectHandle handle, 114 | MtpObjectProperty prop); 115 | 116 | private: 117 | void sendStoreAdded(MtpStorageID id); 118 | void sendStoreRemoved(MtpStorageID id); 119 | void sendEvent(MtpEventCode code, 120 | uint32_t param1, 121 | uint32_t param2, 122 | uint32_t param3); 123 | 124 | void addEditObject(MtpObjectHandle handle, MtpString& path, 125 | uint64_t size, MtpObjectFormat format, int fd); 126 | ObjectEdit* getEditObject(MtpObjectHandle handle); 127 | void removeEditObject(MtpObjectHandle handle); 128 | void commitEdit(ObjectEdit* edit); 129 | 130 | bool handleRequest(); 131 | 132 | MtpResponseCode doGetDeviceInfo(); 133 | MtpResponseCode doOpenSession(); 134 | MtpResponseCode doCloseSession(); 135 | MtpResponseCode doGetStorageIDs(); 136 | MtpResponseCode doGetStorageInfo(); 137 | MtpResponseCode doGetObjectPropsSupported(); 138 | MtpResponseCode doGetObjectHandles(); 139 | MtpResponseCode doGetNumObjects(); 140 | MtpResponseCode doGetObjectReferences(); 141 | MtpResponseCode doSetObjectReferences(); 142 | MtpResponseCode doGetObjectPropValue(); 143 | MtpResponseCode doSetObjectPropValue(); 144 | MtpResponseCode doGetDevicePropValue(); 145 | MtpResponseCode doSetDevicePropValue(); 146 | MtpResponseCode doResetDevicePropValue(); 147 | MtpResponseCode doGetObjectPropList(); 148 | MtpResponseCode doGetObjectInfo(); 149 | MtpResponseCode doGetObject(); 150 | MtpResponseCode doGetThumb(); 151 | MtpResponseCode doGetPartialObject(MtpOperationCode operation); 152 | MtpResponseCode doSendObjectInfo(); 153 | MtpResponseCode doSendObject(); 154 | MtpResponseCode doDeleteObject(); 155 | MtpResponseCode doMoveObject(); 156 | MtpResponseCode doGetObjectPropDesc(); 157 | MtpResponseCode doGetDevicePropDesc(); 158 | MtpResponseCode doSendPartialObject(); 159 | MtpResponseCode doTruncateObject(); 160 | MtpResponseCode doBeginEditObject(); 161 | MtpResponseCode doEndEditObject(); 162 | }; 163 | 164 | }; // namespace android 165 | 166 | #endif // _MTP_SERVER_H 167 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITPRO)),) 6 | $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") 7 | endif 8 | 9 | TOPDIR ?= $(CURDIR) 10 | include $(DEVKITPRO)/libnx/switch_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # DATA is a list of directories containing data files 17 | # INCLUDES is a list of directories containing header files 18 | # ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) 19 | # 20 | # NO_ICON: if set to anything, do not use icon. 21 | # NO_NACP: if set to anything, no .nacp file is generated. 22 | # APP_TITLE is the name of the app stored in the .nacp file (Optional) 23 | # APP_AUTHOR is the author of the app stored in the .nacp file (Optional) 24 | # APP_VERSION is the version of the app stored in the .nacp file (Optional) 25 | # APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) 26 | # ICON is the filename of the icon (.jpg), relative to the project folder. 27 | # If not set, it attempts to use one of the following (in this order): 28 | # - .jpg 29 | # - icon.jpg 30 | # - /default_icon.jpg 31 | # 32 | # CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. 33 | # If not set, it attempts to use one of the following (in this order): 34 | # - .json 35 | # - config.json 36 | # If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead 37 | # of a homebrew executable (.nro). This is intended to be used for sysmodules. 38 | # NACP building is skipped as well. 39 | #--------------------------------------------------------------------------------- 40 | TARGET := $(notdir $(CURDIR)) 41 | BUILD := build 42 | SOURCES := source 43 | DATA := data 44 | INCLUDES := include 45 | #ROMFS := romfs 46 | APP_TITLEID := 00FF00006D7470FF 47 | 48 | # Meta 49 | APP_TITLE := "mtp-server-nx" 50 | APP_AUTHOR := "Gillou68310" 51 | APP_VERSION := "1.3" 52 | 53 | #--------------------------------------------------------------------------------- 54 | # options for code generation 55 | #--------------------------------------------------------------------------------- 56 | ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE 57 | 58 | CFLAGS := -g -Wall -O2 -ffunction-sections \ 59 | $(ARCH) $(DEFINES) 60 | 61 | CFLAGS += $(INCLUDE) -D__SWITCH__ -DWANT_APPLET 62 | 63 | CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++17 64 | 65 | ASFLAGS := -g $(ARCH) 66 | LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 67 | 68 | LIBS := -lnx -lstdc++fs 69 | 70 | #--------------------------------------------------------------------------------- 71 | # list of directories containing libraries, this must be the top level containing 72 | # include and lib 73 | #--------------------------------------------------------------------------------- 74 | LIBDIRS := $(PORTLIBS) $(LIBNX) 75 | 76 | #--------------------------------------------------------------------------------- 77 | # no real need to edit anything past this point unless you need to add additional 78 | # rules for different file extensions 79 | #--------------------------------------------------------------------------------- 80 | ifneq ($(BUILD),$(notdir $(CURDIR))) 81 | #--------------------------------------------------------------------------------- 82 | 83 | export OUTPUT := $(CURDIR)/$(TARGET) 84 | export TOPDIR := $(CURDIR) 85 | 86 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 87 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 88 | 89 | export DEPSDIR := $(CURDIR)/$(BUILD) 90 | 91 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 92 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 93 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 94 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 95 | 96 | #--------------------------------------------------------------------------------- 97 | # use CXX for linking C++ projects, CC for standard C 98 | #--------------------------------------------------------------------------------- 99 | ifeq ($(strip $(CPPFILES)),) 100 | #--------------------------------------------------------------------------------- 101 | export LD := $(CC) 102 | #--------------------------------------------------------------------------------- 103 | else 104 | #--------------------------------------------------------------------------------- 105 | export LD := $(CXX) 106 | #--------------------------------------------------------------------------------- 107 | endif 108 | #--------------------------------------------------------------------------------- 109 | 110 | export OFILES_BIN := $(addsuffix .o,$(BINFILES)) 111 | export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 112 | export OFILES := $(OFILES_BIN) $(OFILES_SRC) 113 | export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) 114 | 115 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 116 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 117 | -I$(CURDIR)/$(BUILD) 118 | 119 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 120 | 121 | ifeq ($(strip $(CONFIG_JSON)),) 122 | jsons := $(wildcard *.json) 123 | ifneq (,$(findstring $(TARGET).json,$(jsons))) 124 | export APP_JSON := $(TOPDIR)/$(TARGET).json 125 | else 126 | ifneq (,$(findstring config.json,$(jsons))) 127 | export APP_JSON := $(TOPDIR)/config.json 128 | endif 129 | endif 130 | else 131 | export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) 132 | endif 133 | 134 | ifeq ($(strip $(ICON)),) 135 | icons := $(wildcard *.jpg) 136 | ifneq (,$(findstring $(TARGET).jpg,$(icons))) 137 | export APP_ICON := $(TOPDIR)/$(TARGET).jpg 138 | else 139 | ifneq (,$(findstring icon.jpg,$(icons))) 140 | export APP_ICON := $(TOPDIR)/icon.jpg 141 | endif 142 | endif 143 | else 144 | export APP_ICON := $(TOPDIR)/$(ICON) 145 | endif 146 | 147 | ifeq ($(strip $(NO_ICON)),) 148 | export NROFLAGS += --icon=$(APP_ICON) 149 | endif 150 | 151 | ifeq ($(strip $(NO_NACP)),) 152 | export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp 153 | endif 154 | 155 | ifneq ($(APP_TITLEID),) 156 | export NACPFLAGS += --titleid=$(APP_TITLEID) 157 | endif 158 | 159 | ifneq ($(ROMFS),) 160 | export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) 161 | endif 162 | 163 | .PHONY: $(BUILD) clean all 164 | 165 | #--------------------------------------------------------------------------------- 166 | all: $(BUILD) 167 | 168 | $(BUILD): 169 | @[ -d $@ ] || mkdir -p $@ 170 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 171 | 172 | #--------------------------------------------------------------------------------- 173 | clean: 174 | @echo clean ... 175 | ifeq ($(strip $(APP_JSON)),) 176 | @rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf 177 | else 178 | @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf 179 | endif 180 | 181 | 182 | #--------------------------------------------------------------------------------- 183 | else 184 | .PHONY: all 185 | 186 | DEPENDS := $(OFILES:.o=.d) 187 | 188 | #--------------------------------------------------------------------------------- 189 | # main targets 190 | #--------------------------------------------------------------------------------- 191 | all : applet 192 | applet : $(OUTPUT).nro 193 | sysmodule : $(OUTPUT).nsp 194 | 195 | ifeq ($(strip $(NO_NACP)),) 196 | $(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp 197 | else 198 | $(OUTPUT).nro : $(OUTPUT).elf 199 | endif 200 | 201 | $(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm 202 | $(OUTPUT).nso : $(OUTPUT).elf 203 | 204 | $(OUTPUT).elf : $(OFILES) 205 | $(OFILES_SRC) : $(HFILES_BIN) 206 | 207 | #--------------------------------------------------------------------------------- 208 | # you need a rule like this for each extension you use as binary data 209 | #--------------------------------------------------------------------------------- 210 | %.bin.o %_bin.h : %.bin 211 | #--------------------------------------------------------------------------------- 212 | @echo $(notdir $<) 213 | @$(bin2o) 214 | 215 | -include $(DEPENDS) 216 | 217 | #--------------------------------------------------------------------------------------- 218 | endif 219 | #--------------------------------------------------------------------------------------- 220 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /source/MtpDataPacket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "MtpDataPacket.h" 25 | #include "MtpStringBuffer.h" 26 | 27 | #include "log.h" 28 | 29 | #define MTP_BUFFER_SIZE 16384 30 | 31 | namespace android { 32 | 33 | MtpDataPacket::MtpDataPacket() 34 | : MtpPacket(MTP_BUFFER_SIZE), // MAX_USBFS_BUFFER_SIZE 35 | mOffset(MTP_CONTAINER_HEADER_SIZE) 36 | { 37 | } 38 | 39 | MtpDataPacket::~MtpDataPacket() { 40 | } 41 | 42 | void MtpDataPacket::reset() { 43 | MtpPacket::reset(); 44 | mOffset = MTP_CONTAINER_HEADER_SIZE; 45 | } 46 | 47 | void MtpDataPacket::setOperationCode(MtpOperationCode code) { 48 | MtpPacket::putUInt16(MTP_CONTAINER_CODE_OFFSET, code); 49 | } 50 | 51 | void MtpDataPacket::setTransactionID(MtpTransactionID id) { 52 | MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id); 53 | } 54 | 55 | uint16_t MtpDataPacket::getUInt16() { 56 | int offset = mOffset; 57 | uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8); 58 | mOffset += 2; 59 | return result; 60 | } 61 | 62 | uint32_t MtpDataPacket::getUInt32() { 63 | int offset = mOffset; 64 | uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) | 65 | ((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24); 66 | mOffset += 4; 67 | return result; 68 | } 69 | 70 | uint64_t MtpDataPacket::getUInt64() { 71 | int offset = mOffset; 72 | uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) | 73 | ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) | 74 | ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) | 75 | ((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56); 76 | mOffset += 8; 77 | return result; 78 | } 79 | 80 | void MtpDataPacket::getUInt128(uint128_t& value) { 81 | value[0] = getUInt32(); 82 | value[1] = getUInt32(); 83 | value[2] = getUInt32(); 84 | value[3] = getUInt32(); 85 | } 86 | 87 | void MtpDataPacket::getString(MtpStringBuffer& string) 88 | { 89 | string.readFromPacket(this); 90 | } 91 | 92 | Int8List* MtpDataPacket::getAInt8() { 93 | Int8List* result = new Int8List; 94 | int count = getUInt32(); 95 | for (int i = 0; i < count; i++) 96 | result->push_back(getInt8()); 97 | return result; 98 | } 99 | 100 | UInt8List* MtpDataPacket::getAUInt8() { 101 | UInt8List* result = new UInt8List; 102 | int count = getUInt32(); 103 | for (int i = 0; i < count; i++) 104 | result->push_back(getUInt8()); 105 | return result; 106 | } 107 | 108 | Int16List* MtpDataPacket::getAInt16() { 109 | Int16List* result = new Int16List; 110 | int count = getUInt32(); 111 | for (int i = 0; i < count; i++) 112 | result->push_back(getInt16()); 113 | return result; 114 | } 115 | 116 | UInt16List* MtpDataPacket::getAUInt16() { 117 | UInt16List* result = new UInt16List; 118 | int count = getUInt32(); 119 | for (int i = 0; i < count; i++) 120 | result->push_back(getUInt16()); 121 | return result; 122 | } 123 | 124 | Int32List* MtpDataPacket::getAInt32() { 125 | Int32List* result = new Int32List; 126 | int count = getUInt32(); 127 | for (int i = 0; i < count; i++) 128 | result->push_back(getInt32()); 129 | return result; 130 | } 131 | 132 | UInt32List* MtpDataPacket::getAUInt32() { 133 | UInt32List* result = new UInt32List; 134 | int count = getUInt32(); 135 | for (int i = 0; i < count; i++) 136 | result->push_back(getUInt32()); 137 | return result; 138 | } 139 | 140 | Int64List* MtpDataPacket::getAInt64() { 141 | Int64List* result = new Int64List; 142 | int count = getUInt32(); 143 | for (int i = 0; i < count; i++) 144 | result->push_back(getInt64()); 145 | return result; 146 | } 147 | 148 | UInt64List* MtpDataPacket::getAUInt64() { 149 | UInt64List* result = new UInt64List; 150 | int count = getUInt32(); 151 | for (int i = 0; i < count; i++) 152 | result->push_back(getUInt64()); 153 | return result; 154 | } 155 | 156 | void MtpDataPacket::putInt8(int8_t value) { 157 | allocate(mOffset + 1); 158 | mBuffer[mOffset++] = (uint8_t)value; 159 | if (mPacketSize < mOffset) 160 | mPacketSize = mOffset; 161 | } 162 | 163 | void MtpDataPacket::putUInt8(uint8_t value) { 164 | allocate(mOffset + 1); 165 | mBuffer[mOffset++] = (uint8_t)value; 166 | if (mPacketSize < mOffset) 167 | mPacketSize = mOffset; 168 | } 169 | 170 | void MtpDataPacket::putInt16(int16_t value) { 171 | allocate(mOffset + 2); 172 | mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 173 | mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 174 | if (mPacketSize < mOffset) 175 | mPacketSize = mOffset; 176 | } 177 | 178 | void MtpDataPacket::putUInt16(uint16_t value) { 179 | allocate(mOffset + 2); 180 | mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 181 | mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 182 | if (mPacketSize < mOffset) 183 | mPacketSize = mOffset; 184 | } 185 | 186 | void MtpDataPacket::putInt32(int32_t value) { 187 | allocate(mOffset + 4); 188 | mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 189 | mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 190 | mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 191 | mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 192 | if (mPacketSize < mOffset) 193 | mPacketSize = mOffset; 194 | } 195 | 196 | void MtpDataPacket::putUInt32(uint32_t value) { 197 | allocate(mOffset + 4); 198 | mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 199 | mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 200 | mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 201 | mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 202 | if (mPacketSize < mOffset) 203 | mPacketSize = mOffset; 204 | } 205 | 206 | void MtpDataPacket::putInt64(int64_t value) { 207 | allocate(mOffset + 8); 208 | mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 209 | mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 210 | mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 211 | mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 212 | mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF); 213 | mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF); 214 | mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF); 215 | mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF); 216 | if (mPacketSize < mOffset) 217 | mPacketSize = mOffset; 218 | } 219 | 220 | void MtpDataPacket::putUInt64(uint64_t value) { 221 | allocate(mOffset + 8); 222 | mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 223 | mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 224 | mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 225 | mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 226 | mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF); 227 | mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF); 228 | mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF); 229 | mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF); 230 | if (mPacketSize < mOffset) 231 | mPacketSize = mOffset; 232 | } 233 | 234 | void MtpDataPacket::putInt128(const int128_t& value) { 235 | putInt32(value[0]); 236 | putInt32(value[1]); 237 | putInt32(value[2]); 238 | putInt32(value[3]); 239 | } 240 | 241 | void MtpDataPacket::putUInt128(const uint128_t& value) { 242 | putUInt32(value[0]); 243 | putUInt32(value[1]); 244 | putUInt32(value[2]); 245 | putUInt32(value[3]); 246 | } 247 | 248 | void MtpDataPacket::putInt128(int64_t value) { 249 | putInt64(value); 250 | putInt64(value < 0 ? -1 : 0); 251 | } 252 | 253 | void MtpDataPacket::putUInt128(uint64_t value) { 254 | putUInt64(value); 255 | putUInt64(0); 256 | } 257 | 258 | void MtpDataPacket::putAInt8(const int8_t* values, int count) { 259 | putUInt32(count); 260 | for (int i = 0; i < count; i++) 261 | putInt8(*values++); 262 | } 263 | 264 | void MtpDataPacket::putAUInt8(const uint8_t* values, int count) { 265 | putUInt32(count); 266 | for (int i = 0; i < count; i++) 267 | putUInt8(*values++); 268 | } 269 | 270 | void MtpDataPacket::putAInt16(const int16_t* values, int count) { 271 | putUInt32(count); 272 | for (int i = 0; i < count; i++) 273 | putInt16(*values++); 274 | } 275 | 276 | void MtpDataPacket::putAUInt16(const uint16_t* values, int count) { 277 | putUInt32(count); 278 | for (int i = 0; i < count; i++) 279 | putUInt16(*values++); 280 | } 281 | 282 | void MtpDataPacket::putAUInt16(const UInt16List* values) { 283 | size_t count = (values ? values->size() : 0); 284 | putUInt32(count); 285 | for (size_t i = 0; i < count; i++) 286 | putUInt16((*values)[i]); 287 | } 288 | 289 | void MtpDataPacket::putAInt32(const int32_t* values, int count) { 290 | putUInt32(count); 291 | for (int i = 0; i < count; i++) 292 | putInt32(*values++); 293 | } 294 | 295 | void MtpDataPacket::putAUInt32(const uint32_t* values, int count) { 296 | putUInt32(count); 297 | for (int i = 0; i < count; i++) 298 | putUInt32(*values++); 299 | } 300 | 301 | void MtpDataPacket::putAUInt32(const UInt32List* list) { 302 | if (!list) { 303 | putEmptyArray(); 304 | } else { 305 | size_t size = list->size(); 306 | putUInt32(size); 307 | for (size_t i = 0; i < size; i++) 308 | putUInt32((*list)[i]); 309 | } 310 | } 311 | 312 | void MtpDataPacket::putAInt64(const int64_t* values, int count) { 313 | putUInt32(count); 314 | for (int i = 0; i < count; i++) 315 | putInt64(*values++); 316 | } 317 | 318 | void MtpDataPacket::putAUInt64(const uint64_t* values, int count) { 319 | putUInt32(count); 320 | for (int i = 0; i < count; i++) 321 | putUInt64(*values++); 322 | } 323 | 324 | void MtpDataPacket::putString(const MtpStringBuffer& string) { 325 | string.writeToPacket(this); 326 | } 327 | 328 | void MtpDataPacket::putString(const char* s) { 329 | MtpStringBuffer string(s); 330 | string.writeToPacket(this); 331 | } 332 | 333 | void MtpDataPacket::putString(const uint16_t* string) { 334 | int count = 0; 335 | for (int i = 0; i < 256; i++) { 336 | if (string[i]) 337 | count++; 338 | else 339 | break; 340 | } 341 | putUInt8(count > 0 ? count + 1 : 0); 342 | for (int i = 0; i < count; i++) 343 | putUInt16(string[i]); 344 | // only terminate with zero if string is not empty 345 | if (count > 0) 346 | putUInt16(0); 347 | } 348 | 349 | int MtpDataPacket::read(USBMtpInterface* usb) { 350 | int ret = usb->read((char*)mBuffer, MTP_BUFFER_SIZE); 351 | if (ret < MTP_CONTAINER_HEADER_SIZE) 352 | return -1; 353 | mPacketSize = ret; 354 | mOffset = MTP_CONTAINER_HEADER_SIZE; 355 | return ret; 356 | } 357 | 358 | int MtpDataPacket::read(USBMtpInterface* usb, uint32_t length) { 359 | int ret = usb->read((char*)mBuffer, length); 360 | if (ret < MTP_CONTAINER_HEADER_SIZE) 361 | return -1; 362 | mPacketSize = ret; 363 | mOffset = MTP_CONTAINER_HEADER_SIZE; 364 | return ret; 365 | } 366 | 367 | int MtpDataPacket::write(USBMtpInterface* usb) { 368 | MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize); 369 | MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); 370 | int ret = usb->write((const char*)mBuffer, mPacketSize); 371 | return (ret < 0 ? ret : 0); 372 | } 373 | 374 | int MtpDataPacket::writeData(USBMtpInterface* usb, void* data, uint32_t length) { 375 | allocate(length); 376 | memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length); 377 | length += MTP_CONTAINER_HEADER_SIZE; 378 | MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length); 379 | MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); 380 | int ret = usb->write((const char*)mBuffer, length); 381 | return (ret < 0 ? ret : 0); 382 | } 383 | 384 | void* MtpDataPacket::getData(int& outLength) const { 385 | int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE; 386 | if (length > 0) { 387 | void* result = malloc(length); 388 | if (result) { 389 | memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length); 390 | outLength = length; 391 | return result; 392 | } 393 | } 394 | outLength = 0; 395 | return NULL; 396 | } 397 | 398 | } // namespace android 399 | -------------------------------------------------------------------------------- /source/usb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "usb.h" 21 | 22 | #define TOTAL_INTERFACES 4 23 | #define TOTAL_ENDPOINTS 4 24 | 25 | typedef struct { 26 | UsbDsEndpoint *endpoint; 27 | u8 *buffer; 28 | RwLock lock; 29 | } usbCommsEndpoint; 30 | 31 | typedef struct { 32 | RwLock lock; 33 | bool initialized; 34 | UsbDsInterface* interface; 35 | u32 endpoint_number; 36 | usbCommsEndpoint endpoint[TOTAL_ENDPOINTS]; 37 | } usbCommsInterface; 38 | 39 | static bool g_usbCommsInitialized = false; 40 | static usbCommsInterface g_usbCommsInterfaces[TOTAL_INTERFACES]; 41 | static bool g_usbCommsErrorHandling = 0; 42 | static RwLock g_usbCommsLock; 43 | static int ep_in = 1; 44 | static int ep_out = 1; 45 | 46 | static Result _usbCommsInterfaceInit5x(u32 intf_ind, const UsbInterfaceDesc *info); 47 | static Result _usbCommsInterfaceInit(u32 intf_ind, const UsbInterfaceDesc *info); 48 | 49 | Result usbInitialize(struct usb_device_descriptor *device_descriptor, u32 num_interfaces, const UsbInterfaceDesc *infos) 50 | { 51 | Result rc = 0; 52 | rwlockWriteLock(&g_usbCommsLock); 53 | 54 | if (g_usbCommsInitialized) { 55 | rc = MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); 56 | } else if (num_interfaces > TOTAL_INTERFACES) { 57 | rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); 58 | } else { 59 | rc = usbDsInitialize(); 60 | 61 | if (R_SUCCEEDED(rc)) { 62 | if (hosversionAtLeast(5,0,0)) { 63 | u8 iManufacturer, iProduct, iSerialNumber; 64 | static const u16 supported_langs[1] = {0x0409}; 65 | // Send language descriptor 66 | rc = usbDsAddUsbLanguageStringDescriptor(NULL, supported_langs, sizeof(supported_langs)/sizeof(u16)); 67 | // Send manufacturer 68 | if (R_SUCCEEDED(rc)) rc = usbDsAddUsbStringDescriptor(&iManufacturer, "Nintendo"); 69 | // Send product 70 | if (R_SUCCEEDED(rc)) rc = usbDsAddUsbStringDescriptor(&iProduct, "Nintendo Switch"); 71 | // Send serial number 72 | if (R_SUCCEEDED(rc)) rc = usbDsAddUsbStringDescriptor(&iSerialNumber, "SerialNumber"); 73 | 74 | // Send device descriptors 75 | device_descriptor->iManufacturer = iManufacturer; 76 | device_descriptor->iProduct = iProduct; 77 | device_descriptor->iSerialNumber = iSerialNumber; 78 | 79 | // Full Speed is USB 1.1 80 | if (R_SUCCEEDED(rc)) rc = usbDsSetUsbDeviceDescriptor(UsbDeviceSpeed_Full, device_descriptor); 81 | 82 | // High Speed is USB 2.0 83 | device_descriptor->bcdUSB = 0x0200; 84 | if (R_SUCCEEDED(rc)) rc = usbDsSetUsbDeviceDescriptor(UsbDeviceSpeed_High, device_descriptor); 85 | 86 | // Super Speed is USB 3.0 87 | device_descriptor->bcdUSB = 0x0300; 88 | // Upgrade packet size to 512 89 | device_descriptor->bMaxPacketSize0 = 0x09; 90 | if (R_SUCCEEDED(rc)) rc = usbDsSetUsbDeviceDescriptor(UsbDeviceSpeed_Super, device_descriptor); 91 | 92 | // Define Binary Object Store 93 | u8 bos[0x16] = { 94 | 0x05, // .bLength 95 | USB_DT_BOS, // .bDescriptorType 96 | 0x16, 0x00, // .wTotalLength 97 | 0x02, // .bNumDeviceCaps 98 | 99 | // USB 2.0 100 | 0x07, // .bLength 101 | USB_DT_DEVICE_CAPABILITY, // .bDescriptorType 102 | 0x02, // .bDevCapabilityType 103 | 0x02, 0x00, 0x00, 0x00, // dev_capability_data 104 | 105 | // USB 3.0 106 | 0x0A, // .bLength 107 | USB_DT_DEVICE_CAPABILITY, // .bDescriptorType 108 | 0x03, // .bDevCapabilityType 109 | 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00 110 | }; 111 | if (R_SUCCEEDED(rc)) rc = usbDsSetBinaryObjectStore(bos, sizeof(bos)); 112 | } 113 | 114 | if (R_SUCCEEDED(rc)) { 115 | for (u32 i = 0; i < num_interfaces; i++) { 116 | usbCommsInterface *intf = &g_usbCommsInterfaces[i]; 117 | const UsbInterfaceDesc *info = &infos[i]; 118 | intf->endpoint_number = info->interface_desc->bNumEndpoints; 119 | rwlockWriteLock(&intf->lock); 120 | for (u32 i = 0; i < intf->endpoint_number; i++) 121 | { 122 | rwlockWriteLock(&intf->endpoint[i].lock); 123 | } 124 | rc = _usbCommsInterfaceInit(i, info); 125 | for (u32 i = 0; i < intf->endpoint_number; i++) 126 | { 127 | rwlockWriteUnlock(&intf->endpoint[i].lock); 128 | } 129 | rwlockWriteUnlock(&intf->lock); 130 | if (R_FAILED(rc)) { 131 | break; 132 | } 133 | } 134 | } 135 | } 136 | 137 | if (R_SUCCEEDED(rc) && hosversionAtLeast(5,0,0)) { 138 | rc = usbDsEnable(); 139 | } 140 | 141 | if (R_FAILED(rc)) { 142 | usbExit(); 143 | } 144 | } 145 | 146 | if (R_SUCCEEDED(rc)) { 147 | g_usbCommsInitialized = true; 148 | g_usbCommsErrorHandling = false; 149 | } 150 | 151 | rwlockWriteUnlock(&g_usbCommsLock); 152 | return rc; 153 | } 154 | 155 | static void _usbCommsInterfaceFree(usbCommsInterface *interface) 156 | { 157 | rwlockWriteLock(&interface->lock); 158 | if (!interface->initialized) { 159 | rwlockWriteUnlock(&interface->lock); 160 | return; 161 | } 162 | 163 | interface->initialized = 0; 164 | interface->interface = NULL; 165 | 166 | for (u32 i = 0; i < interface->endpoint_number; i++) 167 | { 168 | rwlockWriteLock(&interface->endpoint[i].lock); 169 | interface->endpoint[i].endpoint = NULL; 170 | free(interface->endpoint[i].buffer); 171 | interface->endpoint[i].buffer = NULL; 172 | rwlockWriteUnlock(&interface->endpoint[i].lock); 173 | } 174 | 175 | rwlockWriteUnlock(&interface->lock); 176 | } 177 | 178 | void usbExit(void) 179 | { 180 | u32 i; 181 | 182 | rwlockWriteLock(&g_usbCommsLock); 183 | 184 | usbDsExit(); 185 | 186 | g_usbCommsInitialized = false; 187 | 188 | rwlockWriteUnlock(&g_usbCommsLock); 189 | 190 | for (i=0; istring_descriptor != NULL) 212 | { 213 | usbDsAddUsbStringDescriptor(&index, info->string_descriptor); 214 | } 215 | info->interface_desc->iInterface = index; 216 | 217 | struct usb_ss_endpoint_companion_descriptor endpoint_companion = { 218 | .bLength = sizeof(struct usb_ss_endpoint_companion_descriptor), 219 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMPANION, 220 | .bMaxBurst = 0x0F, 221 | .bmAttributes = 0x00, 222 | .wBytesPerInterval = 0x00, 223 | }; 224 | 225 | interface->initialized = 1; 226 | 227 | //The buffer for PostBufferAsync commands must be 0x1000-byte aligned. 228 | for (u32 i = 0; i < interface->endpoint_number; i++) 229 | { 230 | interface->endpoint[i].buffer = (u8*)memalign(0x1000, 0x1000); 231 | if (interface->endpoint[i].buffer == NULL) 232 | { 233 | rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); 234 | break; 235 | } 236 | memset(interface->endpoint[i].buffer, 0, 0x1000); 237 | } 238 | if (R_FAILED(rc)) return rc; 239 | 240 | rc = usbDsRegisterInterface(&interface->interface); 241 | if (R_FAILED(rc)) return rc; 242 | 243 | info->interface_desc->bInterfaceNumber = interface->interface->interface_index; 244 | for (u32 i = 0; i < interface->endpoint_number; i++) 245 | { 246 | if((info->endpoint_desc[i]->bEndpointAddress & USB_ENDPOINT_IN) != 0) 247 | { 248 | info->endpoint_desc[i]->bEndpointAddress |= ep_in; 249 | ep_in++; 250 | } 251 | else 252 | { 253 | info->endpoint_desc[i]->bEndpointAddress |= ep_out; 254 | ep_out++; 255 | } 256 | } 257 | 258 | // Full Speed Config 259 | rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_Full, info->interface_desc, USB_DT_INTERFACE_SIZE); 260 | if (R_FAILED(rc)) return rc; 261 | 262 | for (u32 i = 0; i < interface->endpoint_number; i++) 263 | { 264 | if(info->endpoint_desc[i]->bmAttributes == USB_TRANSFER_TYPE_BULK) 265 | info->endpoint_desc[i]->wMaxPacketSize = 0x40; 266 | rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_Full, info->endpoint_desc[i], USB_DT_ENDPOINT_SIZE); 267 | if (R_FAILED(rc)) return rc; 268 | } 269 | 270 | // High Speed Config 271 | rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_High, info->interface_desc, USB_DT_INTERFACE_SIZE); 272 | if (R_FAILED(rc)) return rc; 273 | 274 | for (u32 i = 0; i < interface->endpoint_number; i++) 275 | { 276 | if(info->endpoint_desc[i]->bmAttributes == USB_TRANSFER_TYPE_BULK) 277 | info->endpoint_desc[i]->wMaxPacketSize = 0x200; 278 | rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_High, info->endpoint_desc[i], USB_DT_ENDPOINT_SIZE); 279 | if (R_FAILED(rc)) return rc; 280 | } 281 | 282 | // Super Speed Config 283 | rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_Super, info->interface_desc, USB_DT_INTERFACE_SIZE); 284 | if (R_FAILED(rc)) return rc; 285 | 286 | for (u32 i = 0; i < interface->endpoint_number; i++) 287 | { 288 | if(info->endpoint_desc[i]->bmAttributes == USB_TRANSFER_TYPE_BULK) 289 | info->endpoint_desc[i]->wMaxPacketSize = 0x400; 290 | rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_Super, info->endpoint_desc[i], USB_DT_ENDPOINT_SIZE); 291 | if (R_FAILED(rc)) return rc; 292 | rc = usbDsInterface_AppendConfigurationData(interface->interface, UsbDeviceSpeed_Super, &endpoint_companion, USB_DT_SS_ENDPOINT_COMPANION_SIZE); 293 | if (R_FAILED(rc)) return rc; 294 | } 295 | 296 | //Setup endpoints. 297 | for (u32 i = 0; i < interface->endpoint_number; i++) 298 | { 299 | rc = usbDsInterface_RegisterEndpoint(interface->interface, &interface->endpoint[i].endpoint, info->endpoint_desc[i]->bEndpointAddress); 300 | if (R_FAILED(rc)) return rc; 301 | } 302 | 303 | rc = usbDsInterface_EnableInterface(interface->interface); 304 | if (R_FAILED(rc)) return rc; 305 | 306 | return rc; 307 | } 308 | 309 | static Result _usbCommsTransfer(usbCommsEndpoint *ep, UsbDirection dir, const void* buffer, size_t size, u64 timeout, size_t *transferredSize) 310 | { 311 | Result rc=0; 312 | u32 urbId=0; 313 | u32 chunksize=0; 314 | u8 transfer_type=0; 315 | u8 *bufptr = (u8*)buffer; 316 | u8 *transfer_buffer = NULL; 317 | u32 tmp_transferredSize = 0; 318 | size_t total_transferredSize=0; 319 | UsbDsReportData reportdata; 320 | 321 | //Makes sure endpoints are ready for data-transfer / wait for init if needed. 322 | rc = usbDsWaitReady(UINT64_MAX); 323 | if (R_FAILED(rc)) return rc; 324 | 325 | while(size) 326 | { 327 | if(((u64)bufptr) & 0xfff)//When bufptr isn't page-aligned copy the data into g_usbComms_endpoint_in_buffer and transfer that, otherwise use the bufptr directly. 328 | { 329 | transfer_buffer = ep->buffer; 330 | memset(ep->buffer, 0, 0x1000); 331 | 332 | chunksize = 0x1000; 333 | chunksize-= ((u64)bufptr) & 0xfff;//After this transfer, bufptr will be page-aligned(if size is large enough for another transfer). 334 | if (sizebuffer, bufptr, chunksize); 338 | 339 | transfer_type = 0; 340 | } 341 | else 342 | { 343 | transfer_buffer = bufptr; 344 | chunksize = size; 345 | transfer_type = 1; 346 | } 347 | 348 | //Start transfer. 349 | rc = usbDsEndpoint_PostBufferAsync(ep->endpoint, transfer_buffer, chunksize, &urbId); 350 | if(R_FAILED(rc))return rc; 351 | 352 | //Wait for the transfer to finish. 353 | rc = eventWait(&ep->endpoint->CompletionEvent, timeout); 354 | 355 | if (R_FAILED(rc)) 356 | { 357 | usbDsEndpoint_Cancel(ep->endpoint); 358 | eventWait(&ep->endpoint->CompletionEvent, UINT64_MAX); 359 | eventClear(&ep->endpoint->CompletionEvent); 360 | return rc; 361 | } 362 | eventClear(&ep->endpoint->CompletionEvent); 363 | 364 | rc = usbDsEndpoint_GetReportData(ep->endpoint, &reportdata); 365 | if (R_FAILED(rc)) return rc; 366 | 367 | rc = usbDsParseReportData(&reportdata, urbId, NULL, &tmp_transferredSize); 368 | if (R_FAILED(rc)) return rc; 369 | 370 | if (tmp_transferredSize > chunksize) tmp_transferredSize = chunksize; 371 | 372 | total_transferredSize+= (size_t)tmp_transferredSize; 373 | 374 | if ((transfer_type==0) && (dir == UsbDirection_Read)) 375 | memcpy(bufptr, transfer_buffer, tmp_transferredSize); 376 | 377 | bufptr+= tmp_transferredSize; 378 | size-= tmp_transferredSize; 379 | 380 | if (tmp_transferredSize < chunksize) break; 381 | } 382 | 383 | if (transferredSize) *transferredSize = total_transferredSize; 384 | 385 | return rc; 386 | } 387 | 388 | size_t usbTransfer(u32 interface, u32 endpoint, UsbDirection dir, void* buffer, size_t size, u64 timeout) 389 | { 390 | size_t transferredSize=-1; 391 | u32 state=0; 392 | Result rc, rc2; 393 | bool initialized; 394 | 395 | usbCommsInterface *inter = &g_usbCommsInterfaces[interface]; 396 | usbCommsEndpoint *ep = &inter->endpoint[endpoint]; 397 | rwlockReadLock(&inter->lock); 398 | initialized = inter->initialized; 399 | rwlockReadUnlock(&inter->lock); 400 | if (!initialized) return 0; 401 | 402 | rwlockWriteLock(&ep->lock); 403 | rc = _usbCommsTransfer(ep, dir, buffer, size, timeout, &transferredSize); 404 | rwlockWriteUnlock(&ep->lock); 405 | if (R_FAILED(rc)) { 406 | rc2 = usbDsGetState(&state); 407 | if (R_SUCCEEDED(rc2)) { 408 | if (state!=5) { 409 | rwlockWriteLock(&ep->lock); 410 | rc = _usbCommsTransfer(ep, dir, buffer, size, timeout, &transferredSize); //If state changed during transfer, try again. usbDsWaitReady() will be called from this. 411 | rwlockWriteUnlock(&ep->lock); 412 | } 413 | } 414 | if (R_FAILED(rc) && g_usbCommsErrorHandling) 415 | { 416 | if(dir == UsbDirection_Write) 417 | diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsWrite)); 418 | else 419 | diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsRead)); 420 | } 421 | } 422 | return transferredSize; 423 | } 424 | -------------------------------------------------------------------------------- /source/MtpProperty.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define LOG_TAG "MtpProperty" 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "MtpDataPacket.h" 25 | #include "MtpDebug.h" 26 | #include "MtpProperty.h" 27 | #include "MtpStringBuffer.h" 28 | #include "MtpUtils.h" 29 | 30 | #include "log.h" 31 | 32 | namespace android { 33 | 34 | MtpProperty::MtpProperty() 35 | : mCode(0), 36 | mType(0), 37 | mWriteable(false), 38 | mDefaultArrayLength(0), 39 | mDefaultArrayValues(NULL), 40 | mCurrentArrayLength(0), 41 | mCurrentArrayValues(NULL), 42 | mGroupCode(0), 43 | mFormFlag(kFormNone), 44 | mEnumLength(0), 45 | mEnumValues(NULL) 46 | { 47 | memset(&mDefaultValue, 0, sizeof(mDefaultValue)); 48 | memset(&mCurrentValue, 0, sizeof(mCurrentValue)); 49 | memset(&mMinimumValue, 0, sizeof(mMinimumValue)); 50 | memset(&mMaximumValue, 0, sizeof(mMaximumValue)); 51 | } 52 | 53 | MtpProperty::MtpProperty(MtpPropertyCode propCode, 54 | MtpDataType type, 55 | bool writeable, 56 | int defaultValue) 57 | : mCode(propCode), 58 | mType(type), 59 | mWriteable(writeable), 60 | mDefaultArrayLength(0), 61 | mDefaultArrayValues(NULL), 62 | mCurrentArrayLength(0), 63 | mCurrentArrayValues(NULL), 64 | mGroupCode(0), 65 | mFormFlag(kFormNone), 66 | mEnumLength(0), 67 | mEnumValues(NULL) 68 | { 69 | memset(&mDefaultValue, 0, sizeof(mDefaultValue)); 70 | memset(&mCurrentValue, 0, sizeof(mCurrentValue)); 71 | memset(&mMinimumValue, 0, sizeof(mMinimumValue)); 72 | memset(&mMaximumValue, 0, sizeof(mMaximumValue)); 73 | 74 | if (defaultValue) { 75 | switch (type) { 76 | case MTP_TYPE_INT8: 77 | mDefaultValue.u.i8 = defaultValue; 78 | break; 79 | case MTP_TYPE_UINT8: 80 | mDefaultValue.u.u8 = defaultValue; 81 | break; 82 | case MTP_TYPE_INT16: 83 | mDefaultValue.u.i16 = defaultValue; 84 | break; 85 | case MTP_TYPE_UINT16: 86 | mDefaultValue.u.u16 = defaultValue; 87 | break; 88 | case MTP_TYPE_INT32: 89 | mDefaultValue.u.i32 = defaultValue; 90 | break; 91 | case MTP_TYPE_UINT32: 92 | mDefaultValue.u.u32 = defaultValue; 93 | break; 94 | case MTP_TYPE_INT64: 95 | mDefaultValue.u.i64 = defaultValue; 96 | break; 97 | case MTP_TYPE_UINT64: 98 | mDefaultValue.u.u64 = defaultValue; 99 | break; 100 | default: 101 | LOG(ERROR) << "unknown type " 102 | << std::hex << type << std::dec 103 | << " in MtpProperty::MtpProperty"; 104 | } 105 | } 106 | } 107 | 108 | MtpProperty::~MtpProperty() { 109 | if (mType == MTP_TYPE_STR) { 110 | // free all strings 111 | free(mDefaultValue.str); 112 | free(mCurrentValue.str); 113 | free(mMinimumValue.str); 114 | free(mMaximumValue.str); 115 | if (mDefaultArrayValues) { 116 | for (int i = 0; i < mDefaultArrayLength; i++) 117 | free(mDefaultArrayValues[i].str); 118 | } 119 | if (mCurrentArrayValues) { 120 | for (int i = 0; i < mCurrentArrayLength; i++) 121 | free(mCurrentArrayValues[i].str); 122 | } 123 | if (mEnumValues) { 124 | for (int i = 0; i < mEnumLength; i++) 125 | free(mEnumValues[i].str); 126 | } 127 | } 128 | delete[] mDefaultArrayValues; 129 | delete[] mCurrentArrayValues; 130 | delete[] mEnumValues; 131 | } 132 | 133 | void MtpProperty::read(MtpDataPacket& packet) { 134 | mCode = packet.getUInt16(); 135 | bool deviceProp = isDeviceProperty(); 136 | mType = packet.getUInt16(); 137 | mWriteable = (packet.getUInt8() == 1); 138 | switch (mType) { 139 | case MTP_TYPE_AINT8: 140 | case MTP_TYPE_AUINT8: 141 | case MTP_TYPE_AINT16: 142 | case MTP_TYPE_AUINT16: 143 | case MTP_TYPE_AINT32: 144 | case MTP_TYPE_AUINT32: 145 | case MTP_TYPE_AINT64: 146 | case MTP_TYPE_AUINT64: 147 | case MTP_TYPE_AINT128: 148 | case MTP_TYPE_AUINT128: 149 | mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength); 150 | if (deviceProp) 151 | mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength); 152 | break; 153 | default: 154 | readValue(packet, mDefaultValue); 155 | if (deviceProp) 156 | readValue(packet, mCurrentValue); 157 | } 158 | if (!deviceProp) 159 | mGroupCode = packet.getUInt32(); 160 | mFormFlag = packet.getUInt8(); 161 | 162 | if (mFormFlag == kFormRange) { 163 | readValue(packet, mMinimumValue); 164 | readValue(packet, mMaximumValue); 165 | readValue(packet, mStepSize); 166 | } else if (mFormFlag == kFormEnum) { 167 | mEnumLength = packet.getUInt16(); 168 | mEnumValues = new MtpPropertyValue[mEnumLength]; 169 | for (int i = 0; i < mEnumLength; i++) 170 | readValue(packet, mEnumValues[i]); 171 | } 172 | } 173 | 174 | void MtpProperty::write(MtpDataPacket& packet) { 175 | bool deviceProp = isDeviceProperty(); 176 | 177 | packet.putUInt16(mCode); 178 | packet.putUInt16(mType); 179 | packet.putUInt8(mWriteable ? 1 : 0); 180 | 181 | switch (mType) { 182 | case MTP_TYPE_AINT8: 183 | case MTP_TYPE_AUINT8: 184 | case MTP_TYPE_AINT16: 185 | case MTP_TYPE_AUINT16: 186 | case MTP_TYPE_AINT32: 187 | case MTP_TYPE_AUINT32: 188 | case MTP_TYPE_AINT64: 189 | case MTP_TYPE_AUINT64: 190 | case MTP_TYPE_AINT128: 191 | case MTP_TYPE_AUINT128: 192 | writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength); 193 | if (deviceProp) 194 | writeArrayValues(packet, mCurrentArrayValues, mCurrentArrayLength); 195 | break; 196 | default: 197 | writeValue(packet, mDefaultValue); 198 | if (deviceProp) 199 | writeValue(packet, mCurrentValue); 200 | } 201 | packet.putUInt32(mGroupCode); 202 | if (!deviceProp) 203 | packet.putUInt8(mFormFlag); 204 | if (mFormFlag == kFormRange) { 205 | writeValue(packet, mMinimumValue); 206 | writeValue(packet, mMaximumValue); 207 | writeValue(packet, mStepSize); 208 | } else if (mFormFlag == kFormEnum) { 209 | packet.putUInt16(mEnumLength); 210 | for (int i = 0; i < mEnumLength; i++) 211 | writeValue(packet, mEnumValues[i]); 212 | } 213 | } 214 | 215 | void MtpProperty::setDefaultValue(const uint16_t* string) { 216 | free(mDefaultValue.str); 217 | if (string) { 218 | MtpStringBuffer buffer(string); 219 | mDefaultValue.str = strdup(buffer); 220 | } 221 | else 222 | mDefaultValue.str = NULL; 223 | } 224 | 225 | void MtpProperty::setCurrentValue(const uint16_t* string) { 226 | free(mCurrentValue.str); 227 | if (string) { 228 | MtpStringBuffer buffer(string); 229 | mCurrentValue.str = strdup(buffer); 230 | } 231 | else 232 | mCurrentValue.str = NULL; 233 | } 234 | 235 | void MtpProperty::setFormRange(int min, int max, int step) { 236 | mFormFlag = kFormRange; 237 | switch (mType) { 238 | case MTP_TYPE_INT8: 239 | mMinimumValue.u.i8 = min; 240 | mMaximumValue.u.i8 = max; 241 | mStepSize.u.i8 = step; 242 | break; 243 | case MTP_TYPE_UINT8: 244 | mMinimumValue.u.u8 = min; 245 | mMaximumValue.u.u8 = max; 246 | mStepSize.u.u8 = step; 247 | break; 248 | case MTP_TYPE_INT16: 249 | mMinimumValue.u.i16 = min; 250 | mMaximumValue.u.i16 = max; 251 | mStepSize.u.i16 = step; 252 | break; 253 | case MTP_TYPE_UINT16: 254 | mMinimumValue.u.u16 = min; 255 | mMaximumValue.u.u16 = max; 256 | mStepSize.u.u16 = step; 257 | break; 258 | case MTP_TYPE_INT32: 259 | mMinimumValue.u.i32 = min; 260 | mMaximumValue.u.i32 = max; 261 | mStepSize.u.i32 = step; 262 | break; 263 | case MTP_TYPE_UINT32: 264 | mMinimumValue.u.u32 = min; 265 | mMaximumValue.u.u32 = max; 266 | mStepSize.u.u32 = step; 267 | break; 268 | case MTP_TYPE_INT64: 269 | mMinimumValue.u.i64 = min; 270 | mMaximumValue.u.i64 = max; 271 | mStepSize.u.i64 = step; 272 | break; 273 | case MTP_TYPE_UINT64: 274 | mMinimumValue.u.u64 = min; 275 | mMaximumValue.u.u64 = max; 276 | mStepSize.u.u64 = step; 277 | break; 278 | default: 279 | LOG(ERROR) << "unsupported type for MtpProperty::setRange"; 280 | break; 281 | } 282 | } 283 | 284 | void MtpProperty::setFormEnum(const int* values, int count) { 285 | mFormFlag = kFormEnum; 286 | delete[] mEnumValues; 287 | mEnumValues = new MtpPropertyValue[count]; 288 | mEnumLength = count; 289 | 290 | for (int i = 0; i < count; i++) { 291 | int value = *values++; 292 | switch (mType) { 293 | case MTP_TYPE_INT8: 294 | mEnumValues[i].u.i8 = value; 295 | break; 296 | case MTP_TYPE_UINT8: 297 | mEnumValues[i].u.u8 = value; 298 | break; 299 | case MTP_TYPE_INT16: 300 | mEnumValues[i].u.i16 = value; 301 | break; 302 | case MTP_TYPE_UINT16: 303 | mEnumValues[i].u.u16 = value; 304 | break; 305 | case MTP_TYPE_INT32: 306 | mEnumValues[i].u.i32 = value; 307 | break; 308 | case MTP_TYPE_UINT32: 309 | mEnumValues[i].u.u32 = value; 310 | break; 311 | case MTP_TYPE_INT64: 312 | mEnumValues[i].u.i64 = value; 313 | break; 314 | case MTP_TYPE_UINT64: 315 | mEnumValues[i].u.u64 = value; 316 | break; 317 | default: 318 | LOG(ERROR) << "unsupported type for MtpProperty::setEnum"; 319 | break; 320 | } 321 | } 322 | } 323 | 324 | void MtpProperty::setFormDateTime() { 325 | mFormFlag = kFormDateTime; 326 | } 327 | 328 | void MtpProperty::print() { 329 | MtpString buffer; 330 | bool deviceProp = isDeviceProperty(); 331 | if (deviceProp) 332 | VLOG(2) << MtpDebug::getDevicePropCodeName(mCode) 333 | << " (" << std::hex << mCode << std::dec << ")"; 334 | else 335 | VLOG(2) << MtpDebug::getObjectPropCodeName(mCode) 336 | << " (" << std::hex << mCode << std::dec << ")"; 337 | VLOG(2) << mType; 338 | VLOG(2) << "writeable " << (mWriteable ? "true" : "false"); 339 | buffer = "default value: "; 340 | print(mDefaultValue, buffer); 341 | VLOG(2) << buffer.c_str(); 342 | if (deviceProp) { 343 | buffer = "current value: "; 344 | print(mCurrentValue, buffer); 345 | VLOG(2) << buffer.c_str(); 346 | } 347 | switch (mFormFlag) { 348 | case kFormNone: 349 | break; 350 | case kFormRange: 351 | buffer = "Range ("; 352 | print(mMinimumValue, buffer); 353 | buffer += ", "; 354 | print(mMaximumValue, buffer); 355 | buffer += ", "; 356 | print(mStepSize, buffer); 357 | buffer += ")"; 358 | VLOG(2) << buffer.c_str(); 359 | break; 360 | case kFormEnum: 361 | buffer = "Enum { "; 362 | for (int i = 0; i < mEnumLength; i++) { 363 | print(mEnumValues[i], buffer); 364 | buffer += " "; 365 | } 366 | buffer += "}"; 367 | VLOG(2) << buffer.c_str(); 368 | break; 369 | case kFormDateTime: 370 | VLOG(2) << "DateTime"; 371 | break; 372 | default: 373 | VLOG(2) << "form " << mFormFlag; 374 | break; 375 | } 376 | } 377 | 378 | void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) { 379 | std::stringstream ss; 380 | switch (mType) { 381 | case MTP_TYPE_INT8: 382 | ss << value.u.i8; 383 | break; 384 | case MTP_TYPE_UINT8: 385 | ss << value.u.u8; 386 | break; 387 | case MTP_TYPE_INT16: 388 | ss << value.u.i16; 389 | break; 390 | case MTP_TYPE_UINT16: 391 | ss << value.u.u16; 392 | break; 393 | case MTP_TYPE_INT32: 394 | ss << value.u.i32; 395 | break; 396 | case MTP_TYPE_UINT32: 397 | ss << value.u.u32; 398 | break; 399 | case MTP_TYPE_INT64: 400 | ss << value.u.i64; 401 | break; 402 | case MTP_TYPE_UINT64: 403 | ss << value.u.u64; 404 | break; 405 | 406 | case MTP_TYPE_INT128: 407 | ss << std::hex << value.u.i128[0] << std::hex << value.u.i128[1] << std::hex << value.u.i128[2] << std::hex << value.u.i128[3]; 408 | //buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1], 409 | // value.u.i128[2], value.u.i128[3]); 410 | break; 411 | case MTP_TYPE_UINT128: 412 | ss << std::hex << value.u.u128[0] << std::hex << value.u.u128[1] << std::hex << value.u.u128[2] << std::hex << value.u.u128[3]; 413 | // buffer.appendFormat("%08X%08X%08X%08X", value.u.u128[0], value.u.u128[1], 414 | // value.u.u128[2], value.u.u128[3]); 415 | break; 416 | case MTP_TYPE_STR: 417 | ss << value.str; 418 | break; 419 | default: 420 | LOG(ERROR) << "unsupported type for MtpProperty::print"; 421 | break; 422 | } 423 | 424 | buffer += ss.str(); 425 | } 426 | 427 | void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) { 428 | MtpStringBuffer stringBuffer; 429 | 430 | switch (mType) { 431 | case MTP_TYPE_INT8: 432 | case MTP_TYPE_AINT8: 433 | value.u.i8 = packet.getInt8(); 434 | break; 435 | case MTP_TYPE_UINT8: 436 | case MTP_TYPE_AUINT8: 437 | value.u.u8 = packet.getUInt8(); 438 | break; 439 | case MTP_TYPE_INT16: 440 | case MTP_TYPE_AINT16: 441 | value.u.i16 = packet.getInt16(); 442 | break; 443 | case MTP_TYPE_UINT16: 444 | case MTP_TYPE_AUINT16: 445 | value.u.u16 = packet.getUInt16(); 446 | break; 447 | case MTP_TYPE_INT32: 448 | case MTP_TYPE_AINT32: 449 | value.u.i32 = packet.getInt32(); 450 | break; 451 | case MTP_TYPE_UINT32: 452 | case MTP_TYPE_AUINT32: 453 | value.u.u32 = packet.getUInt32(); 454 | break; 455 | case MTP_TYPE_INT64: 456 | case MTP_TYPE_AINT64: 457 | value.u.i64 = packet.getInt64(); 458 | break; 459 | case MTP_TYPE_UINT64: 460 | case MTP_TYPE_AUINT64: 461 | value.u.u64 = packet.getUInt64(); 462 | break; 463 | case MTP_TYPE_INT128: 464 | case MTP_TYPE_AINT128: 465 | packet.getInt128(value.u.i128); 466 | break; 467 | case MTP_TYPE_UINT128: 468 | case MTP_TYPE_AUINT128: 469 | packet.getUInt128(value.u.u128); 470 | break; 471 | case MTP_TYPE_STR: 472 | packet.getString(stringBuffer); 473 | value.str = strdup(stringBuffer); 474 | break; 475 | default: 476 | LOG(ERROR) << "unknown type " 477 | << std::hex << mType << std::dec 478 | << " in MtpProperty::readValue"; 479 | } 480 | } 481 | 482 | void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) { 483 | MtpStringBuffer stringBuffer; 484 | 485 | switch (mType) { 486 | case MTP_TYPE_INT8: 487 | case MTP_TYPE_AINT8: 488 | packet.putInt8(value.u.i8); 489 | break; 490 | case MTP_TYPE_UINT8: 491 | case MTP_TYPE_AUINT8: 492 | packet.putUInt8(value.u.u8); 493 | break; 494 | case MTP_TYPE_INT16: 495 | case MTP_TYPE_AINT16: 496 | packet.putInt16(value.u.i16); 497 | break; 498 | case MTP_TYPE_UINT16: 499 | case MTP_TYPE_AUINT16: 500 | packet.putUInt16(value.u.u16); 501 | break; 502 | case MTP_TYPE_INT32: 503 | case MTP_TYPE_AINT32: 504 | packet.putInt32(value.u.i32); 505 | break; 506 | case MTP_TYPE_UINT32: 507 | case MTP_TYPE_AUINT32: 508 | packet.putUInt32(value.u.u32); 509 | break; 510 | case MTP_TYPE_INT64: 511 | case MTP_TYPE_AINT64: 512 | packet.putInt64(value.u.i64); 513 | break; 514 | case MTP_TYPE_UINT64: 515 | case MTP_TYPE_AUINT64: 516 | packet.putUInt64(value.u.u64); 517 | break; 518 | case MTP_TYPE_INT128: 519 | case MTP_TYPE_AINT128: 520 | packet.putInt128(value.u.i128); 521 | break; 522 | case MTP_TYPE_UINT128: 523 | case MTP_TYPE_AUINT128: 524 | packet.putUInt128(value.u.u128); 525 | break; 526 | case MTP_TYPE_STR: 527 | if (value.str) 528 | packet.putString(value.str); 529 | else 530 | packet.putEmptyString(); 531 | break; 532 | default: 533 | LOG(ERROR) << "unknown type " 534 | << std::hex << mType << std::dec 535 | << " in MtpProperty::writeValue"; 536 | } 537 | } 538 | 539 | MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) { 540 | length = packet.getUInt32(); 541 | if (length == 0) 542 | return NULL; 543 | MtpPropertyValue* result = new MtpPropertyValue[length]; 544 | for (int i = 0; i < length; i++) 545 | readValue(packet, result[i]); 546 | return result; 547 | } 548 | 549 | void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) { 550 | packet.putUInt32(length); 551 | for (int i = 0; i < length; i++) 552 | writeValue(packet, values[i]); 553 | } 554 | 555 | } // namespace android 556 | -------------------------------------------------------------------------------- /source/MtpDebug.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "MtpDebug.h" 18 | 19 | namespace android { 20 | 21 | struct CodeEntry { 22 | const char* name; 23 | uint16_t code; 24 | }; 25 | 26 | static const CodeEntry sOperationCodes[] = { 27 | { "MTP_OPERATION_GET_DEVICE_INFO", 0x1001 }, 28 | { "MTP_OPERATION_OPEN_SESSION", 0x1002 }, 29 | { "MTP_OPERATION_CLOSE_SESSION", 0x1003 }, 30 | { "MTP_OPERATION_GET_STORAGE_IDS", 0x1004 }, 31 | { "MTP_OPERATION_GET_STORAGE_INFO", 0x1005 }, 32 | { "MTP_OPERATION_GET_NUM_OBJECTS", 0x1006 }, 33 | { "MTP_OPERATION_GET_OBJECT_HANDLES", 0x1007 }, 34 | { "MTP_OPERATION_GET_OBJECT_INFO", 0x1008 }, 35 | { "MTP_OPERATION_GET_OBJECT", 0x1009 }, 36 | { "MTP_OPERATION_GET_THUMB", 0x100A }, 37 | { "MTP_OPERATION_DELETE_OBJECT", 0x100B }, 38 | { "MTP_OPERATION_SEND_OBJECT_INFO", 0x100C }, 39 | { "MTP_OPERATION_SEND_OBJECT", 0x100D }, 40 | { "MTP_OPERATION_INITIATE_CAPTURE", 0x100E }, 41 | { "MTP_OPERATION_FORMAT_STORE", 0x100F }, 42 | { "MTP_OPERATION_RESET_DEVICE", 0x1010 }, 43 | { "MTP_OPERATION_SELF_TEST", 0x1011 }, 44 | { "MTP_OPERATION_SET_OBJECT_PROTECTION", 0x1012 }, 45 | { "MTP_OPERATION_POWER_DOWN", 0x1013 }, 46 | { "MTP_OPERATION_GET_DEVICE_PROP_DESC", 0x1014 }, 47 | { "MTP_OPERATION_GET_DEVICE_PROP_VALUE", 0x1015 }, 48 | { "MTP_OPERATION_SET_DEVICE_PROP_VALUE", 0x1016 }, 49 | { "MTP_OPERATION_RESET_DEVICE_PROP_VALUE", 0x1017 }, 50 | { "MTP_OPERATION_TERMINATE_OPEN_CAPTURE", 0x1018 }, 51 | { "MTP_OPERATION_MOVE_OBJECT", 0x1019 }, 52 | { "MTP_OPERATION_COPY_OBJECT", 0x101A }, 53 | { "MTP_OPERATION_GET_PARTIAL_OBJECT", 0x101B }, 54 | { "MTP_OPERATION_INITIATE_OPEN_CAPTURE", 0x101C }, 55 | { "MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED", 0x9801 }, 56 | { "MTP_OPERATION_GET_OBJECT_PROP_DESC", 0x9802 }, 57 | { "MTP_OPERATION_GET_OBJECT_PROP_VALUE", 0x9803 }, 58 | { "MTP_OPERATION_SET_OBJECT_PROP_VALUE", 0x9804 }, 59 | { "MTP_OPERATION_GET_OBJECT_PROP_LIST", 0x9805 }, 60 | { "MTP_OPERATION_SET_OBJECT_PROP_LIST", 0x9806 }, 61 | { "MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC", 0x9807 }, 62 | { "MTP_OPERATION_SEND_OBJECT_PROP_LIST", 0x9808 }, 63 | { "MTP_OPERATION_GET_OBJECT_REFERENCES", 0x9810 }, 64 | { "MTP_OPERATION_SET_OBJECT_REFERENCES", 0x9811 }, 65 | { "MTP_OPERATION_SKIP", 0x9820 }, 66 | // android extensions 67 | { "MTP_OPERATION_GET_PARTIAL_OBJECT_64", 0x95C1 }, 68 | { "MTP_OPERATION_SEND_PARTIAL_OBJECT", 0x95C2 }, 69 | { "MTP_OPERATION_TRUNCATE_OBJECT", 0x95C3 }, 70 | { "MTP_OPERATION_BEGIN_EDIT_OBJECT", 0x95C4 }, 71 | { "MTP_OPERATION_END_EDIT_OBJECT", 0x95C5 }, 72 | { 0, 0 }, 73 | }; 74 | 75 | static const CodeEntry sFormatCodes[] = { 76 | { "MTP_FORMAT_UNDEFINED", 0x3000 }, 77 | { "MTP_FORMAT_ASSOCIATION", 0x3001 }, 78 | { "MTP_FORMAT_SCRIPT", 0x3002 }, 79 | { "MTP_FORMAT_EXECUTABLE", 0x3003 }, 80 | { "MTP_FORMAT_TEXT", 0x3004 }, 81 | { "MTP_FORMAT_HTML", 0x3005 }, 82 | { "MTP_FORMAT_DPOF", 0x3006 }, 83 | { "MTP_FORMAT_AIFF", 0x3007 }, 84 | { "MTP_FORMAT_WAV", 0x3008 }, 85 | { "MTP_FORMAT_MP3", 0x3009 }, 86 | { "MTP_FORMAT_AVI", 0x300A }, 87 | { "MTP_FORMAT_MPEG", 0x300B }, 88 | { "MTP_FORMAT_ASF", 0x300C }, 89 | { "MTP_FORMAT_DEFINED", 0x3800 }, 90 | { "MTP_FORMAT_EXIF_JPEG", 0x3801 }, 91 | { "MTP_FORMAT_TIFF_EP", 0x3802 }, 92 | { "MTP_FORMAT_FLASHPIX", 0x3803 }, 93 | { "MTP_FORMAT_BMP", 0x3804 }, 94 | { "MTP_FORMAT_CIFF", 0x3805 }, 95 | { "MTP_FORMAT_GIF", 0x3807 }, 96 | { "MTP_FORMAT_JFIF", 0x3808 }, 97 | { "MTP_FORMAT_CD", 0x3809 }, 98 | { "MTP_FORMAT_PICT", 0x380A }, 99 | { "MTP_FORMAT_PNG", 0x380B }, 100 | { "MTP_FORMAT_TIFF", 0x380D }, 101 | { "MTP_FORMAT_TIFF_IT", 0x380E }, 102 | { "MTP_FORMAT_JP2", 0x380F }, 103 | { "MTP_FORMAT_JPX", 0x3810 }, 104 | { "MTP_FORMAT_UNDEFINED_FIRMWARE", 0xB802 }, 105 | { "MTP_FORMAT_WINDOWS_IMAGE_FORMAT", 0xB881 }, 106 | { "MTP_FORMAT_UNDEFINED_AUDIO", 0xB900 }, 107 | { "MTP_FORMAT_WMA", 0xB901 }, 108 | { "MTP_FORMAT_OGG", 0xB902 }, 109 | { "MTP_FORMAT_AAC", 0xB903 }, 110 | { "MTP_FORMAT_AUDIBLE", 0xB904 }, 111 | { "MTP_FORMAT_FLAC", 0xB906 }, 112 | { "MTP_FORMAT_UNDEFINED_VIDEO", 0xB980 }, 113 | { "MTP_FORMAT_WMV", 0xB981 }, 114 | { "MTP_FORMAT_MP4_CONTAINER", 0xB982 }, 115 | { "MTP_FORMAT_MP2", 0xB983 }, 116 | { "MTP_FORMAT_3GP_CONTAINER", 0xB984 }, 117 | { "MTP_FORMAT_UNDEFINED_COLLECTION", 0xBA00 }, 118 | { "MTP_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM", 0xBA01 }, 119 | { "MTP_FORMAT_ABSTRACT_IMAGE_ALBUM", 0xBA02 }, 120 | { "MTP_FORMAT_ABSTRACT_AUDIO_ALBUM", 0xBA03 }, 121 | { "MTP_FORMAT_ABSTRACT_VIDEO_ALBUM", 0xBA04 }, 122 | { "MTP_FORMAT_ABSTRACT_AV_PLAYLIST", 0xBA05 }, 123 | { "MTP_FORMAT_ABSTRACT_CONTACT_GROUP", 0xBA06 }, 124 | { "MTP_FORMAT_ABSTRACT_MESSAGE_FOLDER", 0xBA07 }, 125 | { "MTP_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION", 0xBA08 }, 126 | { "MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST", 0xBA09 }, 127 | { "MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST", 0xBA0A }, 128 | { "MTP_FORMAT_ABSTRACT_MEDIACAST", 0xBA0B }, 129 | { "MTP_FORMAT_WPL_PLAYLIST", 0xBA10 }, 130 | { "MTP_FORMAT_M3U_PLAYLIST", 0xBA11 }, 131 | { "MTP_FORMAT_MPL_PLAYLIST", 0xBA12 }, 132 | { "MTP_FORMAT_ASX_PLAYLIST", 0xBA13 }, 133 | { "MTP_FORMAT_PLS_PLAYLIST", 0xBA14 }, 134 | { "MTP_FORMAT_UNDEFINED_DOCUMENT", 0xBA80 }, 135 | { "MTP_FORMAT_ABSTRACT_DOCUMENT", 0xBA81 }, 136 | { "MTP_FORMAT_XML_DOCUMENT", 0xBA82 }, 137 | { "MTP_FORMAT_MS_WORD_DOCUMENT", 0xBA83 }, 138 | { "MTP_FORMAT_MHT_COMPILED_HTML_DOCUMENT", 0xBA84 }, 139 | { "MTP_FORMAT_MS_EXCEL_SPREADSHEET", 0xBA85 }, 140 | { "MTP_FORMAT_MS_POWERPOINT_PRESENTATION", 0xBA86 }, 141 | { "MTP_FORMAT_UNDEFINED_MESSAGE", 0xBB00 }, 142 | { "MTP_FORMAT_ABSTRACT_MESSSAGE", 0xBB01 }, 143 | { "MTP_FORMAT_UNDEFINED_CONTACT", 0xBB80 }, 144 | { "MTP_FORMAT_ABSTRACT_CONTACT", 0xBB81 }, 145 | { "MTP_FORMAT_VCARD_2", 0xBB82 }, 146 | { 0, 0 }, 147 | }; 148 | 149 | static const CodeEntry sObjectPropCodes[] = { 150 | { "MTP_PROPERTY_STORAGE_ID", 0xDC01 }, 151 | { "MTP_PROPERTY_OBJECT_FORMAT", 0xDC02 }, 152 | { "MTP_PROPERTY_PROTECTION_STATUS", 0xDC03 }, 153 | { "MTP_PROPERTY_OBJECT_SIZE", 0xDC04 }, 154 | { "MTP_PROPERTY_ASSOCIATION_TYPE", 0xDC05 }, 155 | { "MTP_PROPERTY_ASSOCIATION_DESC", 0xDC06 }, 156 | { "MTP_PROPERTY_OBJECT_FILE_NAME", 0xDC07 }, 157 | { "MTP_PROPERTY_DATE_CREATED", 0xDC08 }, 158 | { "MTP_PROPERTY_DATE_MODIFIED", 0xDC09 }, 159 | { "MTP_PROPERTY_KEYWORDS", 0xDC0A }, 160 | { "MTP_PROPERTY_PARENT_OBJECT", 0xDC0B }, 161 | { "MTP_PROPERTY_ALLOWED_FOLDER_CONTENTS", 0xDC0C }, 162 | { "MTP_PROPERTY_HIDDEN", 0xDC0D }, 163 | { "MTP_PROPERTY_SYSTEM_OBJECT", 0xDC0E }, 164 | { "MTP_PROPERTY_PERSISTENT_UID", 0xDC41 }, 165 | { "MTP_PROPERTY_SYNC_ID", 0xDC42 }, 166 | { "MTP_PROPERTY_PROPERTY_BAG", 0xDC43 }, 167 | { "MTP_PROPERTY_NAME", 0xDC44 }, 168 | { "MTP_PROPERTY_CREATED_BY", 0xDC45 }, 169 | { "MTP_PROPERTY_ARTIST", 0xDC46 }, 170 | { "MTP_PROPERTY_DATE_AUTHORED", 0xDC47 }, 171 | { "MTP_PROPERTY_DESCRIPTION", 0xDC48 }, 172 | { "MTP_PROPERTY_URL_REFERENCE", 0xDC49 }, 173 | { "MTP_PROPERTY_LANGUAGE_LOCALE", 0xDC4A }, 174 | { "MTP_PROPERTY_COPYRIGHT_INFORMATION", 0xDC4B }, 175 | { "MTP_PROPERTY_SOURCE", 0xDC4C }, 176 | { "MTP_PROPERTY_ORIGIN_LOCATION", 0xDC4D }, 177 | { "MTP_PROPERTY_DATE_ADDED", 0xDC4E }, 178 | { "MTP_PROPERTY_NON_CONSUMABLE", 0xDC4F }, 179 | { "MTP_PROPERTY_CORRUPT_UNPLAYABLE", 0xDC50 }, 180 | { "MTP_PROPERTY_PRODUCER_SERIAL_NUMBER", 0xDC51 }, 181 | { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT", 0xDC81 }, 182 | { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_SIZE", 0xDC82 }, 183 | { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT", 0xDC83 }, 184 | { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH", 0xDC84 }, 185 | { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DURATION", 0xDC85 }, 186 | { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DATA", 0xDC86 }, 187 | { "MTP_PROPERTY_WIDTH", 0xDC87 }, 188 | { "MTP_PROPERTY_HEIGHT", 0xDC88 }, 189 | { "MTP_PROPERTY_DURATION", 0xDC89 }, 190 | { "MTP_PROPERTY_RATING", 0xDC8A }, 191 | { "MTP_PROPERTY_TRACK", 0xDC8B }, 192 | { "MTP_PROPERTY_GENRE", 0xDC8C }, 193 | { "MTP_PROPERTY_CREDITS", 0xDC8D }, 194 | { "MTP_PROPERTY_LYRICS", 0xDC8E }, 195 | { "MTP_PROPERTY_SUBSCRIPTION_CONTENT_ID", 0xDC8F }, 196 | { "MTP_PROPERTY_PRODUCED_BY", 0xDC90 }, 197 | { "MTP_PROPERTY_USE_COUNT", 0xDC91 }, 198 | { "MTP_PROPERTY_SKIP_COUNT", 0xDC92 }, 199 | { "MTP_PROPERTY_LAST_ACCESSED", 0xDC93 }, 200 | { "MTP_PROPERTY_PARENTAL_RATING", 0xDC94 }, 201 | { "MTP_PROPERTY_META_GENRE", 0xDC95 }, 202 | { "MTP_PROPERTY_COMPOSER", 0xDC96 }, 203 | { "MTP_PROPERTY_EFFECTIVE_RATING", 0xDC97 }, 204 | { "MTP_PROPERTY_SUBTITLE", 0xDC98 }, 205 | { "MTP_PROPERTY_ORIGINAL_RELEASE_DATE", 0xDC99 }, 206 | { "MTP_PROPERTY_ALBUM_NAME", 0xDC9A }, 207 | { "MTP_PROPERTY_ALBUM_ARTIST", 0xDC9B }, 208 | { "MTP_PROPERTY_MOOD", 0xDC9C }, 209 | { "MTP_PROPERTY_DRM_STATUS", 0xDC9D }, 210 | { "MTP_PROPERTY_SUB_DESCRIPTION", 0xDC9E }, 211 | { "MTP_PROPERTY_IS_CROPPED", 0xDCD1 }, 212 | { "MTP_PROPERTY_IS_COLOUR_CORRECTED", 0xDCD2 }, 213 | { "MTP_PROPERTY_IMAGE_BIT_DEPTH", 0xDCD3 }, 214 | { "MTP_PROPERTY_F_NUMBER", 0xDCD4 }, 215 | { "MTP_PROPERTY_EXPOSURE_TIME", 0xDCD5 }, 216 | { "MTP_PROPERTY_EXPOSURE_INDEX", 0xDCD6 }, 217 | { "MTP_PROPERTY_TOTAL_BITRATE", 0xDE91 }, 218 | { "MTP_PROPERTY_BITRATE_TYPE", 0xDE92 }, 219 | { "MTP_PROPERTY_SAMPLE_RATE", 0xDE93 }, 220 | { "MTP_PROPERTY_NUMBER_OF_CHANNELS", 0xDE94 }, 221 | { "MTP_PROPERTY_AUDIO_BIT_DEPTH", 0xDE95 }, 222 | { "MTP_PROPERTY_SCAN_TYPE", 0xDE97 }, 223 | { "MTP_PROPERTY_AUDIO_WAVE_CODEC", 0xDE99 }, 224 | { "MTP_PROPERTY_AUDIO_BITRATE", 0xDE9A }, 225 | { "MTP_PROPERTY_VIDEO_FOURCC_CODEC", 0xDE9B }, 226 | { "MTP_PROPERTY_VIDEO_BITRATE", 0xDE9C }, 227 | { "MTP_PROPERTY_FRAMES_PER_THOUSAND_SECONDS", 0xDE9D }, 228 | { "MTP_PROPERTY_KEYFRAME_DISTANCE", 0xDE9E }, 229 | { "MTP_PROPERTY_BUFFER_SIZE", 0xDE9F }, 230 | { "MTP_PROPERTY_ENCODING_QUALITY", 0xDEA0 }, 231 | { "MTP_PROPERTY_ENCODING_PROFILE", 0xDEA1 }, 232 | { "MTP_PROPERTY_DISPLAY_NAME", 0xDCE0 }, 233 | { "MTP_PROPERTY_BODY_TEXT", 0xDCE1 }, 234 | { "MTP_PROPERTY_SUBJECT", 0xDCE2 }, 235 | { "MTP_PROPERTY_PRIORITY", 0xDCE3 }, 236 | { "MTP_PROPERTY_GIVEN_NAME", 0xDD00 }, 237 | { "MTP_PROPERTY_MIDDLE_NAMES", 0xDD01 }, 238 | { "MTP_PROPERTY_FAMILY_NAME", 0xDD02 }, 239 | { "MTP_PROPERTY_PREFIX", 0xDD03 }, 240 | { "MTP_PROPERTY_SUFFIX", 0xDD04 }, 241 | { "MTP_PROPERTY_PHONETIC_GIVEN_NAME", 0xDD05 }, 242 | { "MTP_PROPERTY_PHONETIC_FAMILY_NAME", 0xDD06 }, 243 | { "MTP_PROPERTY_EMAIL_PRIMARY", 0xDD07 }, 244 | { "MTP_PROPERTY_EMAIL_PERSONAL_1", 0xDD08 }, 245 | { "MTP_PROPERTY_EMAIL_PERSONAL_2", 0xDD09 }, 246 | { "MTP_PROPERTY_EMAIL_BUSINESS_1", 0xDD0A }, 247 | { "MTP_PROPERTY_EMAIL_BUSINESS_2", 0xDD0B }, 248 | { "MTP_PROPERTY_EMAIL_OTHERS", 0xDD0C }, 249 | { "MTP_PROPERTY_PHONE_NUMBER_PRIMARY", 0xDD0D }, 250 | { "MTP_PROPERTY_PHONE_NUMBER_PERSONAL", 0xDD0E }, 251 | { "MTP_PROPERTY_PHONE_NUMBER_PERSONAL_2", 0xDD0F }, 252 | { "MTP_PROPERTY_PHONE_NUMBER_BUSINESS", 0xDD10 }, 253 | { "MTP_PROPERTY_PHONE_NUMBER_BUSINESS_2", 0xDD11 }, 254 | { "MTP_PROPERTY_PHONE_NUMBER_MOBILE", 0xDD12 }, 255 | { "MTP_PROPERTY_PHONE_NUMBER_MOBILE_2", 0xDD13 }, 256 | { "MTP_PROPERTY_FAX_NUMBER_PRIMARY", 0xDD14 }, 257 | { "MTP_PROPERTY_FAX_NUMBER_PERSONAL", 0xDD15 }, 258 | { "MTP_PROPERTY_FAX_NUMBER_BUSINESS", 0xDD16 }, 259 | { "MTP_PROPERTY_PAGER_NUMBER", 0xDD17 }, 260 | { "MTP_PROPERTY_PHONE_NUMBER_OTHERS", 0xDD18 }, 261 | { "MTP_PROPERTY_PRIMARY_WEB_ADDRESS", 0xDD19 }, 262 | { "MTP_PROPERTY_PERSONAL_WEB_ADDRESS", 0xDD1A }, 263 | { "MTP_PROPERTY_BUSINESS_WEB_ADDRESS", 0xDD1B }, 264 | { "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS", 0xDD1C }, 265 | { "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_2", 0xDD1D }, 266 | { "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_3", 0xDD1E }, 267 | { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL", 0xDD1F }, 268 | { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1", 0xDD20 }, 269 | { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2", 0xDD21 }, 270 | { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY", 0xDD22 }, 271 | { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION", 0xDD23 }, 272 | { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE", 0xDD24 }, 273 | { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY", 0xDD25 }, 274 | { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL", 0xDD26 }, 275 | { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1", 0xDD27 }, 276 | { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2", 0xDD28 }, 277 | { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY", 0xDD29 }, 278 | { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION", 0xDD2A }, 279 | { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE", 0xDD2B }, 280 | { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY", 0xDD2C }, 281 | { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_FULL", 0xDD2D }, 282 | { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1", 0xDD2E }, 283 | { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2", 0xDD2F }, 284 | { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_CITY", 0xDD30 }, 285 | { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_REGION", 0xDD31 }, 286 | { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE", 0xDD32 }, 287 | { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY", 0xDD33 }, 288 | { "MTP_PROPERTY_ORGANIZATION_NAME", 0xDD34 }, 289 | { "MTP_PROPERTY_PHONETIC_ORGANIZATION_NAME", 0xDD35 }, 290 | { "MTP_PROPERTY_ROLE", 0xDD36 }, 291 | { "MTP_PROPERTY_BIRTHDATE", 0xDD37 }, 292 | { "MTP_PROPERTY_MESSAGE_TO", 0xDD40 }, 293 | { "MTP_PROPERTY_MESSAGE_CC", 0xDD41 }, 294 | { "MTP_PROPERTY_MESSAGE_BCC", 0xDD42 }, 295 | { "MTP_PROPERTY_MESSAGE_READ", 0xDD43 }, 296 | { "MTP_PROPERTY_MESSAGE_RECEIVED_TIME", 0xDD44 }, 297 | { "MTP_PROPERTY_MESSAGE_SENDER", 0xDD45 }, 298 | { "MTP_PROPERTY_ACTIVITY_BEGIN_TIME", 0xDD50 }, 299 | { "MTP_PROPERTY_ACTIVITY_END_TIME", 0xDD51 }, 300 | { "MTP_PROPERTY_ACTIVITY_LOCATION", 0xDD52 }, 301 | { "MTP_PROPERTY_ACTIVITY_REQUIRED_ATTENDEES", 0xDD54 }, 302 | { "MTP_PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES", 0xDD55 }, 303 | { "MTP_PROPERTY_ACTIVITY_RESOURCES", 0xDD56 }, 304 | { "MTP_PROPERTY_ACTIVITY_ACCEPTED", 0xDD57 }, 305 | { "MTP_PROPERTY_ACTIVITY_TENTATIVE", 0xDD58 }, 306 | { "MTP_PROPERTY_ACTIVITY_DECLINED", 0xDD59 }, 307 | { "MTP_PROPERTY_ACTIVITY_REMAINDER_TIME", 0xDD5A }, 308 | { "MTP_PROPERTY_ACTIVITY_OWNER", 0xDD5B }, 309 | { "MTP_PROPERTY_ACTIVITY_STATUS", 0xDD5C }, 310 | { "MTP_PROPERTY_OWNER", 0xDD5D }, 311 | { "MTP_PROPERTY_EDITOR", 0xDD5E }, 312 | { "MTP_PROPERTY_WEBMASTER", 0xDD5F }, 313 | { "MTP_PROPERTY_URL_SOURCE", 0xDD60 }, 314 | { "MTP_PROPERTY_URL_DESTINATION", 0xDD61 }, 315 | { "MTP_PROPERTY_TIME_BOOKMARK", 0xDD62 }, 316 | { "MTP_PROPERTY_OBJECT_BOOKMARK", 0xDD63 }, 317 | { "MTP_PROPERTY_BYTE_BOOKMARK", 0xDD64 }, 318 | { "MTP_PROPERTY_LAST_BUILD_DATE", 0xDD70 }, 319 | { "MTP_PROPERTY_TIME_TO_LIVE", 0xDD71 }, 320 | { "MTP_PROPERTY_MEDIA_GUID", 0xDD72 }, 321 | { 0, 0 }, 322 | }; 323 | 324 | static const CodeEntry sDevicePropCodes[] = { 325 | { "MTP_DEVICE_PROPERTY_UNDEFINED", 0x5000 }, 326 | { "MTP_DEVICE_PROPERTY_BATTERY_LEVEL", 0x5001 }, 327 | { "MTP_DEVICE_PROPERTY_FUNCTIONAL_MODE", 0x5002 }, 328 | { "MTP_DEVICE_PROPERTY_IMAGE_SIZE", 0x5003 }, 329 | { "MTP_DEVICE_PROPERTY_COMPRESSION_SETTING", 0x5004 }, 330 | { "MTP_DEVICE_PROPERTY_WHITE_BALANCE", 0x5005 }, 331 | { "MTP_DEVICE_PROPERTY_RGB_GAIN", 0x5006 }, 332 | { "MTP_DEVICE_PROPERTY_F_NUMBER", 0x5007 }, 333 | { "MTP_DEVICE_PROPERTY_FOCAL_LENGTH", 0x5008 }, 334 | { "MTP_DEVICE_PROPERTY_FOCUS_DISTANCE", 0x5009 }, 335 | { "MTP_DEVICE_PROPERTY_FOCUS_MODE", 0x500A }, 336 | { "MTP_DEVICE_PROPERTY_EXPOSURE_METERING_MODE", 0x500B }, 337 | { "MTP_DEVICE_PROPERTY_FLASH_MODE", 0x500C }, 338 | { "MTP_DEVICE_PROPERTY_EXPOSURE_TIME", 0x500D }, 339 | { "MTP_DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE", 0x500E }, 340 | { "MTP_DEVICE_PROPERTY_EXPOSURE_INDEX", 0x500F }, 341 | { "MTP_DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION", 0x5010 }, 342 | { "MTP_DEVICE_PROPERTY_DATETIME", 0x5011 }, 343 | { "MTP_DEVICE_PROPERTY_CAPTURE_DELAY", 0x5012 }, 344 | { "MTP_DEVICE_PROPERTY_STILL_CAPTURE_MODE", 0x5013 }, 345 | { "MTP_DEVICE_PROPERTY_CONTRAST", 0x5014 }, 346 | { "MTP_DEVICE_PROPERTY_SHARPNESS", 0x5015 }, 347 | { "MTP_DEVICE_PROPERTY_DIGITAL_ZOOM", 0x5016 }, 348 | { "MTP_DEVICE_PROPERTY_EFFECT_MODE", 0x5017 }, 349 | { "MTP_DEVICE_PROPERTY_BURST_NUMBER", 0x5018 }, 350 | { "MTP_DEVICE_PROPERTY_BURST_INTERVAL", 0x5019 }, 351 | { "MTP_DEVICE_PROPERTY_TIMELAPSE_NUMBER", 0x501A }, 352 | { "MTP_DEVICE_PROPERTY_TIMELAPSE_INTERVAL", 0x501B }, 353 | { "MTP_DEVICE_PROPERTY_FOCUS_METERING_MODE", 0x501C }, 354 | { "MTP_DEVICE_PROPERTY_UPLOAD_URL", 0x501D }, 355 | { "MTP_DEVICE_PROPERTY_ARTIST", 0x501E }, 356 | { "MTP_DEVICE_PROPERTY_COPYRIGHT_INFO", 0x501F }, 357 | { "MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER", 0xD401 }, 358 | { "MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME", 0xD402 }, 359 | { "MTP_DEVICE_PROPERTY_VOLUME", 0xD403 }, 360 | { "MTP_DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED", 0xD404 }, 361 | { "MTP_DEVICE_PROPERTY_DEVICE_ICON", 0xD405 }, 362 | { "MTP_DEVICE_PROPERTY_PLAYBACK_RATE", 0xD410 }, 363 | { "MTP_DEVICE_PROPERTY_PLAYBACK_OBJECT", 0xD411 }, 364 | { "MTP_DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX", 0xD412 }, 365 | { "MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO", 0xD406 }, 366 | { "MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE", 0xD407 }, 367 | { 0, 0 }, 368 | }; 369 | 370 | static const char* getCodeName(uint16_t code, const CodeEntry* table) { 371 | const CodeEntry* entry = table; 372 | while (entry->name) { 373 | if (entry->code == code) 374 | return entry->name; 375 | entry++; 376 | } 377 | return "UNKNOWN"; 378 | } 379 | 380 | const char* MtpDebug::getOperationCodeName(MtpOperationCode code) { 381 | return getCodeName(code, sOperationCodes); 382 | } 383 | 384 | const char* MtpDebug::getFormatCodeName(MtpObjectFormat code) { 385 | if (code == 0) 386 | return "NONE"; 387 | return getCodeName(code, sFormatCodes); 388 | } 389 | 390 | const char* MtpDebug::getObjectPropCodeName(MtpPropertyCode code) { 391 | if (code == 0) 392 | return "NONE"; 393 | return getCodeName(code, sObjectPropCodes); 394 | } 395 | 396 | const char* MtpDebug::getDevicePropCodeName(MtpPropertyCode code) { 397 | if (code == 0) 398 | return "NONE"; 399 | return getCodeName(code, sDevicePropCodes); 400 | } 401 | 402 | } // namespace android 403 | -------------------------------------------------------------------------------- /include/mtp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _MTP_H 18 | #define _MTP_H 19 | 20 | #include 21 | #include 22 | 23 | #define MTP_STANDARD_VERSION 100 24 | 25 | // Container Types 26 | #define MTP_CONTAINER_TYPE_UNDEFINED 0 27 | #define MTP_CONTAINER_TYPE_COMMAND 1 28 | #define MTP_CONTAINER_TYPE_DATA 2 29 | #define MTP_CONTAINER_TYPE_RESPONSE 3 30 | #define MTP_CONTAINER_TYPE_EVENT 4 31 | 32 | // Container Offsets 33 | #define MTP_CONTAINER_LENGTH_OFFSET 0 34 | #define MTP_CONTAINER_TYPE_OFFSET 4 35 | #define MTP_CONTAINER_CODE_OFFSET 6 36 | #define MTP_CONTAINER_TRANSACTION_ID_OFFSET 8 37 | #define MTP_CONTAINER_PARAMETER_OFFSET 12 38 | #define MTP_CONTAINER_HEADER_SIZE 12 39 | 40 | // MTP Data Types 41 | #define MTP_TYPE_UNDEFINED 0x0000 // Undefined 42 | #define MTP_TYPE_INT8 0x0001 // Signed 8-bit integer 43 | #define MTP_TYPE_UINT8 0x0002 // Unsigned 8-bit integer 44 | #define MTP_TYPE_INT16 0x0003 // Signed 16-bit integer 45 | #define MTP_TYPE_UINT16 0x0004 // Unsigned 16-bit integer 46 | #define MTP_TYPE_INT32 0x0005 // Signed 32-bit integer 47 | #define MTP_TYPE_UINT32 0x0006 // Unsigned 32-bit integer 48 | #define MTP_TYPE_INT64 0x0007 // Signed 64-bit integer 49 | #define MTP_TYPE_UINT64 0x0008 // Unsigned 64-bit integer 50 | #define MTP_TYPE_INT128 0x0009 // Signed 128-bit integer 51 | #define MTP_TYPE_UINT128 0x000A // Unsigned 128-bit integer 52 | #define MTP_TYPE_AINT8 0x4001 // Array of signed 8-bit integers 53 | #define MTP_TYPE_AUINT8 0x4002 // Array of unsigned 8-bit integers 54 | #define MTP_TYPE_AINT16 0x4003 // Array of signed 16-bit integers 55 | #define MTP_TYPE_AUINT16 0x4004 // Array of unsigned 16-bit integers 56 | #define MTP_TYPE_AINT32 0x4005 // Array of signed 32-bit integers 57 | #define MTP_TYPE_AUINT32 0x4006 // Array of unsigned 32-bit integers 58 | #define MTP_TYPE_AINT64 0x4007 // Array of signed 64-bit integers 59 | #define MTP_TYPE_AUINT64 0x4008 // Array of unsigned 64-bit integers 60 | #define MTP_TYPE_AINT128 0x4009 // Array of signed 128-bit integers 61 | #define MTP_TYPE_AUINT128 0x400A // Array of unsigned 128-bit integers 62 | #define MTP_TYPE_STR 0xFFFF // Variable-length Unicode string 63 | 64 | // MTP Format Codes 65 | #define MTP_FORMAT_UNDEFINED 0x3000 // Undefined object 66 | #define MTP_FORMAT_ASSOCIATION 0x3001 // Association (for example, a folder) 67 | #define MTP_FORMAT_SCRIPT 0x3002 // Device model-specific script 68 | #define MTP_FORMAT_EXECUTABLE 0x3003 // Device model-specific binary executable 69 | #define MTP_FORMAT_TEXT 0x3004 // Text file 70 | #define MTP_FORMAT_HTML 0x3005 // Hypertext Markup Language file (text) 71 | #define MTP_FORMAT_DPOF 0x3006 // Digital Print Order Format file (text) 72 | #define MTP_FORMAT_AIFF 0x3007 // Audio clip 73 | #define MTP_FORMAT_WAV 0x3008 // Audio clip 74 | #define MTP_FORMAT_MP3 0x3009 // Audio clip 75 | #define MTP_FORMAT_AVI 0x300A // Video clip 76 | #define MTP_FORMAT_MPEG 0x300B // Video clip 77 | #define MTP_FORMAT_ASF 0x300C // Microsoft Advanced Streaming Format (video) 78 | #define MTP_FORMAT_DEFINED 0x3800 // Unknown image object 79 | #define MTP_FORMAT_EXIF_JPEG 0x3801 // Exchangeable File Format, JEIDA standard 80 | #define MTP_FORMAT_TIFF_EP 0x3802 // Tag Image File Format for Electronic Photography 81 | #define MTP_FORMAT_FLASHPIX 0x3803 // Structured Storage Image Format 82 | #define MTP_FORMAT_BMP 0x3804 // Microsoft Windows Bitmap file 83 | #define MTP_FORMAT_CIFF 0x3805 // Canon Camera Image File Format 84 | #define MTP_FORMAT_GIF 0x3807 // Graphics Interchange Format 85 | #define MTP_FORMAT_JFIF 0x3808 // JPEG File Interchange Format 86 | #define MTP_FORMAT_CD 0x3809 // PhotoCD Image Pac 87 | #define MTP_FORMAT_PICT 0x380A // Quickdraw Image Format 88 | #define MTP_FORMAT_PNG 0x380B // Portable Network Graphics 89 | #define MTP_FORMAT_TIFF 0x380D // Tag Image File Format 90 | #define MTP_FORMAT_TIFF_IT 0x380E // Tag Image File Format for Information Technology (graphic arts) 91 | #define MTP_FORMAT_JP2 0x380F // JPEG2000 Baseline File Format 92 | #define MTP_FORMAT_JPX 0x3810 // JPEG2000 Extended File Format 93 | #define MTP_FORMAT_UNDEFINED_FIRMWARE 0xB802 94 | #define MTP_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881 95 | #define MTP_FORMAT_UNDEFINED_AUDIO 0xB900 96 | #define MTP_FORMAT_WMA 0xB901 97 | #define MTP_FORMAT_OGG 0xB902 98 | #define MTP_FORMAT_AAC 0xB903 99 | #define MTP_FORMAT_AUDIBLE 0xB904 100 | #define MTP_FORMAT_FLAC 0xB906 101 | #define MTP_FORMAT_UNDEFINED_VIDEO 0xB980 102 | #define MTP_FORMAT_WMV 0xB981 103 | #define MTP_FORMAT_MP4_CONTAINER 0xB982 // ISO 14496-1 104 | #define MTP_FORMAT_MP2 0xB983 105 | #define MTP_FORMAT_3GP_CONTAINER 0xB984 // 3GPP file format. Details: http://www.3gpp.org/ftp/Specs/html-info/26244.htm (page title - \u201cTransparent end-to-end packet switched streaming service, 3GPP file format\u201d). 106 | #define MTP_FORMAT_UNDEFINED_COLLECTION 0xBA00 107 | #define MTP_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM 0xBA01 108 | #define MTP_FORMAT_ABSTRACT_IMAGE_ALBUM 0xBA02 109 | #define MTP_FORMAT_ABSTRACT_AUDIO_ALBUM 0xBA03 110 | #define MTP_FORMAT_ABSTRACT_VIDEO_ALBUM 0xBA04 111 | #define MTP_FORMAT_ABSTRACT_AV_PLAYLIST 0xBA05 112 | #define MTP_FORMAT_ABSTRACT_CONTACT_GROUP 0xBA06 113 | #define MTP_FORMAT_ABSTRACT_MESSAGE_FOLDER 0xBA07 114 | #define MTP_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION 0xBA08 115 | #define MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST 0xBA09 116 | #define MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST 0xBA0A 117 | #define MTP_FORMAT_ABSTRACT_MEDIACAST 0xBA0B // For use with mediacasts; references multimedia enclosures of RSS feeds or episodic content 118 | #define MTP_FORMAT_WPL_PLAYLIST 0xBA10 119 | #define MTP_FORMAT_M3U_PLAYLIST 0xBA11 120 | #define MTP_FORMAT_MPL_PLAYLIST 0xBA12 121 | #define MTP_FORMAT_ASX_PLAYLIST 0xBA13 122 | #define MTP_FORMAT_PLS_PLAYLIST 0xBA14 123 | #define MTP_FORMAT_UNDEFINED_DOCUMENT 0xBA80 124 | #define MTP_FORMAT_ABSTRACT_DOCUMENT 0xBA81 125 | #define MTP_FORMAT_XML_DOCUMENT 0xBA82 126 | #define MTP_FORMAT_MS_WORD_DOCUMENT 0xBA83 127 | #define MTP_FORMAT_MHT_COMPILED_HTML_DOCUMENT 0xBA84 128 | #define MTP_FORMAT_MS_EXCEL_SPREADSHEET 0xBA85 129 | #define MTP_FORMAT_MS_POWERPOINT_PRESENTATION 0xBA86 130 | #define MTP_FORMAT_UNDEFINED_MESSAGE 0xBB00 131 | #define MTP_FORMAT_ABSTRACT_MESSSAGE 0xBB01 132 | #define MTP_FORMAT_UNDEFINED_CONTACT 0xBB80 133 | #define MTP_FORMAT_ABSTRACT_CONTACT 0xBB81 134 | #define MTP_FORMAT_VCARD_2 0xBB82 135 | 136 | // MTP Object Property Codes 137 | #define MTP_PROPERTY_STORAGE_ID 0xDC01 138 | #define MTP_PROPERTY_OBJECT_FORMAT 0xDC02 139 | #define MTP_PROPERTY_PROTECTION_STATUS 0xDC03 140 | #define MTP_PROPERTY_OBJECT_SIZE 0xDC04 141 | #define MTP_PROPERTY_ASSOCIATION_TYPE 0xDC05 142 | #define MTP_PROPERTY_ASSOCIATION_DESC 0xDC06 143 | #define MTP_PROPERTY_OBJECT_FILE_NAME 0xDC07 144 | #define MTP_PROPERTY_DATE_CREATED 0xDC08 145 | #define MTP_PROPERTY_DATE_MODIFIED 0xDC09 146 | #define MTP_PROPERTY_KEYWORDS 0xDC0A 147 | #define MTP_PROPERTY_PARENT_OBJECT 0xDC0B 148 | #define MTP_PROPERTY_ALLOWED_FOLDER_CONTENTS 0xDC0C 149 | #define MTP_PROPERTY_HIDDEN 0xDC0D 150 | #define MTP_PROPERTY_SYSTEM_OBJECT 0xDC0E 151 | #define MTP_PROPERTY_PERSISTENT_UID 0xDC41 152 | #define MTP_PROPERTY_SYNC_ID 0xDC42 153 | #define MTP_PROPERTY_PROPERTY_BAG 0xDC43 154 | #define MTP_PROPERTY_NAME 0xDC44 155 | #define MTP_PROPERTY_CREATED_BY 0xDC45 156 | #define MTP_PROPERTY_ARTIST 0xDC46 157 | #define MTP_PROPERTY_DATE_AUTHORED 0xDC47 158 | #define MTP_PROPERTY_DESCRIPTION 0xDC48 159 | #define MTP_PROPERTY_URL_REFERENCE 0xDC49 160 | #define MTP_PROPERTY_LANGUAGE_LOCALE 0xDC4A 161 | #define MTP_PROPERTY_COPYRIGHT_INFORMATION 0xDC4B 162 | #define MTP_PROPERTY_SOURCE 0xDC4C 163 | #define MTP_PROPERTY_ORIGIN_LOCATION 0xDC4D 164 | #define MTP_PROPERTY_DATE_ADDED 0xDC4E 165 | #define MTP_PROPERTY_NON_CONSUMABLE 0xDC4F 166 | #define MTP_PROPERTY_CORRUPT_UNPLAYABLE 0xDC50 167 | #define MTP_PROPERTY_PRODUCER_SERIAL_NUMBER 0xDC51 168 | #define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81 169 | #define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_SIZE 0xDC82 170 | #define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83 171 | #define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84 172 | #define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DURATION 0xDC85 173 | #define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DATA 0xDC86 174 | #define MTP_PROPERTY_WIDTH 0xDC87 175 | #define MTP_PROPERTY_HEIGHT 0xDC88 176 | #define MTP_PROPERTY_DURATION 0xDC89 177 | #define MTP_PROPERTY_RATING 0xDC8A 178 | #define MTP_PROPERTY_TRACK 0xDC8B 179 | #define MTP_PROPERTY_GENRE 0xDC8C 180 | #define MTP_PROPERTY_CREDITS 0xDC8D 181 | #define MTP_PROPERTY_LYRICS 0xDC8E 182 | #define MTP_PROPERTY_SUBSCRIPTION_CONTENT_ID 0xDC8F 183 | #define MTP_PROPERTY_PRODUCED_BY 0xDC90 184 | #define MTP_PROPERTY_USE_COUNT 0xDC91 185 | #define MTP_PROPERTY_SKIP_COUNT 0xDC92 186 | #define MTP_PROPERTY_LAST_ACCESSED 0xDC93 187 | #define MTP_PROPERTY_PARENTAL_RATING 0xDC94 188 | #define MTP_PROPERTY_META_GENRE 0xDC95 189 | #define MTP_PROPERTY_COMPOSER 0xDC96 190 | #define MTP_PROPERTY_EFFECTIVE_RATING 0xDC97 191 | #define MTP_PROPERTY_SUBTITLE 0xDC98 192 | #define MTP_PROPERTY_ORIGINAL_RELEASE_DATE 0xDC99 193 | #define MTP_PROPERTY_ALBUM_NAME 0xDC9A 194 | #define MTP_PROPERTY_ALBUM_ARTIST 0xDC9B 195 | #define MTP_PROPERTY_MOOD 0xDC9C 196 | #define MTP_PROPERTY_DRM_STATUS 0xDC9D 197 | #define MTP_PROPERTY_SUB_DESCRIPTION 0xDC9E 198 | #define MTP_PROPERTY_IS_CROPPED 0xDCD1 199 | #define MTP_PROPERTY_IS_COLOUR_CORRECTED 0xDCD2 200 | #define MTP_PROPERTY_IMAGE_BIT_DEPTH 0xDCD3 201 | #define MTP_PROPERTY_F_NUMBER 0xDCD4 202 | #define MTP_PROPERTY_EXPOSURE_TIME 0xDCD5 203 | #define MTP_PROPERTY_EXPOSURE_INDEX 0xDCD6 204 | #define MTP_PROPERTY_TOTAL_BITRATE 0xDE91 205 | #define MTP_PROPERTY_BITRATE_TYPE 0xDE92 206 | #define MTP_PROPERTY_SAMPLE_RATE 0xDE93 207 | #define MTP_PROPERTY_NUMBER_OF_CHANNELS 0xDE94 208 | #define MTP_PROPERTY_AUDIO_BIT_DEPTH 0xDE95 209 | #define MTP_PROPERTY_SCAN_TYPE 0xDE97 210 | #define MTP_PROPERTY_AUDIO_WAVE_CODEC 0xDE99 211 | #define MTP_PROPERTY_AUDIO_BITRATE 0xDE9A 212 | #define MTP_PROPERTY_VIDEO_FOURCC_CODEC 0xDE9B 213 | #define MTP_PROPERTY_VIDEO_BITRATE 0xDE9C 214 | #define MTP_PROPERTY_FRAMES_PER_THOUSAND_SECONDS 0xDE9D 215 | #define MTP_PROPERTY_KEYFRAME_DISTANCE 0xDE9E 216 | #define MTP_PROPERTY_BUFFER_SIZE 0xDE9F 217 | #define MTP_PROPERTY_ENCODING_QUALITY 0xDEA0 218 | #define MTP_PROPERTY_ENCODING_PROFILE 0xDEA1 219 | #define MTP_PROPERTY_DISPLAY_NAME 0xDCE0 220 | #define MTP_PROPERTY_BODY_TEXT 0xDCE1 221 | #define MTP_PROPERTY_SUBJECT 0xDCE2 222 | #define MTP_PROPERTY_PRIORITY 0xDCE3 223 | #define MTP_PROPERTY_GIVEN_NAME 0xDD00 224 | #define MTP_PROPERTY_MIDDLE_NAMES 0xDD01 225 | #define MTP_PROPERTY_FAMILY_NAME 0xDD02 226 | #define MTP_PROPERTY_PREFIX 0xDD03 227 | #define MTP_PROPERTY_SUFFIX 0xDD04 228 | #define MTP_PROPERTY_PHONETIC_GIVEN_NAME 0xDD05 229 | #define MTP_PROPERTY_PHONETIC_FAMILY_NAME 0xDD06 230 | #define MTP_PROPERTY_EMAIL_PRIMARY 0xDD07 231 | #define MTP_PROPERTY_EMAIL_PERSONAL_1 0xDD08 232 | #define MTP_PROPERTY_EMAIL_PERSONAL_2 0xDD09 233 | #define MTP_PROPERTY_EMAIL_BUSINESS_1 0xDD0A 234 | #define MTP_PROPERTY_EMAIL_BUSINESS_2 0xDD0B 235 | #define MTP_PROPERTY_EMAIL_OTHERS 0xDD0C 236 | #define MTP_PROPERTY_PHONE_NUMBER_PRIMARY 0xDD0D 237 | #define MTP_PROPERTY_PHONE_NUMBER_PERSONAL 0xDD0E 238 | #define MTP_PROPERTY_PHONE_NUMBER_PERSONAL_2 0xDD0F 239 | #define MTP_PROPERTY_PHONE_NUMBER_BUSINESS 0xDD10 240 | #define MTP_PROPERTY_PHONE_NUMBER_BUSINESS_2 0xDD11 241 | #define MTP_PROPERTY_PHONE_NUMBER_MOBILE 0xDD12 242 | #define MTP_PROPERTY_PHONE_NUMBER_MOBILE_2 0xDD13 243 | #define MTP_PROPERTY_FAX_NUMBER_PRIMARY 0xDD14 244 | #define MTP_PROPERTY_FAX_NUMBER_PERSONAL 0xDD15 245 | #define MTP_PROPERTY_FAX_NUMBER_BUSINESS 0xDD16 246 | #define MTP_PROPERTY_PAGER_NUMBER 0xDD17 247 | #define MTP_PROPERTY_PHONE_NUMBER_OTHERS 0xDD18 248 | #define MTP_PROPERTY_PRIMARY_WEB_ADDRESS 0xDD19 249 | #define MTP_PROPERTY_PERSONAL_WEB_ADDRESS 0xDD1A 250 | #define MTP_PROPERTY_BUSINESS_WEB_ADDRESS 0xDD1B 251 | #define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS 0xDD1C 252 | #define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_2 0xDD1D 253 | #define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_3 0xDD1E 254 | #define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1F 255 | #define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20 256 | #define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21 257 | #define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22 258 | #define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23 259 | #define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24 260 | #define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25 261 | #define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26 262 | #define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27 263 | #define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28 264 | #define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29 265 | #define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2A 266 | #define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2B 267 | #define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2C 268 | #define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_FULL 0xDD2D 269 | #define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2E 270 | #define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2F 271 | #define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_CITY 0xDD30 272 | #define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_REGION 0xDD31 273 | #define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32 274 | #define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33 275 | #define MTP_PROPERTY_ORGANIZATION_NAME 0xDD34 276 | #define MTP_PROPERTY_PHONETIC_ORGANIZATION_NAME 0xDD35 277 | #define MTP_PROPERTY_ROLE 0xDD36 278 | #define MTP_PROPERTY_BIRTHDATE 0xDD37 279 | #define MTP_PROPERTY_MESSAGE_TO 0xDD40 280 | #define MTP_PROPERTY_MESSAGE_CC 0xDD41 281 | #define MTP_PROPERTY_MESSAGE_BCC 0xDD42 282 | #define MTP_PROPERTY_MESSAGE_READ 0xDD43 283 | #define MTP_PROPERTY_MESSAGE_RECEIVED_TIME 0xDD44 284 | #define MTP_PROPERTY_MESSAGE_SENDER 0xDD45 285 | #define MTP_PROPERTY_ACTIVITY_BEGIN_TIME 0xDD50 286 | #define MTP_PROPERTY_ACTIVITY_END_TIME 0xDD51 287 | #define MTP_PROPERTY_ACTIVITY_LOCATION 0xDD52 288 | #define MTP_PROPERTY_ACTIVITY_REQUIRED_ATTENDEES 0xDD54 289 | #define MTP_PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES 0xDD55 290 | #define MTP_PROPERTY_ACTIVITY_RESOURCES 0xDD56 291 | #define MTP_PROPERTY_ACTIVITY_ACCEPTED 0xDD57 292 | #define MTP_PROPERTY_ACTIVITY_TENTATIVE 0xDD58 293 | #define MTP_PROPERTY_ACTIVITY_DECLINED 0xDD59 294 | #define MTP_PROPERTY_ACTIVITY_REMAINDER_TIME 0xDD5A 295 | #define MTP_PROPERTY_ACTIVITY_OWNER 0xDD5B 296 | #define MTP_PROPERTY_ACTIVITY_STATUS 0xDD5C 297 | #define MTP_PROPERTY_OWNER 0xDD5D 298 | #define MTP_PROPERTY_EDITOR 0xDD5E 299 | #define MTP_PROPERTY_WEBMASTER 0xDD5F 300 | #define MTP_PROPERTY_URL_SOURCE 0xDD60 301 | #define MTP_PROPERTY_URL_DESTINATION 0xDD61 302 | #define MTP_PROPERTY_TIME_BOOKMARK 0xDD62 303 | #define MTP_PROPERTY_OBJECT_BOOKMARK 0xDD63 304 | #define MTP_PROPERTY_BYTE_BOOKMARK 0xDD64 305 | #define MTP_PROPERTY_LAST_BUILD_DATE 0xDD70 306 | #define MTP_PROPERTY_TIME_TO_LIVE 0xDD71 307 | #define MTP_PROPERTY_MEDIA_GUID 0xDD72 308 | 309 | // MTP Device Property Codes 310 | #define MTP_DEVICE_PROPERTY_UNDEFINED 0x5000 311 | #define MTP_DEVICE_PROPERTY_BATTERY_LEVEL 0x5001 312 | #define MTP_DEVICE_PROPERTY_FUNCTIONAL_MODE 0x5002 313 | #define MTP_DEVICE_PROPERTY_IMAGE_SIZE 0x5003 314 | #define MTP_DEVICE_PROPERTY_COMPRESSION_SETTING 0x5004 315 | #define MTP_DEVICE_PROPERTY_WHITE_BALANCE 0x5005 316 | #define MTP_DEVICE_PROPERTY_RGB_GAIN 0x5006 317 | #define MTP_DEVICE_PROPERTY_F_NUMBER 0x5007 318 | #define MTP_DEVICE_PROPERTY_FOCAL_LENGTH 0x5008 319 | #define MTP_DEVICE_PROPERTY_FOCUS_DISTANCE 0x5009 320 | #define MTP_DEVICE_PROPERTY_FOCUS_MODE 0x500A 321 | #define MTP_DEVICE_PROPERTY_EXPOSURE_METERING_MODE 0x500B 322 | #define MTP_DEVICE_PROPERTY_FLASH_MODE 0x500C 323 | #define MTP_DEVICE_PROPERTY_EXPOSURE_TIME 0x500D 324 | #define MTP_DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE 0x500E 325 | #define MTP_DEVICE_PROPERTY_EXPOSURE_INDEX 0x500F 326 | #define MTP_DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION 0x5010 327 | #define MTP_DEVICE_PROPERTY_DATETIME 0x5011 328 | #define MTP_DEVICE_PROPERTY_CAPTURE_DELAY 0x5012 329 | #define MTP_DEVICE_PROPERTY_STILL_CAPTURE_MODE 0x5013 330 | #define MTP_DEVICE_PROPERTY_CONTRAST 0x5014 331 | #define MTP_DEVICE_PROPERTY_SHARPNESS 0x5015 332 | #define MTP_DEVICE_PROPERTY_DIGITAL_ZOOM 0x5016 333 | #define MTP_DEVICE_PROPERTY_EFFECT_MODE 0x5017 334 | #define MTP_DEVICE_PROPERTY_BURST_NUMBER 0x5018 335 | #define MTP_DEVICE_PROPERTY_BURST_INTERVAL 0x5019 336 | #define MTP_DEVICE_PROPERTY_TIMELAPSE_NUMBER 0x501A 337 | #define MTP_DEVICE_PROPERTY_TIMELAPSE_INTERVAL 0x501B 338 | #define MTP_DEVICE_PROPERTY_FOCUS_METERING_MODE 0x501C 339 | #define MTP_DEVICE_PROPERTY_UPLOAD_URL 0x501D 340 | #define MTP_DEVICE_PROPERTY_ARTIST 0x501E 341 | #define MTP_DEVICE_PROPERTY_COPYRIGHT_INFO 0x501F 342 | #define MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER 0xD401 343 | #define MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME 0xD402 344 | #define MTP_DEVICE_PROPERTY_VOLUME 0xD403 345 | #define MTP_DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED 0xD404 346 | #define MTP_DEVICE_PROPERTY_DEVICE_ICON 0xD405 347 | #define MTP_DEVICE_PROPERTY_PLAYBACK_RATE 0xD410 348 | #define MTP_DEVICE_PROPERTY_PLAYBACK_OBJECT 0xD411 349 | #define MTP_DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX 0xD412 350 | #define MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO 0xD406 351 | #define MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE 0xD407 352 | 353 | // MTP Operation Codes 354 | #define MTP_OPERATION_GET_DEVICE_INFO 0x1001 355 | #define MTP_OPERATION_OPEN_SESSION 0x1002 356 | #define MTP_OPERATION_CLOSE_SESSION 0x1003 357 | #define MTP_OPERATION_GET_STORAGE_IDS 0x1004 358 | #define MTP_OPERATION_GET_STORAGE_INFO 0x1005 359 | #define MTP_OPERATION_GET_NUM_OBJECTS 0x1006 360 | #define MTP_OPERATION_GET_OBJECT_HANDLES 0x1007 361 | #define MTP_OPERATION_GET_OBJECT_INFO 0x1008 362 | #define MTP_OPERATION_GET_OBJECT 0x1009 363 | #define MTP_OPERATION_GET_THUMB 0x100A 364 | #define MTP_OPERATION_DELETE_OBJECT 0x100B 365 | #define MTP_OPERATION_SEND_OBJECT_INFO 0x100C 366 | #define MTP_OPERATION_SEND_OBJECT 0x100D 367 | #define MTP_OPERATION_INITIATE_CAPTURE 0x100E 368 | #define MTP_OPERATION_FORMAT_STORE 0x100F 369 | #define MTP_OPERATION_RESET_DEVICE 0x1010 370 | #define MTP_OPERATION_SELF_TEST 0x1011 371 | #define MTP_OPERATION_SET_OBJECT_PROTECTION 0x1012 372 | #define MTP_OPERATION_POWER_DOWN 0x1013 373 | #define MTP_OPERATION_GET_DEVICE_PROP_DESC 0x1014 374 | #define MTP_OPERATION_GET_DEVICE_PROP_VALUE 0x1015 375 | #define MTP_OPERATION_SET_DEVICE_PROP_VALUE 0x1016 376 | #define MTP_OPERATION_RESET_DEVICE_PROP_VALUE 0x1017 377 | #define MTP_OPERATION_TERMINATE_OPEN_CAPTURE 0x1018 378 | #define MTP_OPERATION_MOVE_OBJECT 0x1019 379 | #define MTP_OPERATION_COPY_OBJECT 0x101A 380 | #define MTP_OPERATION_GET_PARTIAL_OBJECT 0x101B 381 | #define MTP_OPERATION_INITIATE_OPEN_CAPTURE 0x101C 382 | #define MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED 0x9801 383 | #define MTP_OPERATION_GET_OBJECT_PROP_DESC 0x9802 384 | #define MTP_OPERATION_GET_OBJECT_PROP_VALUE 0x9803 385 | #define MTP_OPERATION_SET_OBJECT_PROP_VALUE 0x9804 386 | #define MTP_OPERATION_GET_OBJECT_PROP_LIST 0x9805 387 | #define MTP_OPERATION_SET_OBJECT_PROP_LIST 0x9806 388 | #define MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC 0x9807 389 | #define MTP_OPERATION_SEND_OBJECT_PROP_LIST 0x9808 390 | #define MTP_OPERATION_GET_OBJECT_REFERENCES 0x9810 391 | #define MTP_OPERATION_SET_OBJECT_REFERENCES 0x9811 392 | #define MTP_OPERATION_SKIP 0x9820 393 | 394 | // Android extensions for direct file IO 395 | 396 | // Same as GetPartialObject, but with 64 bit offset 397 | #define MTP_OPERATION_GET_PARTIAL_OBJECT_64 0x95C1 398 | // Same as GetPartialObject64, but copying host to device 399 | #define MTP_OPERATION_SEND_PARTIAL_OBJECT 0x95C2 400 | // Truncates file to 64 bit length 401 | #define MTP_OPERATION_TRUNCATE_OBJECT 0x95C3 402 | // Must be called before using SendPartialObject and TruncateObject 403 | #define MTP_OPERATION_BEGIN_EDIT_OBJECT 0x95C4 404 | // Called to commit changes made by SendPartialObject and TruncateObject 405 | #define MTP_OPERATION_END_EDIT_OBJECT 0x95C5 406 | 407 | // MTP Response Codes 408 | #define MTP_RESPONSE_UNDEFINED 0x2000 409 | #define MTP_RESPONSE_OK 0x2001 410 | #define MTP_RESPONSE_GENERAL_ERROR 0x2002 411 | #define MTP_RESPONSE_SESSION_NOT_OPEN 0x2003 412 | #define MTP_RESPONSE_INVALID_TRANSACTION_ID 0x2004 413 | #define MTP_RESPONSE_OPERATION_NOT_SUPPORTED 0x2005 414 | #define MTP_RESPONSE_PARAMETER_NOT_SUPPORTED 0x2006 415 | #define MTP_RESPONSE_INCOMPLETE_TRANSFER 0x2007 416 | #define MTP_RESPONSE_INVALID_STORAGE_ID 0x2008 417 | #define MTP_RESPONSE_INVALID_OBJECT_HANDLE 0x2009 418 | #define MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED 0x200A 419 | #define MTP_RESPONSE_INVALID_OBJECT_FORMAT_CODE 0x200B 420 | #define MTP_RESPONSE_STORAGE_FULL 0x200C 421 | #define MTP_RESPONSE_OBJECT_WRITE_PROTECTED 0x200D 422 | #define MTP_RESPONSE_STORE_READ_ONLY 0x200E 423 | #define MTP_RESPONSE_ACCESS_DENIED 0x200F 424 | #define MTP_RESPONSE_NO_THUMBNAIL_PRESENT 0x2010 425 | #define MTP_RESPONSE_SELF_TEST_FAILED 0x2011 426 | #define MTP_RESPONSE_PARTIAL_DELETION 0x2012 427 | #define MTP_RESPONSE_STORE_NOT_AVAILABLE 0x2013 428 | #define MTP_RESPONSE_SPECIFICATION_BY_FORMAT_UNSUPPORTED 0x2014 429 | #define MTP_RESPONSE_NO_VALID_OBJECT_INFO 0x2015 430 | #define MTP_RESPONSE_INVALID_CODE_FORMAT 0x2016 431 | #define MTP_RESPONSE_UNKNOWN_VENDOR_CODE 0x2017 432 | #define MTP_RESPONSE_CAPTURE_ALREADY_TERMINATED 0x2018 433 | #define MTP_RESPONSE_DEVICE_BUSY 0x2019 434 | #define MTP_RESPONSE_INVALID_PARENT_OBJECT 0x201A 435 | #define MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT 0x201B 436 | #define MTP_RESPONSE_INVALID_DEVICE_PROP_VALUE 0x201C 437 | #define MTP_RESPONSE_INVALID_PARAMETER 0x201D 438 | #define MTP_RESPONSE_SESSION_ALREADY_OPEN 0x201E 439 | #define MTP_RESPONSE_TRANSACTION_CANCELLED 0x201F 440 | #define MTP_RESPONSE_SPECIFICATION_OF_DESTINATION_UNSUPPORTED 0x2020 441 | #define MTP_RESPONSE_INVALID_OBJECT_PROP_CODE 0xA801 442 | #define MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT 0xA802 443 | #define MTP_RESPONSE_INVALID_OBJECT_PROP_VALUE 0xA803 444 | #define MTP_RESPONSE_INVALID_OBJECT_REFERENCE 0xA804 445 | #define MTP_RESPONSE_GROUP_NOT_SUPPORTED 0xA805 446 | #define MTP_RESPONSE_INVALID_DATASET 0xA806 447 | #define MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807 448 | #define MTP_RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED 0xA808 449 | #define MTP_RESPONSE_OBJECT_TOO_LARGE 0xA809 450 | #define MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED 0xA80A 451 | 452 | // MTP Event Codes 453 | #define MTP_EVENT_UNDEFINED 0x4000 454 | #define MTP_EVENT_CANCEL_TRANSACTION 0x4001 455 | #define MTP_EVENT_OBJECT_ADDED 0x4002 456 | #define MTP_EVENT_OBJECT_REMOVED 0x4003 457 | #define MTP_EVENT_STORE_ADDED 0x4004 458 | #define MTP_EVENT_STORE_REMOVED 0x4005 459 | #define MTP_EVENT_DEVICE_PROP_CHANGED 0x4006 460 | #define MTP_EVENT_OBJECT_INFO_CHANGED 0x4007 461 | #define MTP_EVENT_DEVICE_INFO_CHANGED 0x4008 462 | #define MTP_EVENT_REQUEST_OBJECT_TRANSFER 0x4009 463 | #define MTP_EVENT_STORE_FULL 0x400A 464 | #define MTP_EVENT_DEVICE_RESET 0x400B 465 | #define MTP_EVENT_STORAGE_INFO_CHANGED 0x400C 466 | #define MTP_EVENT_CAPTURE_COMPLETE 0x400D 467 | #define MTP_EVENT_UNREPORTED_STATUS 0x400E 468 | #define MTP_EVENT_OBJECT_PROP_CHANGED 0xC801 469 | #define MTP_EVENT_OBJECT_PROP_DESC_CHANGED 0xC802 470 | #define MTP_EVENT_OBJECT_REFERENCES_CHANGED 0xC803 471 | 472 | // Storage Type 473 | #define MTP_STORAGE_FIXED_ROM 0x0001 474 | #define MTP_STORAGE_REMOVABLE_ROM 0x0002 475 | #define MTP_STORAGE_FIXED_RAM 0x0003 476 | #define MTP_STORAGE_REMOVABLE_RAM 0x0004 477 | 478 | // Storage File System 479 | #define MTP_STORAGE_FILESYSTEM_FLAT 0x0001 480 | #define MTP_STORAGE_FILESYSTEM_HIERARCHICAL 0x0002 481 | #define MTP_STORAGE_FILESYSTEM_DCF 0x0003 482 | 483 | // Storage Access Capability 484 | #define MTP_STORAGE_READ_WRITE 0x0000 485 | #define MTP_STORAGE_READ_ONLY_WITHOUT_DELETE 0x0001 486 | #define MTP_STORAGE_READ_ONLY_WITH_DELETE 0x0002 487 | 488 | // Association Type 489 | #define MTP_ASSOCIATION_TYPE_UNDEFINED 0x0000 490 | #define MTP_ASSOCIATION_TYPE_GENERIC_FOLDER 0x0001 491 | 492 | #endif // _MTP_H 493 | --------------------------------------------------------------------------------