1 /* 2 * Copyright (C) 2017 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 <android-base/logging.h> 18 #include <sys/types.h> 19 20 #include "MtpDescriptors.h" 21 22 namespace android { 23 24 const struct usb_interface_descriptor mtp_interface_desc = { 25 .bLength = USB_DT_INTERFACE_SIZE, 26 .bDescriptorType = USB_DT_INTERFACE, 27 .bInterfaceNumber = 0, 28 .bNumEndpoints = 3, 29 .bInterfaceClass = USB_CLASS_STILL_IMAGE, 30 .bInterfaceSubClass = 1, 31 .bInterfaceProtocol = 1, 32 .iInterface = 1, 33 }; 34 35 const struct usb_interface_descriptor ptp_interface_desc = { 36 .bLength = USB_DT_INTERFACE_SIZE, 37 .bDescriptorType = USB_DT_INTERFACE, 38 .bInterfaceNumber = 0, 39 .bNumEndpoints = 3, 40 .bInterfaceClass = USB_CLASS_STILL_IMAGE, 41 .bInterfaceSubClass = 1, 42 .bInterfaceProtocol = 1, 43 }; 44 45 const struct usb_endpoint_descriptor_no_audio fs_sink = { 46 .bLength = USB_DT_ENDPOINT_SIZE, 47 .bDescriptorType = USB_DT_ENDPOINT, 48 .bEndpointAddress = 1 | USB_DIR_IN, 49 .bmAttributes = USB_ENDPOINT_XFER_BULK, 50 .wMaxPacketSize = MAX_PACKET_SIZE_FS, 51 }; 52 53 const struct usb_endpoint_descriptor_no_audio fs_source = { 54 .bLength = USB_DT_ENDPOINT_SIZE, 55 .bDescriptorType = USB_DT_ENDPOINT, 56 .bEndpointAddress = 2 | USB_DIR_OUT, 57 .bmAttributes = USB_ENDPOINT_XFER_BULK, 58 .wMaxPacketSize = MAX_PACKET_SIZE_FS, 59 }; 60 61 const struct usb_endpoint_descriptor_no_audio intr = { 62 .bLength = USB_DT_ENDPOINT_SIZE, 63 .bDescriptorType = USB_DT_ENDPOINT, 64 .bEndpointAddress = 3 | USB_DIR_IN, 65 .bmAttributes = USB_ENDPOINT_XFER_INT, 66 .wMaxPacketSize = MAX_PACKET_SIZE_EV, 67 .bInterval = 6, 68 }; 69 70 const struct usb_endpoint_descriptor_no_audio hs_sink = { 71 .bLength = USB_DT_ENDPOINT_SIZE, 72 .bDescriptorType = USB_DT_ENDPOINT, 73 .bEndpointAddress = 1 | USB_DIR_IN, 74 .bmAttributes = USB_ENDPOINT_XFER_BULK, 75 .wMaxPacketSize = MAX_PACKET_SIZE_HS, 76 }; 77 78 const struct usb_endpoint_descriptor_no_audio hs_source = { 79 .bLength = USB_DT_ENDPOINT_SIZE, 80 .bDescriptorType = USB_DT_ENDPOINT, 81 .bEndpointAddress = 2 | USB_DIR_OUT, 82 .bmAttributes = USB_ENDPOINT_XFER_BULK, 83 .wMaxPacketSize = MAX_PACKET_SIZE_HS, 84 }; 85 86 const struct usb_endpoint_descriptor_no_audio ss_sink = { 87 .bLength = USB_DT_ENDPOINT_SIZE, 88 .bDescriptorType = USB_DT_ENDPOINT, 89 .bEndpointAddress = 1 | USB_DIR_IN, 90 .bmAttributes = USB_ENDPOINT_XFER_BULK, 91 .wMaxPacketSize = MAX_PACKET_SIZE_SS, 92 }; 93 94 const struct usb_endpoint_descriptor_no_audio ss_source = { 95 .bLength = USB_DT_ENDPOINT_SIZE, 96 .bDescriptorType = USB_DT_ENDPOINT, 97 .bEndpointAddress = 2 | USB_DIR_OUT, 98 .bmAttributes = USB_ENDPOINT_XFER_BULK, 99 .wMaxPacketSize = MAX_PACKET_SIZE_SS, 100 }; 101 102 const struct usb_ss_ep_comp_descriptor ss_sink_comp = { 103 .bLength = sizeof(ss_sink_comp), 104 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 105 .bMaxBurst = 6, 106 }; 107 108 const struct usb_ss_ep_comp_descriptor ss_source_comp = { 109 .bLength = sizeof(ss_source_comp), 110 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 111 .bMaxBurst = 6, 112 }; 113 114 const struct usb_ss_ep_comp_descriptor ss_intr_comp = { 115 .bLength = sizeof(ss_intr_comp), 116 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 117 }; 118 119 const struct func_desc mtp_fs_descriptors = { 120 .intf = mtp_interface_desc, 121 .sink = fs_sink, 122 .source = fs_source, 123 .intr = intr, 124 }; 125 126 const struct func_desc mtp_hs_descriptors = { 127 .intf = mtp_interface_desc, 128 .sink = hs_sink, 129 .source = hs_source, 130 .intr = intr, 131 }; 132 133 const struct ss_func_desc mtp_ss_descriptors = { 134 .intf = mtp_interface_desc, 135 .sink = ss_sink, 136 .sink_comp = ss_sink_comp, 137 .source = ss_source, 138 .source_comp = ss_source_comp, 139 .intr = intr, 140 .intr_comp = ss_intr_comp, 141 }; 142 143 const struct func_desc ptp_fs_descriptors = { 144 .intf = ptp_interface_desc, 145 .sink = fs_sink, 146 .source = fs_source, 147 .intr = intr, 148 }; 149 150 const struct func_desc ptp_hs_descriptors = { 151 .intf = ptp_interface_desc, 152 .sink = hs_sink, 153 .source = hs_source, 154 .intr = intr, 155 }; 156 157 const struct ss_func_desc ptp_ss_descriptors = { 158 .intf = ptp_interface_desc, 159 .sink = ss_sink, 160 .sink_comp = ss_sink_comp, 161 .source = ss_source, 162 .source_comp = ss_source_comp, 163 .intr = intr, 164 .intr_comp = ss_intr_comp, 165 }; 166 167 const struct functionfs_strings mtp_strings = { 168 .header = { 169 .magic = htole32(FUNCTIONFS_STRINGS_MAGIC), 170 .length = htole32(sizeof(mtp_strings)), 171 .str_count = htole32(1), 172 .lang_count = htole32(1), 173 }, 174 .lang0 = { 175 .code = htole16(0x0409), 176 .str1 = STR_INTERFACE, 177 }, 178 }; 179 180 const struct usb_os_desc_header mtp_os_desc_header = { 181 .interface = htole32(1), 182 .dwLength = htole32(sizeof(usb_os_desc_header) + sizeof(usb_ext_compat_desc)), 183 .bcdVersion = htole16(1), 184 .wIndex = htole16(4), 185 .bCount = htole16(1), 186 .Reserved = htole16(0), 187 }; 188 189 const struct usb_ext_compat_desc mtp_os_desc_compat = { 190 .bFirstInterfaceNumber = 0, 191 .Reserved1 = htole32(1), 192 .CompatibleID = { 'M', 'T', 'P' }, 193 .SubCompatibleID = {0}, 194 .Reserved2 = {0}, 195 }; 196 197 const struct usb_ext_compat_desc ptp_os_desc_compat = { 198 .bFirstInterfaceNumber = 0, 199 .Reserved1 = htole32(1), 200 .CompatibleID = { 'P', 'T', 'P' }, 201 .SubCompatibleID = {0}, 202 .Reserved2 = {0}, 203 }; 204 205 const struct desc_v2 mtp_desc_v2 = { 206 .header = { 207 .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), 208 .length = htole32(sizeof(struct desc_v2)), 209 .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | 210 FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC, 211 }, 212 .fs_count = 4, 213 .hs_count = 4, 214 .ss_count = 7, 215 .os_count = 1, 216 .fs_descs = mtp_fs_descriptors, 217 .hs_descs = mtp_hs_descriptors, 218 .ss_descs = mtp_ss_descriptors, 219 .os_header = mtp_os_desc_header, 220 .os_desc = mtp_os_desc_compat, 221 }; 222 223 const struct desc_v2 ptp_desc_v2 = { 224 .header = { 225 .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), 226 .length = htole32(sizeof(struct desc_v2)), 227 .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | 228 FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC, 229 }, 230 .fs_count = 4, 231 .hs_count = 4, 232 .ss_count = 7, 233 .os_count = 1, 234 .fs_descs = ptp_fs_descriptors, 235 .hs_descs = ptp_hs_descriptors, 236 .ss_descs = ptp_ss_descriptors, 237 .os_header = mtp_os_desc_header, 238 .os_desc = ptp_os_desc_compat, 239 }; 240 241 const struct desc_v1 mtp_desc_v1 = { 242 .header = { 243 .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC), 244 .length = htole32(sizeof(struct desc_v1)), 245 .fs_count = 4, 246 .hs_count = 4, 247 }, 248 .fs_descs = mtp_fs_descriptors, 249 .hs_descs = mtp_hs_descriptors, 250 }; 251 252 const struct desc_v1 ptp_desc_v1 = { 253 .header = { 254 .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC), 255 .length = htole32(sizeof(struct desc_v1)), 256 .fs_count = 4, 257 .hs_count = 4, 258 }, 259 .fs_descs = ptp_fs_descriptors, 260 .hs_descs = ptp_hs_descriptors, 261 }; 262 263 bool writeDescriptors(int fd, bool ptp) { 264 ssize_t ret = TEMP_FAILURE_RETRY(write(fd, 265 &(ptp ? ptp_desc_v2 : mtp_desc_v2), sizeof(desc_v2))); 266 if (ret < 0) { 267 PLOG(ERROR) << fd << "Switching to V1 descriptor format"; 268 ret = TEMP_FAILURE_RETRY(write(fd, 269 &(ptp ? ptp_desc_v1 : mtp_desc_v1), sizeof(desc_v1))); 270 if (ret < 0) { 271 PLOG(ERROR) << fd << "Writing descriptors failed"; 272 return false; 273 } 274 } 275 ret = TEMP_FAILURE_RETRY(write(fd, &mtp_strings, sizeof(mtp_strings))); 276 if (ret < 0) { 277 PLOG(ERROR) << fd << "Writing strings failed"; 278 return false; 279 } 280 return true; 281 } 282 283 }; // namespace android 284