1 /* 2 * Copyright (C) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef HDC_USBFFS2_H 16 #define HDC_USBFFS2_H 17 // clang-format off 18 #include <linux/usb/functionfs.h> 19 // clang-format on 20 #include <endian.h> 21 22 namespace Hdc { 23 constexpr auto HDC_USBDR_SND = 0x0; 24 constexpr auto HDC_USBDR_RCV = 0x80; 25 constexpr auto HDC_USBMD_BLK = 0X02; 26 constexpr auto HDC_USBMD_RCV = 0X03; 27 constexpr auto HDC_CLASS = 0xff; 28 constexpr auto HDC_SUBCLASS = 0x50; 29 constexpr auto HDC_FSPKT_SIZE_MAX = 64; 30 constexpr auto HDC_HSPKT_SIZE_MAX = 512; 31 constexpr uint16_t HDC_SSPKT_SIZE_MAX = 1024; 32 constexpr auto USB_FFS_BASE = "/dev/usb-ffs/"; 33 constexpr auto HDC_USBTF_DEV = 0x01; 34 constexpr auto HDC_USBTF_CFG = 0x02; 35 constexpr auto HDC_USBTF_STR = 0x03; 36 constexpr auto HDC_USBTF_ITF = 0x04; 37 constexpr auto HDC_USBTF_EPS = 0x05; 38 constexpr auto PROPERTY_NAME_LENGTH = 20; 39 constexpr auto PROPERTY_DATA_LENGTH = 39; 40 constexpr uint16_t VER_PROTOCOL = 0x01; 41 42 #define SHORT_LE(x) htole16(x) 43 #define LONG_LE(x) htole32(x) 44 #define HDC_INTERFACE_NAME "HDC Interface" 45 46 struct UsbFunctionDesc { 47 struct usb_interface_descriptor ifDesc; 48 struct usb_endpoint_descriptor_no_audio from; 49 struct usb_endpoint_descriptor_no_audio to; 50 } __attribute__((packed)); 51 52 static const struct { 53 struct usb_functionfs_strings_head head; 54 struct { 55 __le16 code; 56 const char name[sizeof(HDC_INTERFACE_NAME)]; 57 } __attribute__((packed)) firstItem; 58 } __attribute__((packed)) USB_FFS_VALUE = { 59 .head = 60 { 61 .magic = LONG_LE(FUNCTIONFS_STRINGS_MAGIC), 62 .length = LONG_LE(sizeof(USB_FFS_VALUE)), 63 .str_count = LONG_LE(1), 64 .lang_count = LONG_LE(1), 65 }, 66 .firstItem = 67 { 68 SHORT_LE(0x0409), 69 HDC_INTERFACE_NAME, 70 }, 71 }; 72 73 struct UsbFunctionfsDescsHeadOld { 74 __le32 magic; 75 __le32 length; 76 __le32 config1Count; 77 __le32 config2Count; 78 } __attribute__((packed)); 79 80 struct UsbFuncConfig { 81 struct usb_interface_descriptor ifDesc; 82 struct usb_endpoint_descriptor_no_audio from; 83 struct usb_ss_ep_comp_descriptor pairFrom; 84 struct usb_endpoint_descriptor_no_audio to; 85 struct usb_ss_ep_comp_descriptor pairTo; 86 } __attribute__((packed)); 87 88 static struct UsbFuncConfig config3 = { 89 .ifDesc = { 90 .bLength = sizeof(config3.ifDesc), 91 .bDescriptorType = USB_DT_INTERFACE, 92 .bInterfaceNumber = 0, 93 .bNumEndpoints = 2, 94 .bInterfaceClass = HDC_CLASS, 95 .bInterfaceSubClass = HDC_SUBCLASS, 96 .bInterfaceProtocol = VER_PROTOCOL, 97 .iInterface = 1 98 }, 99 .from = { 100 .bLength = sizeof(config3.from), 101 .bDescriptorType = USB_DT_ENDPOINT, 102 .bEndpointAddress = 1 | USB_DIR_OUT, 103 .bmAttributes = USB_ENDPOINT_XFER_BULK, 104 .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, 105 }, 106 .pairFrom = { 107 .bLength = sizeof(config3.pairFrom), 108 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 109 .bMaxBurst = 4, 110 }, 111 .to = { 112 .bLength = sizeof(config3.to), 113 .bDescriptorType = USB_DT_ENDPOINT, 114 .bEndpointAddress = 2 | USB_DIR_IN, 115 .bmAttributes = USB_ENDPOINT_XFER_BULK, 116 .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, 117 }, 118 .pairTo = { 119 .bLength = sizeof(config3.pairTo), 120 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 121 .bMaxBurst = 4, 122 }, 123 }; 124 125 static struct UsbFunctionDesc config1 = { 126 .ifDesc = { 127 .bLength = sizeof(config1.ifDesc), 128 .bDescriptorType = USB_DT_INTERFACE, 129 .bInterfaceNumber = 0, 130 .bNumEndpoints = 2, 131 .bInterfaceClass = HDC_CLASS, 132 .bInterfaceSubClass = HDC_SUBCLASS, 133 .bInterfaceProtocol = VER_PROTOCOL, 134 .iInterface = 1 135 }, 136 .from = { 137 .bLength = sizeof(config1.from), 138 .bDescriptorType = USB_DT_ENDPOINT, 139 .bEndpointAddress = 1 | USB_DIR_OUT, 140 .bmAttributes = USB_ENDPOINT_XFER_BULK, 141 .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, 142 }, 143 .to = { 144 .bLength = sizeof(config1.to), 145 .bDescriptorType = USB_DT_ENDPOINT, 146 .bEndpointAddress = 2 | USB_DIR_IN, 147 .bmAttributes = USB_ENDPOINT_XFER_BULK, 148 .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, 149 }, 150 }; 151 152 static struct UsbFunctionDesc config2 = { 153 .ifDesc = { 154 .bLength = sizeof(config2.ifDesc), 155 .bDescriptorType = USB_DT_INTERFACE, 156 .bInterfaceNumber = 0, 157 .bNumEndpoints = 2, 158 .bInterfaceClass = HDC_CLASS, 159 .bInterfaceSubClass = HDC_SUBCLASS, 160 .bInterfaceProtocol = VER_PROTOCOL, 161 .iInterface = 1 162 }, 163 .from = { 164 .bLength = sizeof(config2.from), 165 .bDescriptorType = USB_DT_ENDPOINT, 166 .bEndpointAddress = 1 | USB_DIR_OUT, 167 .bmAttributes = USB_ENDPOINT_XFER_BULK, 168 .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, 169 }, 170 .to = { 171 .bLength = sizeof(config2.to), 172 .bDescriptorType = USB_DT_ENDPOINT, 173 .bEndpointAddress = 2 | USB_DIR_IN, 174 .bmAttributes = USB_ENDPOINT_XFER_BULK, 175 .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, 176 }, 177 }; 178 179 template <size_t PropertyNameLength, size_t PropertyDataLength> 180 struct UsbOsDescExtProp { 181 uint32_t size = sizeof(*this); 182 uint32_t propertyDataTypen = LONG_LE(1); 183 uint16_t propertyNameLength = SHORT_LE(PropertyNameLength); 184 char propertyName [PropertyNameLength]; 185 uint32_t propertyDataLength = LONG_LE(PropertyDataLength); 186 char property [PropertyDataLength]; 187 } __attribute__((packed)); 188 189 using UsbOsDescGuid = UsbOsDescExtProp<PROPERTY_NAME_LENGTH, PROPERTY_DATA_LENGTH>; 190 static UsbOsDescGuid g_osDescGuid = { 191 .propertyName = "DeviceInterfaceGUID", 192 .property = "{f21cc96b-063d-52e1-e3fd-f39cc7a34c40}", 193 }; 194 195 struct UsbExtPropValues { 196 UsbOsDescGuid guid; 197 } __attribute__((packed)); 198 199 static UsbExtPropValues g_osPropValues = { 200 .guid = g_osDescGuid, 201 }; 202 203 static struct usb_ext_compat_desc g_wosDesc = { 204 .bFirstInterfaceNumber = 0, 205 .Reserved1 = LONG_LE(1), 206 .CompatibleID = {'W', 'I', 'N', 'U', 'S', 'B', '\0', '\0'}, 207 .SubCompatibleID = { 0 }, 208 .Reserved2 = { 0 }, 209 }; 210 211 static struct usb_os_desc_header g_wosHead = { 212 .interface = LONG_LE(0), 213 .dwLength = LONG_LE(sizeof(g_wosHead) + sizeof(g_wosDesc)), 214 .bcdVersion = LONG_LE(1), 215 .wIndex = LONG_LE(4), 216 { 217 { 218 .bCount = LONG_LE(1), 219 .Reserved = LONG_LE(0), 220 } 221 }, 222 }; 223 224 static struct usb_os_desc_header g_osPropHead = { 225 .interface = LONG_LE(0), 226 .dwLength = LONG_LE(sizeof(g_wosHead) + sizeof(g_osPropValues)), 227 .bcdVersion = LONG_LE(1), 228 .wIndex = LONG_LE(5), 229 .wCount = SHORT_LE(1), 230 }; 231 232 233 struct UsbFunctionfsDescV2 { 234 struct usb_functionfs_descs_head_v2 head; 235 __le32 config1Count; 236 __le32 config2Count; 237 __le32 config3Count; 238 __le32 configWosCount; 239 struct UsbFunctionDesc config1Desc, config2Desc; 240 struct UsbFuncConfig config3Desc; 241 struct usb_os_desc_header wosHead; 242 struct usb_ext_compat_desc wosDesc; 243 struct usb_os_desc_header osPropHead; 244 struct UsbExtPropValues osPropValues; 245 } __attribute__((packed)); 246 247 } // namespace Hdc 248 #endif 249