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 
writeDescriptors(int fd,bool ptp)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