MtpDescriptors.cpp 8.0 KB

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