blob: 54306a9978d680f199aa9604bdf4dc70cded8769 [file] [log] [blame]
bigbiff bigbiffaf32bb92018-12-18 18:39:53 -05001/*
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#include <cutils/properties.h>
20
21#include "MtpDescriptors.h"
22#include "MtpDebug.h"
23
24const 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
35const 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
45const 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
53const 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
61const 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
70const 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
78const 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
86const 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
94const 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
102const 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
108const 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
114const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
115 .bLength = sizeof(ss_intr_comp),
116 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
117};
118
119const struct func_desc mtp_fs_descriptors = {
120 .intf = mtp_interface_desc,
121 .sink = fs_sink,
122 .source = fs_source,
123 .intr = intr,
124};
125
126const struct func_desc mtp_hs_descriptors = {
127 .intf = mtp_interface_desc,
128 .sink = hs_sink,
129 .source = hs_source,
130 .intr = intr,
131};
132
133const 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
143const struct func_desc ptp_fs_descriptors = {
144 .intf = ptp_interface_desc,
145 .sink = fs_sink,
146 .source = fs_source,
147 .intr = intr,
148};
149
150const struct func_desc ptp_hs_descriptors = {
151 .intf = ptp_interface_desc,
152 .sink = hs_sink,
153 .source = hs_source,
154 .intr = intr,
155};
156
157const 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
167const 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
180const 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
189const 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
197const 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
205const 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
223const 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
241const 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
252const 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
263bool 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 MTPE("Switching to V1 descriptor format\n");
268 ret = TEMP_FAILURE_RETRY(write(fd,
269 &(ptp ? ptp_desc_v1 : mtp_desc_v1), sizeof(desc_v1)));
270 if (ret < 0) {
271 MTPE("Writing descriptors failed\n");
272 return false;
273 }
274 }
275 ret = TEMP_FAILURE_RETRY(write(fd, &mtp_strings, sizeof(mtp_strings)));
276 if (ret < 0) {
277 MTPE("Writing strings failed\n");
278 return false;
279 }
280 property_set("sys.usb.ffs.mtp.ready", "1");
281 return true;
282}