diff options
Diffstat (limited to 'mtp/ffs/MtpDescriptors.cpp')
-rw-r--r-- | mtp/ffs/MtpDescriptors.cpp | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/mtp/ffs/MtpDescriptors.cpp b/mtp/ffs/MtpDescriptors.cpp new file mode 100644 index 000000000..54306a997 --- /dev/null +++ b/mtp/ffs/MtpDescriptors.cpp @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> +#include <sys/types.h> +#include <cutils/properties.h> + +#include "MtpDescriptors.h" +#include "MtpDebug.h" + +const struct usb_interface_descriptor mtp_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 3, + .bInterfaceClass = USB_CLASS_STILL_IMAGE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 1, +}; + +const struct usb_interface_descriptor ptp_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 3, + .bInterfaceClass = USB_CLASS_STILL_IMAGE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, +}; + +const struct usb_endpoint_descriptor_no_audio fs_sink = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_FS, +}; + +const struct usb_endpoint_descriptor_no_audio fs_source = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_FS, +}; + +const struct usb_endpoint_descriptor_no_audio intr = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 3 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = MAX_PACKET_SIZE_EV, + .bInterval = 6, +}; + +const struct usb_endpoint_descriptor_no_audio hs_sink = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_HS, +}; + +const struct usb_endpoint_descriptor_no_audio hs_source = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_HS, +}; + +const struct usb_endpoint_descriptor_no_audio ss_sink = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_SS, +}; + +const struct usb_endpoint_descriptor_no_audio ss_source = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_SS, +}; + +const struct usb_ss_ep_comp_descriptor ss_sink_comp = { + .bLength = sizeof(ss_sink_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 6, +}; + +const struct usb_ss_ep_comp_descriptor ss_source_comp = { + .bLength = sizeof(ss_source_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 6, +}; + +const struct usb_ss_ep_comp_descriptor ss_intr_comp = { + .bLength = sizeof(ss_intr_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, +}; + +const struct func_desc mtp_fs_descriptors = { + .intf = mtp_interface_desc, + .sink = fs_sink, + .source = fs_source, + .intr = intr, +}; + +const struct func_desc mtp_hs_descriptors = { + .intf = mtp_interface_desc, + .sink = hs_sink, + .source = hs_source, + .intr = intr, +}; + +const struct ss_func_desc mtp_ss_descriptors = { + .intf = mtp_interface_desc, + .sink = ss_sink, + .sink_comp = ss_sink_comp, + .source = ss_source, + .source_comp = ss_source_comp, + .intr = intr, + .intr_comp = ss_intr_comp, +}; + +const struct func_desc ptp_fs_descriptors = { + .intf = ptp_interface_desc, + .sink = fs_sink, + .source = fs_source, + .intr = intr, +}; + +const struct func_desc ptp_hs_descriptors = { + .intf = ptp_interface_desc, + .sink = hs_sink, + .source = hs_source, + .intr = intr, +}; + +const struct ss_func_desc ptp_ss_descriptors = { + .intf = ptp_interface_desc, + .sink = ss_sink, + .sink_comp = ss_sink_comp, + .source = ss_source, + .source_comp = ss_source_comp, + .intr = intr, + .intr_comp = ss_intr_comp, +}; + +const struct functionfs_strings mtp_strings = { + .header = { + .magic = htole32(FUNCTIONFS_STRINGS_MAGIC), + .length = htole32(sizeof(mtp_strings)), + .str_count = htole32(1), + .lang_count = htole32(1), + }, + .lang0 = { + .code = htole16(0x0409), + .str1 = STR_INTERFACE, + }, +}; + +const struct usb_os_desc_header mtp_os_desc_header = { + .interface = htole32(1), + .dwLength = htole32(sizeof(usb_os_desc_header) + sizeof(usb_ext_compat_desc)), + .bcdVersion = htole16(1), + .wIndex = htole16(4), + .bCount = htole16(1), + .Reserved = htole16(0), +}; + +const struct usb_ext_compat_desc mtp_os_desc_compat = { + .bFirstInterfaceNumber = 0, + .Reserved1 = htole32(1), + .CompatibleID = { 'M', 'T', 'P' }, + .SubCompatibleID = {0}, + .Reserved2 = {0}, +}; + +const struct usb_ext_compat_desc ptp_os_desc_compat = { + .bFirstInterfaceNumber = 0, + .Reserved1 = htole32(1), + .CompatibleID = { 'P', 'T', 'P' }, + .SubCompatibleID = {0}, + .Reserved2 = {0}, +}; + +const struct desc_v2 mtp_desc_v2 = { + .header = { + .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), + .length = htole32(sizeof(struct desc_v2)), + .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | + FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC, + }, + .fs_count = 4, + .hs_count = 4, + .ss_count = 7, + .os_count = 1, + .fs_descs = mtp_fs_descriptors, + .hs_descs = mtp_hs_descriptors, + .ss_descs = mtp_ss_descriptors, + .os_header = mtp_os_desc_header, + .os_desc = mtp_os_desc_compat, +}; + +const struct desc_v2 ptp_desc_v2 = { + .header = { + .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), + .length = htole32(sizeof(struct desc_v2)), + .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | + FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC, + }, + .fs_count = 4, + .hs_count = 4, + .ss_count = 7, + .os_count = 1, + .fs_descs = ptp_fs_descriptors, + .hs_descs = ptp_hs_descriptors, + .ss_descs = ptp_ss_descriptors, + .os_header = mtp_os_desc_header, + .os_desc = ptp_os_desc_compat, +}; + +const struct desc_v1 mtp_desc_v1 = { + .header = { + .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC), + .length = htole32(sizeof(struct desc_v1)), + .fs_count = 4, + .hs_count = 4, + }, + .fs_descs = mtp_fs_descriptors, + .hs_descs = mtp_hs_descriptors, +}; + +const struct desc_v1 ptp_desc_v1 = { + .header = { + .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC), + .length = htole32(sizeof(struct desc_v1)), + .fs_count = 4, + .hs_count = 4, + }, + .fs_descs = ptp_fs_descriptors, + .hs_descs = ptp_hs_descriptors, +}; + +bool writeDescriptors(int fd, bool ptp) { + ssize_t ret = TEMP_FAILURE_RETRY(write(fd, + &(ptp ? ptp_desc_v2 : mtp_desc_v2), sizeof(desc_v2))); + if (ret < 0) { + MTPE("Switching to V1 descriptor format\n"); + ret = TEMP_FAILURE_RETRY(write(fd, + &(ptp ? ptp_desc_v1 : mtp_desc_v1), sizeof(desc_v1))); + if (ret < 0) { + MTPE("Writing descriptors failed\n"); + return false; + } + } + ret = TEMP_FAILURE_RETRY(write(fd, &mtp_strings, sizeof(mtp_strings))); + if (ret < 0) { + MTPE("Writing strings failed\n"); + return false; + } + property_set("sys.usb.ffs.mtp.ready", "1"); + return true; +} |