Changeset 60394 in vbox for trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceGadgetClassTest.cpp
- Timestamp:
- Apr 8, 2016 11:07:37 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceGadgetClassTest.cpp
r60376 r60394 31 31 #include <iprt/process.h> 32 32 #include <iprt/string.h> 33 #include <iprt/symlink.h> 33 34 #include <iprt/types.h> 34 35 … … 46 47 #define UTS_GADGET_TEMPLATE_NAME "gadget_test" 47 48 49 /** Default vendor ID which is recognized by the usbtest driver. */ 48 50 #define UTS_GADGET_TEST_VENDOR_ID_DEF UINT16_C(0x0525) 51 /** Default product ID which is recognized by the usbtest driver. */ 49 52 #define UTS_GADGET_TEST_PRODUCT_ID_DEF UINT16_C(0xa4a0) 53 /** Default device class. */ 50 54 #define UTS_GADGET_TEST_DEVICE_CLASS_DEF UINT8_C(0xff) 51 55 /** Default serial number string. */ 56 #define UTS_GADGET_TEST_SERIALNUMBER_DEF "0123456789" 57 /** Default manufacturer string. */ 58 #define UTS_GADGET_TEST_MANUFACTURER_DEF "Oracle Inc." 59 /** Default product string. */ 60 #define UTS_GADGET_TEST_PRODUCT_DEF "USB test device" 52 61 53 62 /** … … 68 77 69 78 /********************************************************************************************************************************* 79 * Global Variables * 80 *********************************************************************************************************************************/ 81 82 /** Number of already created gadgets, used for the template name. */ 83 static volatile uint32_t g_cGadgets = 0; 84 85 86 /********************************************************************************************************************************* 70 87 * Internal Functions * 71 88 *********************************************************************************************************************************/ 72 89 90 /** 91 * Creates a new directory pointed to by the given format string. 92 * 93 * @returns IPRT status code. 94 * @param pszFormat The format string. 95 * @param va The arguments. 96 */ 97 static int utsGadgetClassTestDirCreateV(const char *pszFormat, va_list va) 98 { 99 int rc = VINF_SUCCESS; 100 char aszPath[RTPATH_MAX + 1]; 101 102 size_t cbStr = RTStrPrintfV(&aszPath[0], sizeof(aszPath), pszFormat, va); 103 if (cbStr <= sizeof(aszPath) - 1) 104 rc = RTDirCreateFullPath(aszPath, 0700); 105 else 106 rc = VERR_BUFFER_OVERFLOW; 107 108 return rc; 109 } 110 111 112 /** 113 * Creates a new directory pointed to by the given format string. 114 * 115 * @returns IPRT status code. 116 * @param pszFormat The format string. 117 * @param ... The arguments. 118 */ 119 static int utsGadgetClassTestDirCreate(const char *pszFormat, ...) 120 { 121 va_list va; 122 va_start(va, pszFormat); 123 int rc = utsGadgetClassTestDirCreateV(pszFormat, va); 124 va_end(va); 125 return rc; 126 } 127 128 129 /** 130 * Removes a directory pointed to by the given format string. 131 * 132 * @returns IPRT status code. 133 * @param pszFormat The format string. 134 * @param va The arguments. 135 */ 136 static int utsGadgetClassTestDirRemoveV(const char *pszFormat, va_list va) 137 { 138 int rc = VINF_SUCCESS; 139 char aszPath[RTPATH_MAX + 1]; 140 141 size_t cbStr = RTStrPrintfV(&aszPath[0], sizeof(aszPath), pszFormat, va); 142 if (cbStr <= sizeof(aszPath) - 1) 143 rc = RTDirRemove(aszPath); 144 else 145 rc = VERR_BUFFER_OVERFLOW; 146 147 return rc; 148 } 149 150 151 /** 152 * Removes a directory pointed to by the given format string. 153 * 154 * @returns IPRT status code. 155 * @param pszFormat The format string. 156 * @param ... The arguments. 157 */ 158 static int utsGadgetClassTestDirRemove(const char *pszFormat, ...) 159 { 160 va_list va; 161 va_start(va, pszFormat); 162 int rc = utsGadgetClassTestDirRemoveV(pszFormat, va); 163 va_end(va); 164 return rc; 165 } 166 167 168 /** 169 * Links the given function to the given config. 170 * 171 * @returns IPRT status code. 172 * @param pClass The gadget class instance data. 173 * @param pszFunc The function to link. 174 * @param pszCfg The configuration which the function will be part of. 175 */ 176 static int utsGadgetClassTestLinkFuncToCfg(PUTSGADGETCLASSINT pClass, const char *pszFunc, const char *pszCfg) 177 { 178 int rc = VINF_SUCCESS; 179 char aszPathFunc[RTPATH_MAX + 1]; 180 char aszPathCfg[RTPATH_MAX + 1]; 181 182 size_t cbStr = RTStrPrintf(&aszPathFunc[0], sizeof(aszPathFunc), "%s/functions/%s", 183 pClass->pszGadgetPath, pszFunc); 184 if (cbStr <= sizeof(aszPathFunc) - 1) 185 { 186 cbStr = RTStrPrintf(&aszPathCfg[0], sizeof(aszPathCfg), "%s/configs/%s", 187 pClass->pszGadgetPath, pszCfg); 188 if (cbStr <= sizeof(aszPathCfg) - 1) 189 rc = RTSymlinkCreate(&aszPathCfg[0], &aszPathFunc[0], RTSYMLINKTYPE_DIR, 0); 190 else 191 rc = VERR_BUFFER_OVERFLOW; 192 } 193 else 194 rc = VERR_BUFFER_OVERFLOW; 195 196 return rc; 197 } 198 199 200 /** 201 * Unlinks the given function from the given configuration. 202 * 203 * @returns IPRT status code. 204 * @param pClass The gadget class instance data. 205 * @param pszFunc The function to unlink. 206 * @param pszCfg The configuration which the function is currently part of. 207 */ 208 static int utsGadgetClassTestUnlinkFuncFromCfg(PUTSGADGETCLASSINT pClass, const char *pszFunc, const char *pszCfg) 209 { 210 int rc = VINF_SUCCESS; 211 char aszPath[RTPATH_MAX + 1]; 212 size_t cbStr = RTStrPrintf(&aszPath[0], sizeof(aszPath), "%s/configs/%s/%s", 213 pClass->pszGadgetPath, pszCfg, pszFunc); 214 if (cbStr <= sizeof(aszPath) - 1) 215 rc = RTSymlinkDelete(&aszPath[0], 0); 216 else 217 rc = VERR_BUFFER_OVERFLOW; 218 219 return rc; 220 } 221 222 223 /** 224 * Cleans up any leftover configurations from the gadget class. 225 * 226 * @returns nothing. 227 * @param pClass The gadget class instance data. 228 */ 229 static void utsGadgetClassTestCleanup(PUTSGADGETCLASSINT pClass) 230 { 231 /* Unbind the gadget from the currently assigned UDC first. */ 232 int rc = RTLinuxSysFsWriteStrFile("", 0, NULL, "%s/UDC", pClass->pszGadgetPath); 233 AssertRC(rc); 234 235 /* Delete the symlinks, ignore any errors. */ 236 utsGadgetClassTestUnlinkFuncFromCfg(pClass, "Loopback.0", "c.2"); 237 utsGadgetClassTestUnlinkFuncFromCfg(pClass, "SourceSink.0", "c.1"); 238 239 /* Delete configuration strings and then the configuration directories. */ 240 utsGadgetClassTestDirRemove("%s/configs/c.2/strings/0x409", pClass->pszGadgetPath); 241 utsGadgetClassTestDirRemove("%s/configs/c.1/strings/0x409", pClass->pszGadgetPath); 242 243 utsGadgetClassTestDirRemove("%s/configs/c.2", pClass->pszGadgetPath); 244 utsGadgetClassTestDirRemove("%s/configs/c.1", pClass->pszGadgetPath); 245 246 /* Delete the functions. */ 247 utsGadgetClassTestDirRemove("%s/functions/Loopback.0", pClass->pszGadgetPath); 248 utsGadgetClassTestDirRemove("%s/functions/SourceSink.0", pClass->pszGadgetPath); 249 250 /* Delete the english strings. */ 251 utsGadgetClassTestDirRemove("%s/strings/0x409", pClass->pszGadgetPath); 252 253 /* Finally delete the gadget template. */ 254 utsGadgetClassTestDirRemove(pClass->pszGadgetPath); 255 } 73 256 74 257 /** … … 82 265 { 83 266 /* Create the gadget template */ 84 unsigned idx = 0; 85 char aszPath[RTPATH_MAX]; 86 87 do 88 { 89 RTStrPrintf(&aszPath[0], RT_ELEMENTS(aszPath), "%s/%s%u", 90 UTS_GADGET_CLASS_CONFIGFS_MNT_DEF, UTS_GADGET_TEMPLATE_NAME, 91 idx); 92 rc = RTDirCreateFullPath(aszPath, 0700); 93 if (RT_SUCCESS(rc)) 94 break; 95 idx++; 96 } while (idx < 100); 97 267 unsigned idx = ASMAtomicIncU32(&g_cGadgets); 268 269 int rcStr = RTStrAPrintf(&pClass->pszGadgetPath, "%s/%s%u", UTS_GADGET_CLASS_CONFIGFS_MNT_DEF, 270 UTS_GADGET_TEMPLATE_NAME, idx); 271 if (rcStr == -1) 272 return VERR_NO_STR_MEMORY; 273 274 rc = utsGadgetClassTestDirCreate(pClass->pszGadgetPath); 98 275 if (RT_SUCCESS(rc)) 99 276 { 100 pClass->pszGadgetPath = RTStrDup(aszPath);101 102 277 uint16_t idVendor = 0; 103 278 uint16_t idProduct = 0; 104 279 uint8_t bDeviceClass = 0; 105 rc = utsGadgetCfgQueryU16Def(paCfg, "Gadget/idVendor", &idVendor, UTS_GADGET_TEST_VENDOR_ID_DEF); 106 if (RT_SUCCESS(rc)) 107 rc = utsGadgetCfgQueryU16Def(paCfg, "Gadget/idProduct", &idProduct, UTS_GADGET_TEST_PRODUCT_ID_DEF); 108 if (RT_SUCCESS(rc)) 109 rc = utsGadgetCfgQueryU8Def(paCfg, "Gadget/bDeviceClass", &bDeviceClass, UTS_GADGET_TEST_DEVICE_CLASS_DEF); 280 char *pszSerial = NULL; 281 char *pszManufacturer = NULL; 282 char *pszProduct = NULL; 283 284 /* Get basic device config. */ 285 rc = utsGadgetCfgQueryU16Def(paCfg, "Gadget/idVendor", &idVendor, UTS_GADGET_TEST_VENDOR_ID_DEF); 286 if (RT_SUCCESS(rc)) 287 rc = utsGadgetCfgQueryU16Def(paCfg, "Gadget/idProduct", &idProduct, UTS_GADGET_TEST_PRODUCT_ID_DEF); 288 if (RT_SUCCESS(rc)) 289 rc = utsGadgetCfgQueryU8Def(paCfg, "Gadget/bDeviceClass", &bDeviceClass, UTS_GADGET_TEST_DEVICE_CLASS_DEF); 290 if (RT_SUCCESS(rc)) 291 rc = utsGadgetCfgQueryStringDef(paCfg, "Gadget/SerialNumber", &pszSerial, UTS_GADGET_TEST_SERIALNUMBER_DEF); 292 if (RT_SUCCESS(rc)) 293 rc = utsGadgetCfgQueryStringDef(paCfg, "Gadget/Manufacturer", &pszManufacturer, UTS_GADGET_TEST_MANUFACTURER_DEF); 294 if (RT_SUCCESS(rc)) 295 rc = utsGadgetCfgQueryStringDef(paCfg, "Gadget/Product", &pszProduct, UTS_GADGET_TEST_PRODUCT_DEF); 296 297 if (RT_SUCCESS(rc)) 298 { 299 /* Write basic attributes. */ 300 rc = RTLinuxSysFsWriteU16File(16, idVendor, "%s/idVendor", pClass->pszGadgetPath); 301 if (RT_SUCCESS(rc)) 302 rc = RTLinuxSysFsWriteU16File(16, idProduct, "%s/idProduct", pClass->pszGadgetPath); 303 if (RT_SUCCESS(rc)) 304 rc = RTLinuxSysFsWriteU16File(16, bDeviceClass, "%s/bDeviceClass", pClass->pszGadgetPath); 305 306 /* Create english language strings. */ 307 if (RT_SUCCESS(rc)) 308 rc = utsGadgetClassTestDirCreate("%s/strings/0x409", pClass->pszGadgetPath); 309 if (RT_SUCCESS(rc)) 310 rc = RTLinuxSysFsWriteStrFile(pszSerial, 0, NULL, "%s/strings/0x409/serialnumber", pClass->pszGadgetPath); 311 if (RT_SUCCESS(rc)) 312 rc = RTLinuxSysFsWriteStrFile(pszManufacturer, 0, NULL, "%s/strings/0x409/manufacturer", pClass->pszGadgetPath); 313 if (RT_SUCCESS(rc)) 314 rc = RTLinuxSysFsWriteStrFile(pszProduct, 0, NULL, "%s/strings/0x409/product", pClass->pszGadgetPath); 315 316 /* Create the gadget functions. */ 317 if (RT_SUCCESS(rc)) 318 rc = utsGadgetClassTestDirCreate("%s/functions/SourceSink.0", pClass->pszGadgetPath); 319 if (RT_SUCCESS(rc)) 320 rc = utsGadgetClassTestDirCreate("%s/functions/Loopback.0", pClass->pszGadgetPath); 321 322 /* Create the device configs. */ 323 if (RT_SUCCESS(rc)) 324 rc = utsGadgetClassTestDirCreate("%s/configs/c.1", pClass->pszGadgetPath); 325 if (RT_SUCCESS(rc)) 326 rc = utsGadgetClassTestDirCreate("%s/configs/c.2", pClass->pszGadgetPath); 327 328 /* Write configuration strings. */ 329 if (RT_SUCCESS(rc)) 330 rc = utsGadgetClassTestDirCreate("%s/configs/c.1/strings/0x409", pClass->pszGadgetPath); 331 if (RT_SUCCESS(rc)) 332 rc = utsGadgetClassTestDirCreate("%s/configs/c.2/strings/0x409", pClass->pszGadgetPath); 333 if (RT_SUCCESS(rc)) 334 rc = RTLinuxSysFsWriteStrFile("source and sink data", 0, NULL, "%s/configs/c.1/strings/0x409/configuration", pClass->pszGadgetPath); 335 if (RT_SUCCESS(rc)) 336 rc = RTLinuxSysFsWriteStrFile("loop input to output", 0, NULL, "%s/configs/c.2/strings/0x409/configuration", pClass->pszGadgetPath); 337 338 /* Link the functions into the configurations. */ 339 if (RT_SUCCESS(rc)) 340 rc = utsGadgetClassTestLinkFuncToCfg(pClass, "SourceSink.0", "c.1"); 341 if (RT_SUCCESS(rc)) 342 rc = utsGadgetClassTestLinkFuncToCfg(pClass, "Loopback.0", "c.2"); 343 344 /* Finally enable the gadget by attaching it to a UDC. */ 345 /** @todo: Figure out a free UDC dynamically. */ 346 if (RT_SUCCESS(rc)) 347 rc = RTLinuxSysFsWriteStrFile("dummy_udc.0", 0, NULL, "%s/UDC", pClass->pszGadgetPath); 348 } 349 350 if (pszSerial) 351 RTStrFree(pszSerial); 352 if (pszManufacturer) 353 RTStrFree(pszManufacturer); 354 if (pszProduct) 355 RTStrFree(pszProduct); 110 356 } 111 357 } … … 113 359 rc = VERR_NOT_FOUND; 114 360 361 if (RT_FAILURE(rc)) 362 utsGadgetClassTestCleanup(pClass); 363 115 364 return rc; 116 365 } … … 122 371 static DECLCALLBACK(void) utsGadgetClassTestTerm(PUTSGADGETCLASSINT pClass) 123 372 { 124 373 utsGadgetClassTestCleanup(pClass); 374 375 if (pClass->pszGadgetPath) 376 RTStrFree(pClass->pszGadgetPath); 125 377 } 126 378
Note:
See TracChangeset
for help on using the changeset viewer.