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_USBFFS_H 16 #define HDC_USBFFS_H 17 // clang-format off 18 #include <linux/usb/functionfs.h> 19 #include "daemon_common.h" 20 // clang-format on 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 41 #define SHORT_LE(x) htole16(x) 42 #define LONG_LE(x) htole32(x) 43 #define HDC_INTERFACE_NAME "HDC Interface" 44 45 struct UsbFunctionDesc { 46 struct usb_interface_descriptor ifDesc; 47 struct usb_endpoint_descriptor_no_audio from; 48 struct usb_endpoint_descriptor_no_audio to; 49 } __attribute__((packed)); 50 51 static const struct { 52 struct usb_functionfs_strings_head head; 53 struct { 54 __le16 code; 55 const char name[sizeof(HDC_INTERFACE_NAME)]; 56 } __attribute__((packed)) firstItem; 57 } __attribute__((packed)) USB_FFS_VALUE = { 58 .head = 59 { 60 .magic = LONG_LE(FUNCTIONFS_STRINGS_MAGIC), 61 .length = LONG_LE(sizeof(USB_FFS_VALUE)), 62 .str_count = LONG_LE(1), 63 .lang_count = LONG_LE(1), 64 }, 65 .firstItem = 66 { 67 SHORT_LE(0x0409), 68 HDC_INTERFACE_NAME, 69 }, 70 }; 71 72 struct UsbFunctionfsDescsHeadOld { 73 __le32 magic; 74 __le32 length; 75 __le32 config1Count; 76 __le32 config2Count; 77 } __attribute__((packed)); 78 79 struct UsbFuncConfig { 80 struct usb_interface_descriptor ifDesc; 81 struct usb_endpoint_descriptor_no_audio from; 82 struct usb_ss_ep_comp_descriptor pairFrom; 83 struct usb_endpoint_descriptor_no_audio to; 84 struct usb_ss_ep_comp_descriptor pairTo; 85 } __attribute__((packed)); 86 87 static struct UsbFuncConfig config3 = { 88 .ifDesc = { 89 .bLength = sizeof(config3.ifDesc), 90 .bDescriptorType = USB_DT_INTERFACE, 91 .bInterfaceNumber = 0, 92 .bNumEndpoints = 2, 93 .bInterfaceClass = HDC_CLASS, 94 .bInterfaceSubClass = HDC_SUBCLASS, 95 .bInterfaceProtocol = VER_PROTOCOL, 96 .iInterface = 1 97 }, 98 .from = { 99 .bLength = sizeof(config3.from), 100 .bDescriptorType = USB_DT_ENDPOINT, 101 .bEndpointAddress = 1 | USB_DIR_OUT, 102 .bmAttributes = USB_ENDPOINT_XFER_BULK, 103 .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, 104 }, 105 .pairFrom = { 106 .bLength = sizeof(config3.pairFrom), 107 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 108 .bMaxBurst = 4, 109 }, 110 .to = { 111 .bLength = sizeof(config3.to), 112 .bDescriptorType = USB_DT_ENDPOINT, 113 .bEndpointAddress = 2 | USB_DIR_IN, 114 .bmAttributes = USB_ENDPOINT_XFER_BULK, 115 .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, 116 }, 117 .pairTo = { 118 .bLength = sizeof(config3.pairTo), 119 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 120 .bMaxBurst = 4, 121 }, 122 }; 123 124 static struct UsbFunctionDesc config1 = { 125 .ifDesc = { 126 .bLength = sizeof(config1.ifDesc), 127 .bDescriptorType = USB_DT_INTERFACE, 128 .bInterfaceNumber = 0, 129 .bNumEndpoints = 2, 130 .bInterfaceClass = HDC_CLASS, 131 .bInterfaceSubClass = HDC_SUBCLASS, 132 .bInterfaceProtocol = VER_PROTOCOL, 133 .iInterface = 1 134 }, 135 .from = { 136 .bLength = sizeof(config1.from), 137 .bDescriptorType = USB_DT_ENDPOINT, 138 .bEndpointAddress = 1 | USB_DIR_OUT, 139 .bmAttributes = USB_ENDPOINT_XFER_BULK, 140 .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, 141 }, 142 .to = { 143 .bLength = sizeof(config1.to), 144 .bDescriptorType = USB_DT_ENDPOINT, 145 .bEndpointAddress = 2 | USB_DIR_IN, 146 .bmAttributes = USB_ENDPOINT_XFER_BULK, 147 .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, 148 }, 149 }; 150 151 static struct UsbFunctionDesc config2 = { 152 .ifDesc = { 153 .bLength = sizeof(config2.ifDesc), 154 .bDescriptorType = USB_DT_INTERFACE, 155 .bInterfaceNumber = 0, 156 .bNumEndpoints = 2, 157 .bInterfaceClass = HDC_CLASS, 158 .bInterfaceSubClass = HDC_SUBCLASS, 159 .bInterfaceProtocol = VER_PROTOCOL, 160 .iInterface = 1 161 }, 162 .from = { 163 .bLength = sizeof(config2.from), 164 .bDescriptorType = USB_DT_ENDPOINT, 165 .bEndpointAddress = 1 | USB_DIR_OUT, 166 .bmAttributes = USB_ENDPOINT_XFER_BULK, 167 .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, 168 }, 169 .to = { 170 .bLength = sizeof(config2.to), 171 .bDescriptorType = USB_DT_ENDPOINT, 172 .bEndpointAddress = 2 | USB_DIR_IN, 173 .bmAttributes = USB_ENDPOINT_XFER_BULK, 174 .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, 175 }, 176 }; 177 178 template <size_t PropertyNameLength, size_t PropertyDataLength> 179 struct UsbOsDescExtProp { 180 uint32_t size = sizeof(*this); 181 uint32_t propertyDataTypen = LONG_LE(1); 182 uint16_t propertyNameLength = SHORT_LE(PropertyNameLength); 183 char propertyName [PropertyNameLength]; 184 uint32_t propertyDataLength = LONG_LE(PropertyDataLength); 185 char property [PropertyDataLength]; 186 } __attribute__((packed)); 187 188 using UsbOsDescGuid = UsbOsDescExtProp<PROPERTY_NAME_LENGTH, PROPERTY_DATA_LENGTH>; 189 UsbOsDescGuid osDescGuid = { 190 .propertyName = "DeviceInterfaceGUID", 191 .property = "{f21cc96b-063d-52e1-e3fd-f39cc7a34c40}", 192 }; 193 194 struct UsbExtPropValues { 195 UsbOsDescGuid guid; 196 } __attribute__((packed)); 197 198 UsbExtPropValues g_osPropValues = { 199 .guid = osDescGuid, 200 }; 201 202 struct usb_ext_compat_desc g_wosDesc = { 203 .bFirstInterfaceNumber = 0, 204 .Reserved1 = LONG_LE(1), 205 .CompatibleID = {'W', 'I', 'N', 'U', 'S', 'B', '\0', '\0'}, 206 .SubCompatibleID = { 0 }, 207 .Reserved2 = { 0 }, 208 }; 209 210 struct usb_os_desc_header g_wosHead = { 211 .interface = LONG_LE(0), 212 .dwLength = LONG_LE(sizeof(g_wosHead) + sizeof(g_wosDesc)), 213 .bcdVersion = LONG_LE(1), 214 .wIndex = LONG_LE(4), 215 .bCount = LONG_LE(1), 216 .Reserved = LONG_LE(0), 217 }; 218 219 struct usb_os_desc_header g_osPropHead = { 220 .interface = LONG_LE(0), 221 .dwLength = LONG_LE(sizeof(g_wosHead) + sizeof(g_osPropValues)), 222 .bcdVersion = LONG_LE(1), 223 .wIndex = LONG_LE(5), 224 .wCount = SHORT_LE(1), 225 }; 226 227 struct usb_functionfs_desc_v2 { 228 struct usb_functionfs_descs_head_v2 head; 229 __le32 config1Count; 230 __le32 config2Count; 231 __le32 config3Count; 232 __le32 configWosCount; 233 struct UsbFunctionDesc config1Desc, config2Desc; 234 struct UsbFuncConfig config3Desc; 235 struct usb_os_desc_header wosHead; 236 struct usb_ext_compat_desc wosDesc; 237 struct usb_os_desc_header osPropHead; 238 struct UsbExtPropValues osPropValues; 239 } __attribute__((packed)); 240 241 } // namespace Hdc 242 #endif 243