Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2701 lines
76 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. Port driver for USB host controllers
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. 6-20-99 : created
  12. --*/
  13. #include "common.h"
  14. #ifdef DRM_SUPPORT
  15. #include <ksdrmhlp.h>
  16. #endif
  17. #include "usbpriv.h"
  18. // paged functions
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, USBPORT_FdoDeviceControlIrp)
  21. #pragma alloc_text(PAGE, USBPORT_PdoDeviceControlIrp)
  22. #pragma alloc_text(PAGE, USBPORT_LegacyGetUnicodeName)
  23. #pragma alloc_text(PAGE, USBPORT_GetSymbolicName)
  24. #ifdef DRM_SUPPORT
  25. #pragma alloc_text(PAGE, USBPORT_PdoSetContentId)
  26. #endif
  27. #endif
  28. // non paged functions
  29. // USBPORT_FdoInternalDeviceControlIrp
  30. // USBPORT_PdoInternalDeviceControlIrp
  31. // USBPORT_UserSendOnePacket
  32. BOOLEAN
  33. USBPORT_CheckLength(
  34. PUSBUSER_REQUEST_HEADER Header,
  35. ULONG ParameterLength
  36. )
  37. /*++
  38. Routine Description:
  39. Checks Length of user supplied buffer based on api
  40. Arguments:
  41. Return Value:
  42. FALSE if buffer too small
  43. --*/
  44. {
  45. ULONG length;
  46. BOOLEAN retCode = TRUE;
  47. length = sizeof(*Header) + ParameterLength;
  48. Header->ActualBufferLength = length;
  49. if (length > Header->RequestBufferLength) {
  50. //TEST_TRAP();
  51. Header->UsbUserStatusCode = UsbUserBufferTooSmall;
  52. retCode = FALSE;
  53. }
  54. return retCode;
  55. }
  56. NTSTATUS
  57. USBPORT_FdoDeviceControlIrp(
  58. PDEVICE_OBJECT FdoDeviceObject,
  59. PIRP Irp
  60. )
  61. /*++
  62. Routine Description:
  63. Disptach routine for DEVICE_CONTROL Irps sent to the FDO for the HC.
  64. NOTE: These are user mode requests
  65. Arguments:
  66. DeviceObject - Fdo for USB HC
  67. Return Value:
  68. NTSTATUS
  69. --*/
  70. {
  71. PIO_STACK_LOCATION irpStack;
  72. NTSTATUS ntStatus = STATUS_SUCCESS;
  73. PDEVICE_EXTENSION devExt;
  74. ULONG information = 0;
  75. USBPORT_KdPrint((2, "'IRP_MJ_DEVICE_CONTROL\n"));
  76. irpStack = IoGetCurrentIrpStackLocation(Irp);
  77. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  78. ASSERT_FDOEXT(devExt);
  79. USBPORT_ASSERT(irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL);
  80. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  81. case IOCTL_USB_DIAGNOSTIC_MODE_ON:
  82. USBPORT_KdPrint((2, "'IOCTL_USB_DIAGNOSTIC_MODE_ON\n"));
  83. SET_FDO_FLAG(devExt, USBPORT_FDOFLAG_DIAG_MODE);
  84. ntStatus = STATUS_SUCCESS;
  85. break;
  86. case IOCTL_USB_DIAGNOSTIC_MODE_OFF:
  87. USBPORT_KdPrint((2, "'IOCTL_USB_DIAGNOSTIC_MODE_OFF\n"));
  88. CLEAR_FDO_FLAG(devExt, USBPORT_FDOFLAG_DIAG_MODE);
  89. ntStatus = STATUS_SUCCESS;;
  90. break;
  91. case IOCTL_GET_HCD_DRIVERKEY_NAME:
  92. USBPORT_KdPrint((2, "'IOCTL_GET_HCD_DRIVERKEY_NAME\n"));
  93. ntStatus = USBPORT_LegacyGetUnicodeName(FdoDeviceObject,
  94. Irp,
  95. &information);
  96. break;
  97. case IOCTL_USB_GET_ROOT_HUB_NAME:
  98. USBPORT_KdPrint((2, "'IOCTL_USB_GET_ROOT_HUB_NAME\n"));
  99. ntStatus = USBPORT_LegacyGetUnicodeName(FdoDeviceObject,
  100. Irp,
  101. &information);
  102. break;
  103. case IOCTL_USB_USER_REQUEST:
  104. USBPORT_KdPrint((2, "'IOCTL_USB_USER_REQUEST\n"));
  105. ntStatus = USBPORT_UsbFdoUserIoctl(FdoDeviceObject,
  106. Irp,
  107. &information);
  108. break;
  109. // old IOCTLS no longer supported
  110. // case IOCTL_USB_HCD_GET_STATS_2:
  111. // case IOCTL_USB_HCD_GET_STATS_1:
  112. default:
  113. // bugbug pass on to PDO or complete with error?
  114. USBPORT_KdPrint((2, "'INVALID DEVICE CONTROL\n"));
  115. DEBUG_BREAK();
  116. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  117. } // switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  118. USBPORT_CompleteIrp(FdoDeviceObject, Irp, ntStatus, information);
  119. //
  120. // DO NOT TOUCH THE IRP FROM THIS POINT ON
  121. //
  122. return ntStatus;
  123. }
  124. #ifdef DRM_SUPPORT
  125. NTSTATUS
  126. USBPORT_PdoSetContentId
  127. (
  128. IN PIRP irp,
  129. IN PKSP_DRMAUDIOSTREAM_CONTENTID pKsProperty,
  130. IN PKSDRMAUDIOSTREAM_CONTENTID pvData
  131. )
  132. /* ++
  133. *
  134. * Description:
  135. *
  136. *
  137. * Arguments:
  138. *
  139. * Return:
  140. *
  141. * -- */
  142. {
  143. ULONG ContentId;
  144. NTSTATUS ntStatus;
  145. PIO_STACK_LOCATION ioStackLocation;
  146. PDEVICE_EXTENSION devExt;
  147. PDEVICE_OBJECT fdoDeviceObject;
  148. PDEVICE_EXTENSION fdoDevExt;
  149. PUSBPORT_REGISTRATION_PACKET registrationPacket;
  150. PVOID *pHandlers;
  151. ULONG numHandlers;
  152. PAGED_CODE();
  153. ASSERT(irp);
  154. ASSERT(pKsProperty);
  155. ASSERT(pvData);
  156. ioStackLocation = IoGetCurrentIrpStackLocation(irp);
  157. devExt = ioStackLocation->DeviceObject->DeviceExtension;
  158. fdoDeviceObject = devExt->HcFdoDeviceObject;
  159. GET_DEVICE_EXT(fdoDevExt, fdoDeviceObject);
  160. registrationPacket = &REGISTRATION_PACKET(fdoDevExt);
  161. pHandlers = (PVOID *)&registrationPacket->MINIPORT_OpenEndpoint;
  162. numHandlers = (ULONG)((((ULONG_PTR)&registrationPacket->MINIPORT_PassThru -
  163. (ULONG_PTR)&registrationPacket->MINIPORT_OpenEndpoint) /
  164. sizeof(PVOID)) + 1);
  165. ContentId = pvData->ContentId;
  166. // Context = pKsProperty->Context;
  167. // Since there is a private interface between USBPORT.SYS and the miniports,
  168. // we give DRM a list of function pointers in the miniport for validation,
  169. // in place of a device object, since the miniport does not handle IRP
  170. // requests.
  171. // If at some future time a miniport is ever written that acts as a bridge
  172. // to another bus or device stack, this may have to be modified such that
  173. // DRM is notified of that driver that the data is forwarded to.
  174. ntStatus = pKsProperty->DrmAddContentHandlers(ContentId, pHandlers, numHandlers);
  175. return ntStatus;
  176. }
  177. #endif
  178. NTSTATUS
  179. USBPORT_PdoDeviceControlIrp(
  180. PDEVICE_OBJECT PdoDeviceObject,
  181. PIRP Irp
  182. )
  183. /*++
  184. Routine Description:
  185. Dispatch routine for DEVICE_CONTROL Irps sent to the PDO for the Root Hub.
  186. NOTE: These are user mode requests
  187. Arguments:
  188. DeviceObject - Pdo for USB Root Hub
  189. Return Value:
  190. NTSTATUS
  191. --*/
  192. {
  193. PIO_STACK_LOCATION irpStack;
  194. NTSTATUS ntStatus = STATUS_SUCCESS;
  195. PDEVICE_EXTENSION rhDevExt;
  196. ULONG information = 0;
  197. USBPORT_KdPrint((2, "'IRP_MJ_DEVICE_CONTROL\n"));
  198. irpStack = IoGetCurrentIrpStackLocation(Irp);
  199. GET_DEVICE_EXT(rhDevExt, PdoDeviceObject);
  200. ASSERT_PDOEXT(rhDevExt);
  201. USBPORT_ASSERT(irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL);
  202. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  203. #ifdef DRM_SUPPORT
  204. case IOCTL_KS_PROPERTY:
  205. USBPORT_KdPrint((2, "'IOCTL_KS_PROPERTY\n"));
  206. ntStatus = KsPropertyHandleDrmSetContentId(Irp, USBPORT_PdoSetContentId);
  207. break;
  208. #endif
  209. default:
  210. USBPORT_KdPrint((2, "'INVALID DEVICE CONTROL\n"));
  211. DEBUG_BREAK();
  212. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  213. } // switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  214. USBPORT_CompleteIrp(PdoDeviceObject, Irp, ntStatus, information);
  215. //
  216. // DO NOT TOUCH THE IRP FROM THIS POINT ON
  217. //
  218. return ntStatus;
  219. }
  220. NTSTATUS
  221. USBPORT_FdoInternalDeviceControlIrp(
  222. PDEVICE_OBJECT FdoDeviceObject,
  223. PIRP Irp
  224. )
  225. /*++
  226. Routine Description:
  227. Disptach routine for INTERNAL_DEVICE_CONTROL Irps sent to
  228. the FDO for the HC.
  229. NOTE: These are kernel mode requests
  230. Arguments:
  231. DeviceObject - Fdo for USB HC
  232. Return Value:
  233. NTSTATUS
  234. --*/
  235. {
  236. PIO_STACK_LOCATION irpStack;
  237. NTSTATUS ntStatus = STATUS_SUCCESS;
  238. PDEVICE_EXTENSION devExt;
  239. USBPORT_KdPrint((2, "'IRP_MJ_DEVICE_CONTROL\n"));
  240. irpStack = IoGetCurrentIrpStackLocation(Irp);
  241. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  242. ASSERT_FDOEXT(devExt);
  243. USBPORT_ASSERT(irpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
  244. // bugbug pass on to PDO or complete with error?
  245. USBPORT_KdPrint((2, "'INVALID INTERNAL DEVICE CONTROL\n"));
  246. DEBUG_BREAK();
  247. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  248. USBPORT_CompleteIrp(FdoDeviceObject, Irp, ntStatus, 0);
  249. //
  250. // DO NOT TOUCH THE IRP FROM THIS POINT ON
  251. //
  252. return ntStatus;
  253. }
  254. NTSTATUS
  255. USBPORT_PdoInternalDeviceControlIrp(
  256. PDEVICE_OBJECT PdoDeviceObject,
  257. PIRP Irp
  258. )
  259. /*++
  260. Routine Description:
  261. Disptach routine for INTERNAL_DEVICE_CONTROL Irps sent to
  262. the PDO for the Root Hub.
  263. NOTE: These are kernel mode requests
  264. Arguments:
  265. DeviceObject - Fdo for USB HC
  266. Return Value:
  267. NTSTATUS
  268. --*/
  269. {
  270. PIO_STACK_LOCATION irpStack;
  271. NTSTATUS ntStatus = STATUS_SUCCESS;
  272. PDEVICE_EXTENSION rhDevExt;
  273. USBPORT_KdPrint((2, "'INTERNAL_DEVICE_CONTROL\n"));
  274. irpStack = IoGetCurrentIrpStackLocation(Irp);
  275. GET_DEVICE_EXT(rhDevExt, PdoDeviceObject);
  276. ASSERT_PDOEXT(rhDevExt);
  277. USBPORT_ASSERT(irpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
  278. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  279. case IOCTL_INTERNAL_USB_SUBMIT_URB:
  280. USBPORT_KdPrint((2, "'IOCTL_INTERNAL_USB_SUBMIT_URB\n"));
  281. {
  282. PURB urb;
  283. //
  284. // all URBs are eventually passed to the root hub PDO
  285. // this is where we service cleint requests
  286. //
  287. // extract the urb;
  288. urb = irpStack->Parameters.Others.Argument1;
  289. // call the main urb control function
  290. ntStatus = USBPORT_ProcessURB(PdoDeviceObject,
  291. rhDevExt->HcFdoDeviceObject,
  292. Irp,
  293. urb);
  294. }
  295. goto USBPORT_PdoInternalDeviceControlIrp_Done;
  296. break;
  297. case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
  298. USBPORT_KdPrint((2, "'IOCTL_INTERNAL_USB_GET_HUB_COUNT\n"));
  299. {
  300. PULONG count;
  301. //
  302. // bump the count and complete the Irp
  303. //
  304. count = irpStack->Parameters.Others.Argument1;
  305. ASSERT(count != NULL);
  306. (*count)++;
  307. ntStatus = STATUS_SUCCESS;
  308. }
  309. break;
  310. case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
  311. {
  312. PUSBD_DEVICE_HANDLE *deviceHandle;
  313. deviceHandle = irpStack->Parameters.Others.Argument1;
  314. *deviceHandle = &rhDevExt->Pdo.RootHubDeviceHandle;
  315. ntStatus = STATUS_SUCCESS;
  316. }
  317. break;
  318. case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
  319. ntStatus =
  320. USBPORT_IdleNotificationRequest(PdoDeviceObject, Irp);
  321. goto USBPORT_PdoInternalDeviceControlIrp_Done;
  322. break;
  323. case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
  324. USBPORT_KdPrint((2, "'IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n"));
  325. // this api is called by the hub driver to get the
  326. // PDO for he root hub.
  327. // Since the hub may be loaded on a PDO enumerated by
  328. // another hub it uses this api to get the 'fastest path'
  329. // to the HCD for URB requests by client drivers.
  330. {
  331. PDEVICE_OBJECT *rootHubPdo, *hcdTopOfStackDeviceObject;
  332. rootHubPdo = irpStack->Parameters.Others.Argument1;
  333. hcdTopOfStackDeviceObject =
  334. irpStack->Parameters.Others.Argument2;
  335. USBPORT_ASSERT(hcdTopOfStackDeviceObject != NULL);
  336. USBPORT_ASSERT(rootHubPdo != NULL);
  337. *rootHubPdo = PdoDeviceObject;
  338. // the original USBD was somewhat screwy in the layout
  339. // of the HCD device objects in the case of the port
  340. // driver all requests should go to to the root hub PDO
  341. *hcdTopOfStackDeviceObject =
  342. PdoDeviceObject;
  343. ntStatus = STATUS_SUCCESS;
  344. }
  345. break;
  346. #if 0
  347. case IOCTL_INTERNAL_USB_GET_HUB_NAME:
  348. TEST_TRAP();
  349. ntStatus = STATUS_NOT_SUPPORTED;
  350. break;
  351. #endif
  352. default:
  353. USBPORT_KdPrint((2, "'INVALID INTERNAL DEVICE CONTROL %x\n",
  354. irpStack->Parameters.DeviceIoControl.IoControlCode));
  355. DEBUG_BREAK();
  356. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  357. }
  358. //
  359. // DO NOT TOUCH THE IRP FROM THIS POINT ON
  360. //
  361. USBPORT_CompleteIrp(PdoDeviceObject, Irp, ntStatus, 0);
  362. USBPORT_PdoInternalDeviceControlIrp_Done:
  363. return ntStatus;
  364. }
  365. NTSTATUS
  366. USBPORT_UsbFdoUserIoctl(
  367. PDEVICE_OBJECT FdoDeviceObject,
  368. PIRP Irp,
  369. PULONG BytesReturned
  370. )
  371. /*++
  372. Routine Description:
  373. The goal here is to have all user mode APIS
  374. pass thru this routine so that the parameter
  375. validation is handled in one place.
  376. We define user APIS supported by the PORT FDO
  377. thru this single IOCTL.
  378. The USUSER APIs use the same buffer for input and output,
  379. hence the InputBufferLength and the OutputbufferLength must
  380. always be equal.
  381. We get here if the client sends the IOCTL_USB_USER_REQUEST.
  382. We only return NTSTATUS failure if the header portion of the
  383. buffer is invalid.
  384. Arguments:
  385. DeviceObject - Fdo for USB HC
  386. BytesRetrned - ptr to bytes to return to caller, initially zero
  387. Return Value:
  388. NTSTATUS
  389. --*/
  390. {
  391. PIO_STACK_LOCATION irpStack;
  392. NTSTATUS ntStatus;
  393. PUSBUSER_REQUEST_HEADER header;
  394. PDEVICE_EXTENSION devExt;
  395. PUCHAR ioBufferO;
  396. ULONG inputBufferLength, outputBufferLength, allocLength;
  397. ULONG ioBufferLength;
  398. PUCHAR myIoBuffer;
  399. BOOLEAN alloced;
  400. USBPORT_KdPrint((2, "'USBPORT_FdoUserIoctl\n"));
  401. irpStack = IoGetCurrentIrpStackLocation(Irp);
  402. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  403. ASSERT_FDOEXT(devExt);
  404. USBPORT_ASSERT(irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL);
  405. USBPORT_ASSERT(irpStack->Parameters.DeviceIoControl.IoControlCode ==
  406. IOCTL_USB_USER_REQUEST);
  407. ioBufferO = Irp->AssociatedIrp.SystemBuffer;
  408. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  409. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  410. //
  411. // one bug that the driver verifier does not catch is if we trash the
  412. // iobuffer passed to us.
  413. //
  414. // We shadow this buffer to one we allocate, this way DV should catch
  415. // us if we trash memory.
  416. // We do this in retail even though this a perf hit since the NT guys
  417. // tend to favor stability more than perf and this is not a hot-path.
  418. //
  419. // If DV is ever modified to do this for us we cann remove this code.
  420. //
  421. allocLength = max(inputBufferLength, outputBufferLength);
  422. if (allocLength) {
  423. ALLOC_POOL_Z(myIoBuffer, NonPagedPool, allocLength);
  424. } else {
  425. myIoBuffer = NULL;
  426. }
  427. if (myIoBuffer != NULL) {
  428. alloced = TRUE;
  429. RtlCopyMemory(myIoBuffer,
  430. ioBufferO,
  431. inputBufferLength);
  432. } else {
  433. // if alloc fails just fall back to the original
  434. alloced = FALSE;
  435. myIoBuffer = ioBufferO;
  436. }
  437. ioBufferLength = inputBufferLength;
  438. USBPORT_KdPrint((2, "'ioBuffer = %x - %x\n", ioBufferO, myIoBuffer));
  439. USBPORT_KdPrint((2, "'inputBufferLength %d\n", inputBufferLength));
  440. USBPORT_KdPrint((2, "'outputBufferLength %d\n", outputBufferLength));
  441. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'uIOC', ioBufferO, inputBufferLength,
  442. outputBufferLength);
  443. // some initial parameter validation
  444. // bogus buffer lengths
  445. if (inputBufferLength != outputBufferLength) {
  446. ntStatus = STATUS_INVALID_PARAMETER;
  447. goto USBPORT_UsbFdoUserIoctl_Done;
  448. }
  449. // must have at least enough for a header
  450. if (ioBufferLength < sizeof(USBUSER_REQUEST_HEADER)) {
  451. ntStatus = STATUS_BUFFER_TOO_SMALL;
  452. goto USBPORT_UsbFdoUserIoctl_Done;
  453. }
  454. // no _try _except needed here since we are using method buffered and
  455. // we already validate the length
  456. //__try {
  457. // UCHAR ch;
  458. // // check the buffer
  459. //
  460. // ch = *ioBufferO;
  461. // ch = *(ioBufferO+sizeof(USBUSER_REQUEST_HEADER));
  462. //
  463. //} __except(EXCEPTION_EXECUTE_HANDLER) {
  464. // USBPORT_KdPrint((0,"'EXCEPTION USBPORT_UsbFdoUserIoctl\n"));
  465. // ntStatus = GetExceptionCode();
  466. // TEST_TRAP();
  467. // goto USBPORT_UsbFdoUserIoctl_Done;
  468. // }
  469. // header buffer is valid, at this point we return
  470. // STATUS_SUCCESS to the caller and fill in the header
  471. // with the appropriate error code
  472. ntStatus = STATUS_SUCCESS;
  473. // validate the header buffer parameters
  474. header = (PUSBUSER_REQUEST_HEADER) myIoBuffer;
  475. // assume success, set return values
  476. header->UsbUserStatusCode = UsbUserSuccess;
  477. *BytesReturned =
  478. header->ActualBufferLength = sizeof(*header);
  479. // length set in header should be the same
  480. // as length passed in the ioctl
  481. if (header->RequestBufferLength != ioBufferLength) {
  482. header->UsbUserStatusCode =
  483. UsbUserInvalidHeaderParameter;
  484. goto USBPORT_UsbFdoUserIoctl_Done;
  485. }
  486. // we have a valid header and cleint buffer, attempt to execute
  487. // the api
  488. // validate rules for Api codes
  489. // is this an API that only works when the root hub is disabled?
  490. {
  491. ULONG mask;
  492. mask = (USBUSER_OP_MASK_DEVONLY_API | USBUSER_OP_MASK_HCTEST_API);
  493. if ((header->UsbUserRequest & mask) &&
  494. devExt->Fdo.RootHubPdo != NULL) {
  495. // root hub only api and we have a root hub, make sure it
  496. // is disabled
  497. PDEVICE_EXTENSION rhDevExt;
  498. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  499. ASSERT_PDOEXT(rhDevExt);
  500. if (!(TEST_FLAG(rhDevExt->PnpStateFlags, USBPORT_PNP_REMOVED) ||
  501. SET_FDO_FLAG(devExt, USBPORT_FDOFLAG_DIAG_MODE))) {
  502. header->UsbUserStatusCode = UsbUserFeatureDisabled;
  503. ntStatus = STATUS_UNSUCCESSFUL;
  504. goto USBPORT_UsbFdoUserIoctl_Done;
  505. }
  506. }
  507. }
  508. switch (header->UsbUserRequest) {
  509. case USBUSER_OP_SEND_ONE_PACKET:
  510. if (USBPORT_CheckLength(header, sizeof(PACKET_PARAMETERS))) {
  511. // DCA api
  512. USBPORT_UserSendOnePacket(FdoDeviceObject, header,
  513. (PPACKET_PARAMETERS) (myIoBuffer+sizeof(*header)));
  514. }
  515. break;
  516. case USBUSER_OP_RAW_RESET_PORT:
  517. if (USBPORT_CheckLength(header, sizeof(RAW_RESET_PORT_PARAMETERS))) {
  518. // DCA api
  519. USBPORT_UserRawResetPort(FdoDeviceObject, header,
  520. (PRAW_RESET_PORT_PARAMETERS) (myIoBuffer+sizeof(*header)));
  521. }
  522. break;
  523. case USBUSER_SET_ROOTPORT_FEATURE:
  524. if (USBPORT_CheckLength(header, sizeof(RAW_ROOTPORT_FEATURE))) {
  525. // DCA api
  526. USBPORT_UserSetRootPortFeature(FdoDeviceObject, header,
  527. (PRAW_ROOTPORT_FEATURE) (myIoBuffer+sizeof(*header)));
  528. }
  529. break;
  530. case USBUSER_CLEAR_ROOTPORT_FEATURE:
  531. if (USBPORT_CheckLength(header, sizeof(RAW_ROOTPORT_FEATURE))) {
  532. // DCA api
  533. USBPORT_UserClearRootPortFeature(FdoDeviceObject, header,
  534. (PRAW_ROOTPORT_FEATURE) (myIoBuffer+sizeof(*header)));
  535. }
  536. break;
  537. case USBUSER_GET_ROOTPORT_STATUS:
  538. // DCA api
  539. if (USBPORT_CheckLength(header, sizeof(RAW_ROOTPORT_PARAMETERS))) {
  540. USBPORT_GetRootPortStatus(FdoDeviceObject, header,
  541. (PRAW_ROOTPORT_PARAMETERS) (myIoBuffer+sizeof(*header)));
  542. }
  543. break;
  544. case USBUSER_OP_OPEN_RAW_DEVICE:
  545. // DCA api
  546. if (USBPORT_CheckLength(header, sizeof(USB_OPEN_RAW_DEVICE_PARAMETERS))) {
  547. USBPORT_UserOpenRawDevice(FdoDeviceObject, header,
  548. (PUSB_OPEN_RAW_DEVICE_PARAMETERS) (myIoBuffer+sizeof(*header)));
  549. }
  550. break;
  551. case USBUSER_OP_CLOSE_RAW_DEVICE:
  552. // DCA api
  553. if (USBPORT_CheckLength(header, sizeof(USB_CLOSE_RAW_DEVICE_PARAMETERS))) {
  554. USBPORT_UserCloseRawDevice(FdoDeviceObject, header,
  555. (PUSB_CLOSE_RAW_DEVICE_PARAMETERS) (myIoBuffer+sizeof(*header)));
  556. }
  557. break;
  558. case USBUSER_OP_SEND_RAW_COMMAND:
  559. // DCA api
  560. if (USBPORT_CheckLength(header, sizeof(USB_SEND_RAW_COMMAND_PARAMETERS))) {
  561. USBPORT_UserSendRawCommand(FdoDeviceObject, header,
  562. (PUSB_SEND_RAW_COMMAND_PARAMETERS) (myIoBuffer+sizeof(*header)));
  563. }
  564. break;
  565. case USBUSER_GET_CONTROLLER_INFO_0:
  566. if (USBPORT_CheckLength(header, sizeof(USB_CONTROLLER_INFO_0))) {
  567. USBPORT_UserGetControllerInfo_0(FdoDeviceObject, header,
  568. (PUSB_CONTROLLER_INFO_0) (myIoBuffer+sizeof(*header)));
  569. }
  570. break;
  571. case USBUSER_GET_CONTROLLER_DRIVER_KEY:
  572. if (USBPORT_CheckLength(header, sizeof(USB_UNICODE_NAME))) {
  573. USBPORT_UserGetControllerKey(FdoDeviceObject, header,
  574. (PUSB_UNICODE_NAME) (myIoBuffer+sizeof(*header)));
  575. }
  576. break;
  577. case USBUSER_GET_ROOTHUB_SYMBOLIC_NAME:
  578. if (USBPORT_CheckLength(header, sizeof(USB_UNICODE_NAME))) {
  579. USBPORT_UserGetRootHubName(FdoDeviceObject, header,
  580. (PUSB_UNICODE_NAME) (myIoBuffer+sizeof(*header)));
  581. }
  582. break;
  583. case USBUSER_PASS_THRU:
  584. if (USBPORT_CheckLength(header, sizeof(USB_PASS_THRU_PARAMETERS))) {
  585. USBPORT_UserPassThru(FdoDeviceObject, header,
  586. (PUSB_PASS_THRU_PARAMETERS) (myIoBuffer+sizeof(*header)));
  587. }
  588. break;
  589. case USBUSER_GET_BANDWIDTH_INFORMATION:
  590. if (USBPORT_CheckLength(header, sizeof(USB_BANDWIDTH_INFO))) {
  591. USBPORT_UserGetBandwidthInformation(FdoDeviceObject, header,
  592. (PUSB_BANDWIDTH_INFO) (myIoBuffer+sizeof(*header)));
  593. }
  594. break;
  595. case USBUSER_GET_POWER_STATE_MAP:
  596. if (USBPORT_CheckLength(header, sizeof(USB_POWER_INFO))) {
  597. USBPORT_UserPowerInformation(FdoDeviceObject, header,
  598. (PUSB_POWER_INFO) (myIoBuffer+sizeof(*header)));
  599. }
  600. break;
  601. case USBUSER_GET_BUS_STATISTICS_0:
  602. if (USBPORT_CheckLength(header, sizeof(USB_BUS_STATISTICS_0))) {
  603. USBPORT_UserGetBusStatistics0(FdoDeviceObject, header,
  604. (PUSB_BUS_STATISTICS_0) (myIoBuffer+sizeof(*header)));
  605. }
  606. break;
  607. // case USBUSER_GET_BUS_STATISTICS_0_AND_RESET:
  608. // if (USBPORT_CheckLength(header, sizeof(USB_BUS_STATISTICS_0))) {
  609. // USBPORT_UserGetBusStatistics0(FdoDeviceObject, header,
  610. // (PUSB_BUS_STATISTICS_0) (myIoBuffer+sizeof(*header)),
  611. // TRUE);
  612. // }
  613. // break;
  614. case USBUSER_GET_USB_DRIVER_VERSION:
  615. if (USBPORT_CheckLength(header, sizeof(USB_DRIVER_VERSION_PARAMETERS))) {
  616. USBPORT_UserGetDriverVersion(FdoDeviceObject, header,
  617. (PUSB_DRIVER_VERSION_PARAMETERS) (myIoBuffer+sizeof(*header)));
  618. }
  619. break;
  620. default:
  621. header->UsbUserStatusCode = UsbUserInvalidRequestCode;
  622. }
  623. // this will be at least the size of the header
  624. if (header->RequestBufferLength > header->ActualBufferLength) {
  625. // if the packet buffer is larger then just return 'actual length'
  626. *BytesReturned =
  627. header->ActualBufferLength;
  628. } else {
  629. // packet buffer is smaller -- return the size of the
  630. // packet buffer passed in
  631. *BytesReturned = header->RequestBufferLength;
  632. }
  633. USBPORT_UsbFdoUserIoctl_Done:
  634. if (alloced) {
  635. // copy the data no matter what we put in it
  636. // USBPORT_ASSERT(outputBufferLength == inputBufferLength);
  637. RtlCopyMemory(ioBufferO,
  638. myIoBuffer,
  639. outputBufferLength);
  640. FREE_POOL(FdoDeviceObject, myIoBuffer);
  641. }
  642. return ntStatus;
  643. }
  644. VOID
  645. USBPORT_UserSendOnePacket(
  646. PDEVICE_OBJECT FdoDeviceObject,
  647. PUSBUSER_REQUEST_HEADER Header,
  648. PPACKET_PARAMETERS PacketParameters
  649. )
  650. /*++
  651. Routine Description:
  652. Execute a single step transaction
  653. Arguments:
  654. DeviceObject - Fdo for USB HC
  655. Return Value:
  656. none.
  657. --*/
  658. {
  659. PDEVICE_EXTENSION devExt;
  660. USB_MINIPORT_STATUS mpStatus;
  661. HW_32BIT_PHYSICAL_ADDRESS phys;
  662. PUCHAR va, mpData;
  663. ULONG length, mpDataLength;
  664. MP_PACKET_PARAMETERS mpPacket;
  665. USBD_STATUS usbdStatus;
  666. USB_USER_ERROR_CODE usbUserStatus;
  667. USBPORT_KdPrint((2, "'USBPORT_UserSendOnePacket\n"));
  668. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  669. ASSERT_FDOEXT(devExt);
  670. // limit single packet to 64k
  671. if (PacketParameters->DataLength > 0x10000) {
  672. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Tbts', 0, 0,
  673. PacketParameters->DataLength);
  674. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  675. return;
  676. }
  677. if (PacketParameters->Timeout >= 21474) {
  678. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  679. return;
  680. }
  681. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  682. Header->UsbUserStatusCode = UsbUserFeatureDisabled;
  683. return;
  684. }
  685. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_SUSPENDED)) {
  686. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  687. return;
  688. }
  689. // extra length check is needed since we
  690. // have embedded data
  691. // if we get here we know packet parameters are valid
  692. length = sizeof(*Header) + sizeof(PACKET_PARAMETERS) - 4 +
  693. PacketParameters->DataLength;
  694. if (length > Header->RequestBufferLength) {
  695. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Tsma', length, 0,
  696. Header->RequestBufferLength);
  697. Header->UsbUserStatusCode = UsbUserBufferTooSmall;
  698. return;
  699. }
  700. Header->ActualBufferLength = length;
  701. usbUserStatus = UsbUserSuccess;
  702. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'ssPK', &mpPacket, 0,
  703. PacketParameters);
  704. // dump the PacketParameters
  705. USBPORT_KdPrint((1, "'DeviceAddress %d\n", PacketParameters->DeviceAddress));
  706. USBPORT_KdPrint((1, "'EndpointAddress %d\n", PacketParameters->EndpointAddress));
  707. USBPORT_KdPrint((1, "'MaximumPacketSize %d\n", PacketParameters->MaximumPacketSize));
  708. USBPORT_KdPrint((1, "'Flags %08.8x\n", PacketParameters->Flags));
  709. USBPORT_KdPrint((1, "'ErrorCount %d\n", PacketParameters->ErrorCount));
  710. // build up request for miniport
  711. length = devExt->Fdo.ScratchCommonBuffer->MiniportLength;
  712. va = devExt->Fdo.ScratchCommonBuffer->MiniportVa;
  713. phys = devExt->Fdo.ScratchCommonBuffer->MiniportPhys;
  714. mpPacket.DeviceAddress = PacketParameters->DeviceAddress;
  715. mpPacket.EndpointAddress = PacketParameters->EndpointAddress;
  716. mpPacket.MaximumPacketSize = PacketParameters->MaximumPacketSize;
  717. if (PacketParameters->Flags & USB_PACKETFLAG_SETUP) {
  718. mpPacket.Type = ss_Setup;
  719. } else if (PacketParameters->Flags & USB_PACKETFLAG_ASYNC_IN) {
  720. USBPORT_KdPrint((1, "'Async In\n"));
  721. mpPacket.Type = ss_In;
  722. } else if (PacketParameters->Flags & USB_PACKETFLAG_ASYNC_OUT) {
  723. USBPORT_KdPrint((1, "'Async Out\n"));
  724. mpPacket.Type = ss_Out;
  725. } else if (PacketParameters->Flags & USB_PACKETFLAG_ISO_IN) {
  726. USBPORT_KdPrint((1, "'Iso In\n"));
  727. mpPacket.Type = ss_Iso_In;
  728. } else if (PacketParameters->Flags & USB_PACKETFLAG_ISO_OUT) {
  729. USBPORT_KdPrint((1, "'Iso Out\n"));
  730. mpPacket.Type = ss_Iso_Out;
  731. } else {
  732. usbUserStatus = UsbUserInvalidParameter;
  733. }
  734. if (PacketParameters->Flags & USB_PACKETFLAG_LOW_SPEED) {
  735. USBPORT_KdPrint((1, "'LowSpeed\n"));
  736. mpPacket.Speed = ss_Low;
  737. mpPacket.HubDeviceAddress = PacketParameters->HubDeviceAddress;
  738. mpPacket.PortTTNumber = PacketParameters->PortTTNumber;
  739. } else if (PacketParameters->Flags & USB_PACKETFLAG_FULL_SPEED) {
  740. USBPORT_KdPrint((1, "'FullSpeed\n"));
  741. mpPacket.Speed = ss_Full;
  742. mpPacket.HubDeviceAddress = PacketParameters->HubDeviceAddress;
  743. mpPacket.PortTTNumber = PacketParameters->PortTTNumber;
  744. } else if (PacketParameters->Flags & USB_PACKETFLAG_HIGH_SPEED) {
  745. USBPORT_KdPrint((1, "'HighSpeed\n"));
  746. mpPacket.Speed = ss_High;
  747. } else {
  748. usbUserStatus = UsbUserInvalidParameter;
  749. }
  750. if (PacketParameters->Flags & USB_PACKETFLAG_TOGGLE0) {
  751. USBPORT_KdPrint((1, "'Toggle0\n"));
  752. mpPacket.Toggle = ss_Toggle0;
  753. } else if (PacketParameters->Flags & USB_PACKETFLAG_TOGGLE1) {
  754. USBPORT_KdPrint((1, "'Toggle1\n"));
  755. mpPacket.Toggle = ss_Toggle1;
  756. } else {
  757. usbUserStatus = UsbUserInvalidParameter;
  758. }
  759. if (usbUserStatus == UsbUserSuccess) {
  760. mpData = &PacketParameters->Data[0];
  761. mpDataLength = PacketParameters->DataLength;
  762. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'ssDT', mpData, mpDataLength, 0);
  763. MP_StartSendOnePacket(devExt,
  764. &mpPacket,
  765. mpData,
  766. &mpDataLength,
  767. va,
  768. phys,
  769. length,
  770. &usbdStatus,
  771. mpStatus);
  772. if (USBMP_STATUS_SUCCESS != mpStatus) {
  773. usbUserStatus = UsbUserMiniportError;
  774. goto USBPORT_UserSendOnePacket_Exit;
  775. }
  776. do {
  777. // wait 10 ms
  778. USBPORT_Wait(FdoDeviceObject, 10);
  779. // wait a user specified time
  780. if (PacketParameters->Timeout) {
  781. USBPORT_Wait(FdoDeviceObject, PacketParameters->Timeout);
  782. }
  783. MP_EndSendOnePacket(devExt,
  784. &mpPacket,
  785. mpData,
  786. &mpDataLength,
  787. va,
  788. phys,
  789. length,
  790. &usbdStatus,
  791. mpStatus);
  792. } while (USBMP_STATUS_BUSY == mpStatus);
  793. // allow one frame to pass before continuing
  794. USBPORT_Wait(FdoDeviceObject, 1);
  795. PacketParameters->DataLength = mpDataLength;
  796. PacketParameters->UsbdStatusCode = usbdStatus;
  797. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'ssDE', mpData, mpDataLength,
  798. PacketParameters);
  799. }
  800. USBPORT_UserSendOnePacket_Exit:
  801. Header->UsbUserStatusCode = usbUserStatus;
  802. }
  803. VOID
  804. USBPORT_UserRawResetPort(
  805. PDEVICE_OBJECT FdoDeviceObject,
  806. PUSBUSER_REQUEST_HEADER Header,
  807. PRAW_RESET_PORT_PARAMETERS Parameters
  808. )
  809. /*++
  810. Routine Description:
  811. Cycle a specific Root Port
  812. Arguments:
  813. DeviceObject - Fdo for USB HC
  814. Return Value:
  815. none.
  816. --*/
  817. {
  818. PDEVICE_EXTENSION devExt;
  819. USB_MINIPORT_STATUS mpStatus;
  820. USB_USER_ERROR_CODE usbUserStatus;
  821. RH_PORT_STATUS portStatus;
  822. ULONG loopCount;
  823. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  824. ASSERT_FDOEXT(devExt);
  825. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort, %x\n", devExt));
  826. usbUserStatus = UsbUserSuccess;
  827. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Rrsp', 0, 0, Parameters->PortNumber);
  828. if (!USBPORT_ValidateRootPortApi(FdoDeviceObject, Parameters->PortNumber)) {
  829. Header->UsbUserStatusCode =
  830. usbUserStatus = UsbUserInvalidParameter;
  831. return;
  832. }
  833. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  834. Header->UsbUserStatusCode = UsbUserFeatureDisabled;
  835. return;
  836. }
  837. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort: Setting port power\n"));
  838. // power the port
  839. devExt->Fdo.MiniportDriver->
  840. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  841. devExt->Fdo.MiniportDeviceData,
  842. Parameters->PortNumber);
  843. //
  844. // Wait the required time for the port power to stabilize.
  845. //
  846. // 512ms --> Max port power to power good time for root hub
  847. // 100ms --> Max time for device to have power stabilize
  848. //
  849. // After this time, the device must have signalled connect on the device
  850. //
  851. USBPORT_Wait( FdoDeviceObject, 612 );
  852. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  853. &portStatus, mpStatus);
  854. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort: Port status = %x\n",
  855. portStatus ));
  856. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Rrs1', 0, 0,
  857. (ULONG_PTR) portStatus.ul);
  858. //
  859. // Device should have signalled connect, if not, it's an error.
  860. //
  861. if ( portStatus.Connected )
  862. {
  863. //
  864. // Provide another 100ms for debounce interval.
  865. //
  866. USBPORT_Wait( FdoDeviceObject, 100 );
  867. //
  868. // Reset the device
  869. //
  870. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort: Setting port reset\n"));
  871. // attempt a reset
  872. mpStatus = devExt->Fdo.MiniportDriver->
  873. RegistrationPacket.MINIPORT_RH_SetFeaturePortReset(
  874. devExt->Fdo.MiniportDeviceData,
  875. Parameters->PortNumber);
  876. //
  877. // wait for reset change, this process is drive by the
  878. // HC root hub hardware or miniport
  879. //
  880. loopCount = 0;
  881. USBPORT_Wait( FdoDeviceObject, 20 );
  882. MPRH_GetPortStatus(devExt,
  883. (USHORT)(Parameters->PortNumber), &portStatus, mpStatus);
  884. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Rrs2', 0, 0,
  885. (ULONG_PTR) portStatus.ul);
  886. //
  887. // Some hubs seem to be taking longer than 20 ms to signal reset change
  888. // This is a loop to give it up to another 20ms.
  889. //
  890. while ( !portStatus.ResetChange && loopCount < 20 )
  891. {
  892. loopCount++;
  893. USBPORT_Wait( FdoDeviceObject, 1 );
  894. MPRH_GetPortStatus(devExt,
  895. (USHORT)(Parameters->PortNumber), &portStatus, mpStatus);
  896. }
  897. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort: loopCount = %d\n",
  898. loopCount));
  899. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Rrs3', 0, loopCount,
  900. (ULONG_PTR) portStatus.ul);
  901. if ( portStatus.ResetChange )
  902. {
  903. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort: Clearing reset "
  904. "change\n"));
  905. // clear the change bit
  906. mpStatus = devExt->Fdo.MiniportDriver->
  907. RegistrationPacket.MINIPORT_RH_ClearFeaturePortResetChange(
  908. devExt->Fdo.MiniportDeviceData,
  909. Parameters->PortNumber);
  910. MPRH_GetPortStatus( devExt,
  911. (USHORT) (Parameters->PortNumber),
  912. &portStatus,
  913. mpStatus );
  914. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Rrs4', 0, 0,
  915. (ULONG_PTR) portStatus.ul);
  916. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort: Port status = %x\n",
  917. portStatus ));
  918. //
  919. // Wait an additional 10 seconds for device reset recovery
  920. //
  921. USBPORT_Wait( FdoDeviceObject, 10 );
  922. }
  923. else
  924. {
  925. USBPORT_KdPrint((2,
  926. "'USBPORT_UserRawResetPort: reset change not set\n"
  927. "'PortStatus = 0x%x\n", portStatus.ul));
  928. TEST_TRAP();
  929. }
  930. } else {
  931. usbUserStatus = UsbUserNoDeviceConnected;
  932. }
  933. // status is low 16 bits
  934. Parameters->PortStatus = (USHORT) portStatus.ul;
  935. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Rrs>', 0, portStatus.ul,
  936. usbUserStatus);
  937. Header->UsbUserStatusCode = usbUserStatus;
  938. }
  939. VOID
  940. USBPORT_GetRootPortStatus(
  941. PDEVICE_OBJECT FdoDeviceObject,
  942. PUSBUSER_REQUEST_HEADER Header,
  943. PRAW_ROOTPORT_PARAMETERS Parameters
  944. )
  945. /*++
  946. Routine Description:
  947. Cycle a specific Root Port
  948. Arguments:
  949. DeviceObject - Fdo for USB HC
  950. Return Value:
  951. none.
  952. --*/
  953. {
  954. PDEVICE_EXTENSION devExt;
  955. USB_MINIPORT_STATUS mpStatus;
  956. USB_USER_ERROR_CODE usbUserStatus;
  957. USBPRIV_ROOTPORT_STATUS portStatusInfo;
  958. USBPORT_KdPrint((2, "'USBPORT_GetRootPortStatus\n"));
  959. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  960. ASSERT_FDOEXT(devExt);
  961. usbUserStatus = UsbUserSuccess;
  962. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'gRPs', 0, 0, Parameters->PortNumber);
  963. if (!USBPORT_ValidateRootPortApi(FdoDeviceObject, Parameters->PortNumber)) {
  964. Header->UsbUserStatusCode =
  965. usbUserStatus = UsbUserInvalidParameter;
  966. return;
  967. }
  968. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  969. Header->UsbUserStatusCode = UsbUserFeatureDisabled;
  970. return;
  971. }
  972. portStatusInfo.PortNumber = (USHORT) Parameters->PortNumber;
  973. portStatusInfo.PortStatus.ul = 0;
  974. MP_PassThru(devExt,
  975. (LPGUID) &GUID_USBPRIV_ROOTPORT_STATUS,
  976. sizeof(portStatusInfo),
  977. &portStatusInfo, // Info,
  978. mpStatus);
  979. if (USBMP_STATUS_NOT_SUPPORTED == mpStatus) {
  980. MPRH_GetPortStatus(devExt, portStatusInfo.PortNumber,
  981. &(portStatusInfo.PortStatus), mpStatus);
  982. }
  983. // status is low 16 bits
  984. Parameters->PortStatus = (USHORT) portStatusInfo.PortStatus.ul;
  985. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'gRP>', 0, 0, usbUserStatus);
  986. Header->UsbUserStatusCode = usbUserStatus;
  987. }
  988. VOID
  989. USBPORT_UserGetControllerInfo_0(
  990. PDEVICE_OBJECT FdoDeviceObject,
  991. PUSBUSER_REQUEST_HEADER Header,
  992. PUSB_CONTROLLER_INFO_0 ControllerInfo_0
  993. )
  994. /*++
  995. Routine Description:
  996. Execute a single step transaction
  997. Arguments:
  998. DeviceObject - Fdo for USB HC
  999. Return Value:
  1000. none.
  1001. --*/
  1002. {
  1003. PDEVICE_EXTENSION devExt;
  1004. ROOTHUB_DATA hubData;
  1005. RH_HUB_CHARATERISTICS rhChars;
  1006. USBPORT_KdPrint((2, "'USBPORT_UserGetControllerInfo_0\n"));
  1007. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1008. ASSERT_FDOEXT(devExt);
  1009. ControllerInfo_0->HcFeatureFlags = 0;
  1010. MPRH_GetRootHubData(devExt, &hubData);
  1011. ControllerInfo_0->NumberOfRootPorts =
  1012. hubData.NumberOfPorts;
  1013. rhChars.us = hubData.HubCharacteristics.us;
  1014. if (rhChars.PowerSwitchType == USBPORT_RH_POWER_SWITCH_PORT) {
  1015. ControllerInfo_0->HcFeatureFlags |=
  1016. USB_HC_FEATURE_FLAG_PORT_POWER_SWITCHING;
  1017. }
  1018. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_RH_CAN_SUSPEND)) {
  1019. ControllerInfo_0->HcFeatureFlags |=
  1020. USB_HC_FEATURE_FLAG_SEL_SUSPEND;
  1021. }
  1022. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_LEGACY_BIOS)) {
  1023. ControllerInfo_0->HcFeatureFlags |=
  1024. USB_HC_FEATURE_LEGACY_BIOS;
  1025. }
  1026. ControllerInfo_0->PciVendorId =
  1027. devExt->Fdo.PciVendorId;
  1028. ControllerInfo_0->PciDeviceId =
  1029. devExt->Fdo.PciDeviceId;
  1030. ControllerInfo_0->PciRevision =
  1031. (UCHAR) devExt->Fdo.PciRevisionId;
  1032. ControllerInfo_0->ControllerFlavor =
  1033. devExt->Fdo.HcFlavor;
  1034. Header->UsbUserStatusCode =
  1035. UsbUserSuccess;
  1036. }
  1037. VOID
  1038. USBPORT_UserGetControllerKey(
  1039. PDEVICE_OBJECT FdoDeviceObject,
  1040. PUSBUSER_REQUEST_HEADER Header,
  1041. PUSB_UNICODE_NAME ControllerKey
  1042. )
  1043. /*++
  1044. Routine Description:
  1045. Returns the Driver key associated with this symbolic link for the
  1046. host controller.
  1047. Arguments:
  1048. DeviceObject - Fdo for USB HC
  1049. Return Value:
  1050. none.
  1051. --*/
  1052. {
  1053. PDEVICE_EXTENSION devExt;
  1054. NTSTATUS ntStatus;
  1055. ULONG userLength, actualLength;
  1056. USBPORT_KdPrint((2, "'USBPORT_UserGetControllerKey\n"));
  1057. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1058. ASSERT_FDOEXT(devExt);
  1059. // we should not get here unl;ess this hold true
  1060. USBPORT_ASSERT(Header->RequestBufferLength >=
  1061. sizeof(USB_UNICODE_NAME)+sizeof(*Header));
  1062. // userlength
  1063. userLength = Header->RequestBufferLength - sizeof(*Header)
  1064. - sizeof(USB_UNICODE_NAME);
  1065. // note: this will cause us to return a NULL terminated
  1066. // key
  1067. RtlZeroMemory(ControllerKey, userLength);
  1068. ntStatus = IoGetDeviceProperty(
  1069. devExt->Fdo.PhysicalDeviceObject,
  1070. DevicePropertyDriverKeyName,
  1071. userLength,
  1072. &ControllerKey->String[0],
  1073. &actualLength);
  1074. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'dKEY', &ControllerKey->String[0], userLength,
  1075. actualLength);
  1076. if (NT_SUCCESS(ntStatus)) {
  1077. Header->UsbUserStatusCode = UsbUserSuccess;
  1078. ControllerKey->Length = actualLength + sizeof(UNICODE_NULL);
  1079. } else if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  1080. Header->UsbUserStatusCode = UsbUserBufferTooSmall;
  1081. } else {
  1082. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  1083. }
  1084. Header->ActualBufferLength =
  1085. actualLength+sizeof(*Header)+sizeof(USB_UNICODE_NAME);
  1086. }
  1087. VOID
  1088. USBPORT_UserGetRootHubName(
  1089. PDEVICE_OBJECT FdoDeviceObject,
  1090. PUSBUSER_REQUEST_HEADER Header,
  1091. PUSB_UNICODE_NAME RootHubName
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. Returns the Driver key associated with this symbolic link for the
  1096. host controller.
  1097. Arguments:
  1098. DeviceObject - Fdo for USB HC
  1099. Return Value:
  1100. none.
  1101. --*/
  1102. {
  1103. PDEVICE_EXTENSION devExt;
  1104. NTSTATUS ntStatus;
  1105. ULONG userLength, actualLength;
  1106. UNICODE_STRING hubNameUnicodeString;
  1107. USBPORT_KdPrint((2, "'USBPORT_UserGetRootHubName\n"));
  1108. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1109. ASSERT_FDOEXT(devExt);
  1110. // we should not get here unl;ess this hold true
  1111. USBPORT_ASSERT(Header->RequestBufferLength >=
  1112. sizeof(USB_UNICODE_NAME)+sizeof(*Header));
  1113. // userlength
  1114. userLength = Header->RequestBufferLength - sizeof(*Header)
  1115. - sizeof(USB_UNICODE_NAME);
  1116. // note: this will cause us to return a NULL terminated
  1117. // key
  1118. RtlZeroMemory(RootHubName, userLength);
  1119. ntStatus = USBPORT_GetSymbolicName(FdoDeviceObject,
  1120. devExt->Fdo.RootHubPdo,
  1121. &hubNameUnicodeString);
  1122. actualLength = 0;
  1123. if (NT_SUCCESS(ntStatus)) {
  1124. ULONG n;
  1125. actualLength = hubNameUnicodeString.Length;
  1126. n = hubNameUnicodeString.Length;
  1127. if (n > userLength) {
  1128. n = userLength;
  1129. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1130. }
  1131. if (n) {
  1132. RtlCopyMemory(&RootHubName->String[0],
  1133. hubNameUnicodeString.Buffer,
  1134. n);
  1135. }
  1136. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Huns',
  1137. &hubNameUnicodeString, 0, 0);
  1138. RtlFreeUnicodeString(&hubNameUnicodeString);
  1139. }
  1140. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'gHNM', ntStatus, userLength,
  1141. actualLength);
  1142. if (NT_SUCCESS(ntStatus)) {
  1143. Header->UsbUserStatusCode = UsbUserSuccess;
  1144. RootHubName->Length = actualLength + sizeof(UNICODE_NULL);
  1145. } else if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  1146. Header->UsbUserStatusCode = UsbUserBufferTooSmall;
  1147. } else {
  1148. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  1149. }
  1150. Header->ActualBufferLength =
  1151. actualLength+sizeof(*Header)+sizeof(USB_UNICODE_NAME);
  1152. }
  1153. VOID
  1154. USBPORT_UserPassThru(
  1155. PDEVICE_OBJECT FdoDeviceObject,
  1156. PUSBUSER_REQUEST_HEADER Header,
  1157. PUSB_PASS_THRU_PARAMETERS PassThru
  1158. )
  1159. /*++
  1160. Routine Description:
  1161. Handles pass-thru apis for the Miniport
  1162. Arguments:
  1163. DeviceObject - Fdo for USB HC
  1164. Return Value:
  1165. none.
  1166. --*/
  1167. {
  1168. PDEVICE_EXTENSION devExt;
  1169. NTSTATUS ntStatus;
  1170. ULONG userLength, actualLength, length;
  1171. USB_MINIPORT_STATUS mpStatus;
  1172. ULONG parameterLength;
  1173. USBPORT_KdPrint((2, "'USBPORT_UserPassThru\n"));
  1174. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1175. ASSERT_FDOEXT(devExt);
  1176. // we should not get here unless this hold true
  1177. USBPORT_ASSERT(Header->RequestBufferLength >=
  1178. sizeof(USB_PASS_THRU_PARAMETERS)+sizeof(*Header));
  1179. // limit pass thru blocks to 64k
  1180. if (PassThru->ParameterLength > 0x10000) {
  1181. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  1182. return;
  1183. }
  1184. // extra length check is needed since we
  1185. // have embedded data
  1186. // if we get here we know packet parameters are valid
  1187. length = sizeof(*Header) + sizeof(USB_PASS_THRU_PARAMETERS) - 4 +
  1188. PassThru->ParameterLength;
  1189. if (length > Header->RequestBufferLength) {
  1190. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Tsma', length, 0,
  1191. Header->RequestBufferLength);
  1192. Header->UsbUserStatusCode = UsbUserBufferTooSmall;
  1193. return;
  1194. }
  1195. // userlength
  1196. parameterLength = PassThru->ParameterLength;
  1197. Header->ActualBufferLength =
  1198. sizeof(*Header)+sizeof(USB_PASS_THRU_PARAMETERS) +
  1199. parameterLength;
  1200. // call the miniport
  1201. MP_PassThru(devExt,
  1202. &PassThru->FunctionGUID,
  1203. parameterLength,
  1204. &PassThru->Parameters,
  1205. mpStatus);
  1206. if (mpStatus == USBMP_STATUS_SUCCESS) {
  1207. Header->UsbUserStatusCode = UsbUserSuccess;
  1208. USBPORT_KdPrint((1, "'USBPORT_UserPassThru Success\n"));
  1209. } else {
  1210. Header->UsbUserStatusCode = UsbUserMiniportError;
  1211. USBPORT_KdPrint((1, "'USBPORT_UserPassThru Error\n"));
  1212. }
  1213. }
  1214. WDMUSB_POWER_STATE
  1215. WdmUsbSystemPowerState(
  1216. SYSTEM_POWER_STATE SystemPowerState
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. Arguments:
  1221. Return Value:
  1222. WDMUSB_POWER_STATE that matches the WDM power state passed in
  1223. --*/
  1224. {
  1225. switch(SystemPowerState) {
  1226. case PowerSystemWorking:
  1227. return WdmUsbPowerSystemWorking;
  1228. case PowerSystemSleeping1:
  1229. return WdmUsbPowerSystemSleeping1;
  1230. case PowerSystemSleeping2:
  1231. return WdmUsbPowerSystemSleeping2;
  1232. case PowerSystemSleeping3:
  1233. return WdmUsbPowerSystemSleeping3;
  1234. case PowerSystemHibernate:
  1235. return WdmUsbPowerSystemHibernate;
  1236. case PowerSystemShutdown:
  1237. return WdmUsbPowerSystemShutdown;
  1238. }
  1239. return WdmUsbPowerNotMapped;
  1240. }
  1241. WDMUSB_POWER_STATE
  1242. WdmUsbDevicePowerState(
  1243. DEVICE_POWER_STATE DevicePowerState
  1244. )
  1245. /*++
  1246. Routine Description:
  1247. Arguments:
  1248. Return Value:
  1249. WDMUSB_POWER_STATE that matches the WDM power state passed in
  1250. --*/
  1251. {
  1252. switch(DevicePowerState) {
  1253. case PowerDeviceUnspecified:
  1254. return WdmUsbPowerDeviceUnspecified;
  1255. case PowerDeviceD0:
  1256. return WdmUsbPowerDeviceD0;
  1257. case PowerDeviceD1:
  1258. return WdmUsbPowerDeviceD1;
  1259. case PowerDeviceD2:
  1260. return WdmUsbPowerDeviceD2;
  1261. case PowerDeviceD3:
  1262. return WdmUsbPowerDeviceD3;
  1263. }
  1264. return WdmUsbPowerNotMapped;
  1265. }
  1266. VOID
  1267. USBPORT_MapPowerStateInformation(
  1268. PDEVICE_OBJECT FdoDeviceObject,
  1269. PUSB_POWER_INFO PowerInformation,
  1270. PDEVICE_CAPABILITIES HcCaps,
  1271. PDEVICE_CAPABILITIES RhCaps
  1272. )
  1273. /*++
  1274. Routine Description:
  1275. Arguments:
  1276. Return Value:
  1277. none.
  1278. --*/
  1279. {
  1280. PHC_POWER_STATE hcPowerState = NULL;
  1281. PDEVICE_EXTENSION devExt;
  1282. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1283. ASSERT_FDOEXT(devExt);
  1284. PowerInformation->RhDeviceWake =
  1285. WdmUsbDevicePowerState(RhCaps->DeviceWake);
  1286. PowerInformation->RhSystemWake =
  1287. WdmUsbSystemPowerState(RhCaps->SystemWake);
  1288. PowerInformation->HcDeviceWake =
  1289. WdmUsbDevicePowerState(HcCaps->DeviceWake);
  1290. PowerInformation->HcSystemWake =
  1291. WdmUsbSystemPowerState(HcCaps->SystemWake);
  1292. switch (PowerInformation->SystemState) {
  1293. case WdmUsbPowerSystemWorking:
  1294. PowerInformation->RhDevicePowerState =
  1295. WdmUsbDevicePowerState(RhCaps->DeviceState[PowerSystemWorking]);
  1296. PowerInformation->HcDevicePowerState =
  1297. WdmUsbDevicePowerState(HcCaps->DeviceState[PowerSystemWorking]);
  1298. // hcPowerState = USBPORT_GetHcPowerState(FdoDeviceObject,
  1299. // PowerSystemWorking);
  1300. break;
  1301. case WdmUsbPowerSystemSleeping1:
  1302. PowerInformation->RhDevicePowerState =
  1303. WdmUsbDevicePowerState(RhCaps->DeviceState[PowerSystemSleeping1]);
  1304. PowerInformation->HcDevicePowerState =
  1305. WdmUsbDevicePowerState(HcCaps->DeviceState[PowerSystemSleeping1]);
  1306. hcPowerState = USBPORT_GetHcPowerState(FdoDeviceObject,
  1307. &devExt->Fdo.HcPowerStateTbl,
  1308. PowerSystemSleeping1);
  1309. break;
  1310. case WdmUsbPowerSystemSleeping2:
  1311. PowerInformation->RhDevicePowerState =
  1312. WdmUsbDevicePowerState(RhCaps->DeviceState[PowerSystemSleeping2]);
  1313. PowerInformation->HcDevicePowerState =
  1314. WdmUsbDevicePowerState(HcCaps->DeviceState[PowerSystemSleeping2]);
  1315. hcPowerState = USBPORT_GetHcPowerState(FdoDeviceObject,
  1316. &devExt->Fdo.HcPowerStateTbl,
  1317. PowerSystemSleeping2);
  1318. break;
  1319. case WdmUsbPowerSystemSleeping3:
  1320. PowerInformation->RhDevicePowerState =
  1321. WdmUsbDevicePowerState(RhCaps->DeviceState[PowerSystemSleeping3]);
  1322. PowerInformation->HcDevicePowerState =
  1323. WdmUsbDevicePowerState(HcCaps->DeviceState[PowerSystemSleeping3]);
  1324. hcPowerState = USBPORT_GetHcPowerState(FdoDeviceObject,
  1325. &devExt->Fdo.HcPowerStateTbl,
  1326. PowerSystemSleeping3);
  1327. break;
  1328. case WdmUsbPowerSystemHibernate:
  1329. PowerInformation->RhDevicePowerState =
  1330. WdmUsbDevicePowerState(RhCaps->DeviceState[PowerSystemHibernate]);
  1331. PowerInformation->HcDevicePowerState =
  1332. WdmUsbDevicePowerState(HcCaps->DeviceState[PowerSystemHibernate]);
  1333. hcPowerState = USBPORT_GetHcPowerState(FdoDeviceObject,
  1334. &devExt->Fdo.HcPowerStateTbl,
  1335. PowerSystemHibernate);
  1336. break;
  1337. }
  1338. if (hcPowerState != NULL) {
  1339. switch(hcPowerState->Attributes) {
  1340. case HcPower_Y_Wakeup_Y:
  1341. PowerInformation->CanWakeup = 1;
  1342. PowerInformation->IsPowered = 1;
  1343. break;
  1344. case HcPower_N_Wakeup_N:
  1345. PowerInformation->CanWakeup = 0;
  1346. PowerInformation->IsPowered = 0;
  1347. break;
  1348. case HcPower_Y_Wakeup_N:
  1349. PowerInformation->CanWakeup = 0;
  1350. PowerInformation->IsPowered = 1;
  1351. break;
  1352. case HcPower_N_Wakeup_Y:
  1353. PowerInformation->CanWakeup = 1;
  1354. PowerInformation->IsPowered = 0;
  1355. break;
  1356. }
  1357. } else {
  1358. PowerInformation->CanWakeup = 0;
  1359. PowerInformation->IsPowered = 0;
  1360. }
  1361. PowerInformation->LastSystemSleepState =
  1362. WdmUsbSystemPowerState(devExt->Fdo.LastSystemSleepState);
  1363. }
  1364. VOID
  1365. USBPORT_UserPowerInformation(
  1366. PDEVICE_OBJECT FdoDeviceObject,
  1367. PUSBUSER_REQUEST_HEADER Header,
  1368. PUSB_POWER_INFO PowerInformation
  1369. )
  1370. /*++
  1371. Routine Description:
  1372. Handles power info API
  1373. Arguments:
  1374. DeviceObject - Fdo for USB HC
  1375. Return Value:
  1376. none.
  1377. --*/
  1378. {
  1379. PDEVICE_EXTENSION devExt, rhDevExt;
  1380. PDEVICE_CAPABILITIES hcDeviceCaps, rhDeviceCaps;
  1381. USBPORT_KdPrint((2, "'USBPORT_UserPowerInformation\n"));
  1382. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1383. ASSERT_FDOEXT(devExt);
  1384. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  1385. ASSERT_PDOEXT(rhDevExt);
  1386. // BUGBUG this api should fail if we are not started
  1387. if (!TEST_FLAG(rhDevExt->PnpStateFlags, USBPORT_PNP_STARTED)) {
  1388. Header->ActualBufferLength =
  1389. sizeof(*Header)+sizeof(USB_POWER_INFO);
  1390. Header->UsbUserStatusCode = UsbUserDeviceNotStarted;
  1391. return;
  1392. }
  1393. rhDeviceCaps = &rhDevExt->DeviceCapabilities;
  1394. hcDeviceCaps = &devExt->DeviceCapabilities;
  1395. // we should not get here unless this holds true
  1396. USBPORT_ASSERT(Header->RequestBufferLength >=
  1397. sizeof(USB_POWER_INFO)+sizeof(*Header));
  1398. USBPORT_MapPowerStateInformation(
  1399. FdoDeviceObject,
  1400. PowerInformation,
  1401. hcDeviceCaps,
  1402. rhDeviceCaps);
  1403. Header->ActualBufferLength =
  1404. sizeof(*Header)+sizeof(USB_POWER_INFO);
  1405. }
  1406. VOID
  1407. USBPORT_UserOpenRawDevice(
  1408. PDEVICE_OBJECT FdoDeviceObject,
  1409. PUSBUSER_REQUEST_HEADER Header,
  1410. PUSB_OPEN_RAW_DEVICE_PARAMETERS Parameters
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Arguments:
  1415. DeviceObject - Fdo for USB HC
  1416. Return Value:
  1417. none.
  1418. --*/
  1419. {
  1420. PDEVICE_EXTENSION devExt;
  1421. NTSTATUS ntStatus;
  1422. USB_USER_ERROR_CODE usbUserStatus;
  1423. USHORT portStatus;
  1424. USBPORT_KdPrint((2, "'USBPORT_OpenRawDevice\n"));
  1425. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1426. ASSERT_FDOEXT(devExt);
  1427. usbUserStatus = UsbUserSuccess;
  1428. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  1429. usbUserStatus = UsbUserFeatureDisabled;
  1430. goto USBPORT_UserOpenRawDevice_Done;
  1431. }
  1432. // fail request if open
  1433. if (devExt->Fdo.RawDeviceHandle) {
  1434. usbUserStatus = UsbUserInvalidParameter;
  1435. goto USBPORT_UserOpenRawDevice_Done;
  1436. }
  1437. // fabricate port status
  1438. portStatus = Parameters->PortStatus;
  1439. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'oRAW', 0, 0, portStatus);
  1440. // we assume that a device is connected here, we just create
  1441. // a raw handle to it, nothing more.
  1442. //
  1443. // everything else must be handled by the caller.
  1444. ntStatus = USBPORT_CreateDevice(&devExt->Fdo.RawDeviceHandle,
  1445. FdoDeviceObject,
  1446. NULL,
  1447. portStatus,
  1448. 0);
  1449. if (NT_SUCCESS(ntStatus)) {
  1450. // mark this device handle as 'special'
  1451. SET_FLAG(devExt->Fdo.RawDeviceHandle->DeviceFlags,
  1452. USBPORT_DEVICEFLAG_RAWHANDLE);
  1453. Parameters->MaxPacketEp0 =
  1454. devExt->Fdo.RawDeviceHandle->DeviceDescriptor.bMaxPacketSize0;
  1455. }
  1456. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'oRAs', 0, 0, ntStatus);
  1457. usbUserStatus =
  1458. USBPORT_NtStatus_TO_UsbUserStatus(ntStatus);
  1459. USBPORT_UserOpenRawDevice_Done:
  1460. Header->UsbUserStatusCode = usbUserStatus;
  1461. }
  1462. VOID
  1463. USBPORT_UserCloseRawDevice(
  1464. PDEVICE_OBJECT FdoDeviceObject,
  1465. PUSBUSER_REQUEST_HEADER Header,
  1466. PUSB_CLOSE_RAW_DEVICE_PARAMETERS Parameters
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. Arguments:
  1471. DeviceObject - Fdo for USB HC
  1472. Return Value:
  1473. none.
  1474. --*/
  1475. {
  1476. PDEVICE_EXTENSION devExt;
  1477. USB_MINIPORT_STATUS mpStatus;
  1478. USB_USER_ERROR_CODE usbUserStatus;
  1479. NTSTATUS ntStatus;
  1480. USBPORT_KdPrint((2, "'USBPORT_UserCloseRawDevice\n"));
  1481. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1482. ASSERT_FDOEXT(devExt);
  1483. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  1484. usbUserStatus = UsbUserFeatureDisabled;
  1485. goto USBPORT_UserCloseRawDevice_Done;
  1486. }
  1487. // fail request if closed
  1488. if (devExt->Fdo.RawDeviceHandle == NULL) {
  1489. usbUserStatus = UsbUserInvalidParameter;
  1490. goto USBPORT_UserCloseRawDevice_Done;
  1491. }
  1492. usbUserStatus = UsbUserSuccess;
  1493. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'cRAW', 0, 0, 0);
  1494. ntStatus =
  1495. USBPORT_RemoveDevice(devExt->Fdo.RawDeviceHandle,
  1496. FdoDeviceObject,
  1497. 0);
  1498. devExt->Fdo.RawDeviceHandle = NULL;
  1499. // in this particular case the API should not fail
  1500. USBPORT_ASSERT(ntStatus == STATUS_SUCCESS);
  1501. USBPORT_UserCloseRawDevice_Done:
  1502. Header->UsbUserStatusCode = usbUserStatus;
  1503. }
  1504. VOID
  1505. USBPORT_UserSendRawCommand(
  1506. PDEVICE_OBJECT FdoDeviceObject,
  1507. PUSBUSER_REQUEST_HEADER Header,
  1508. PUSB_SEND_RAW_COMMAND_PARAMETERS Parameters
  1509. )
  1510. /*++
  1511. Routine Description:
  1512. Arguments:
  1513. DeviceObject - Fdo for USB HC
  1514. Return Value:
  1515. none.
  1516. --*/
  1517. {
  1518. PDEVICE_EXTENSION devExt;
  1519. USB_MINIPORT_STATUS mpStatus;
  1520. USB_USER_ERROR_CODE usbUserStatus;
  1521. USB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
  1522. PUSBD_PIPE_HANDLE_I defaultPipe;
  1523. NTSTATUS ntStatus;
  1524. ULONG length;
  1525. USBPORT_KdPrint((2, "'USBPORT_UserSendRawCommand\n"));
  1526. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1527. ASSERT_FDOEXT(devExt);
  1528. usbUserStatus = UsbUserSuccess;
  1529. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'sRAW', 0, 0, 0);
  1530. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  1531. Header->UsbUserStatusCode = UsbUserFeatureDisabled;
  1532. return;
  1533. }
  1534. // fail request if closed
  1535. if (devExt->Fdo.RawDeviceHandle == NULL) {
  1536. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  1537. return;
  1538. }
  1539. // a control transfer can be up 0 to 64k
  1540. if (Parameters->DataLength > 0x10000) {
  1541. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Tbts', 0, 0,
  1542. Parameters->DataLength);
  1543. Header->UsbUserStatusCode = UsbUserInvalidParameter;
  1544. return;
  1545. }
  1546. // extra length check is needed sinve we
  1547. // have embedded data
  1548. // if we get here we know packet parameters are valid
  1549. length = sizeof(*Header) + sizeof(USB_SEND_RAW_COMMAND_PARAMETERS) - 4 +
  1550. Parameters->DataLength;
  1551. // length is the area of the buffer we may reference
  1552. if (length > Header->RequestBufferLength) {
  1553. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'Tsma', length, 0,
  1554. Header->RequestBufferLength);
  1555. Header->UsbUserStatusCode = UsbUserBufferTooSmall;
  1556. return;
  1557. }
  1558. Header->ActualBufferLength = length;
  1559. setupPacket.bmRequestType.B = Parameters->Usb_bmRequest;
  1560. setupPacket.bRequest = Parameters->Usb_bRequest;
  1561. setupPacket.wValue.W = Parameters->Usb_wVlaue;
  1562. setupPacket.wIndex.W = Parameters->Usb_wIndex;
  1563. setupPacket.wLength = Parameters->Usb_wLength;
  1564. // if address is different then we will need to
  1565. // poke the endpoint
  1566. defaultPipe = &devExt->Fdo.RawDeviceHandle->DefaultPipe;
  1567. defaultPipe->Endpoint->Parameters.MaxPacketSize =
  1568. Parameters->MaximumPacketSize;
  1569. defaultPipe->Endpoint->Parameters.DeviceAddress =
  1570. Parameters->DeviceAddress;
  1571. MP_PokeEndpoint(devExt, defaultPipe->Endpoint, mpStatus);
  1572. ntStatus = USBPORT_SendCommand(devExt->Fdo.RawDeviceHandle,
  1573. FdoDeviceObject,
  1574. &setupPacket,
  1575. &Parameters->Data[0],
  1576. Parameters->DataLength,
  1577. &Parameters->DataLength,
  1578. &Parameters->UsbdStatusCode);
  1579. usbUserStatus =
  1580. USBPORT_NtStatus_TO_UsbUserStatus(ntStatus);
  1581. Header->UsbUserStatusCode = usbUserStatus;
  1582. }
  1583. VOID
  1584. USBPORT_UserGetBandwidthInformation(
  1585. PDEVICE_OBJECT FdoDeviceObject,
  1586. PUSBUSER_REQUEST_HEADER Header,
  1587. PUSB_BANDWIDTH_INFO BandwidthInfo
  1588. )
  1589. /*++
  1590. Routine Description:
  1591. Arguments:
  1592. DeviceObject - Fdo for USB HC
  1593. Return Value:
  1594. none.
  1595. --*/
  1596. {
  1597. PDEVICE_EXTENSION devExt;
  1598. ULONG asyncBW;
  1599. USBPORT_KdPrint((2, "'USBPORT_UserGetBandwidthInformation\n"));
  1600. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1601. ASSERT_FDOEXT(devExt);
  1602. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'gBWi', 0, 0, 0);
  1603. BandwidthInfo->DeviceCount =
  1604. USBPORT_GetDeviceCount(FdoDeviceObject);
  1605. BandwidthInfo->TotalBusBandwidth =
  1606. devExt->Fdo.TotalBusBandwidth;
  1607. // return allocation based on 32 sec
  1608. // segment of bus time
  1609. BandwidthInfo->Total32secBandwidth =
  1610. devExt->Fdo.TotalBusBandwidth * 32;
  1611. asyncBW = BandwidthInfo->TotalBusBandwidth/10;
  1612. BandwidthInfo->AllocedBulkAndControl =
  1613. asyncBW * 32;
  1614. BandwidthInfo->AllocedIso =
  1615. devExt->Fdo.AllocedIsoBW*32;
  1616. BandwidthInfo->AllocedInterrupt_1ms =
  1617. devExt->Fdo.AllocedInterruptBW[0]*32;
  1618. BandwidthInfo->AllocedInterrupt_2ms =
  1619. devExt->Fdo.AllocedInterruptBW[1]*16;
  1620. BandwidthInfo->AllocedInterrupt_4ms =
  1621. devExt->Fdo.AllocedInterruptBW[2]*8;
  1622. BandwidthInfo->AllocedInterrupt_8ms =
  1623. devExt->Fdo.AllocedInterruptBW[3]*4;
  1624. BandwidthInfo->AllocedInterrupt_16ms =
  1625. devExt->Fdo.AllocedInterruptBW[4]*2;
  1626. BandwidthInfo->AllocedInterrupt_32ms =
  1627. devExt->Fdo.AllocedInterruptBW[5]*1;
  1628. Header->ActualBufferLength =
  1629. sizeof(*Header)+sizeof(USB_BANDWIDTH_INFO);
  1630. }
  1631. VOID
  1632. USBPORT_UserGetBusStatistics0(
  1633. PDEVICE_OBJECT FdoDeviceObject,
  1634. PUSBUSER_REQUEST_HEADER Header,
  1635. PUSB_BUS_STATISTICS_0 BusStatistics0
  1636. )
  1637. /*++
  1638. Routine Description:
  1639. Arguments:
  1640. DeviceObject - Fdo for USB HC
  1641. Return Value:
  1642. none.
  1643. --*/
  1644. {
  1645. PDEVICE_EXTENSION devExt, rhDevExt;
  1646. KIRQL irql;
  1647. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1648. ASSERT_FDOEXT(devExt);
  1649. if (devExt->Fdo.RootHubPdo != NULL) {
  1650. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  1651. ASSERT_PDOEXT(rhDevExt);
  1652. } else {
  1653. rhDevExt = NULL;
  1654. }
  1655. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'gBus', rhDevExt,
  1656. BusStatistics0, 0);
  1657. BusStatistics0->DeviceCount =
  1658. USBPORT_GetDeviceCount(FdoDeviceObject);
  1659. KeQuerySystemTime(&BusStatistics0->CurrentSystemTime);
  1660. MP_Get32BitFrameNumber(devExt,
  1661. BusStatistics0->CurrentUsbFrame);
  1662. // lock the stat counters while we read them
  1663. KeAcquireSpinLock(&devExt->Fdo.StatCounterSpin.sl, &irql);
  1664. BusStatistics0->BulkBytes =
  1665. devExt->Fdo.StatBulkDataBytes;
  1666. BusStatistics0->IsoBytes =
  1667. devExt->Fdo.StatIsoDataBytes;
  1668. BusStatistics0->InterruptBytes =
  1669. devExt->Fdo.StatInterruptDataBytes;
  1670. BusStatistics0->ControlDataBytes =
  1671. devExt->Fdo.StatControlDataBytes;
  1672. BusStatistics0->RootHubDevicePowerState = 4;
  1673. BusStatistics0->RootHubEnabled = FALSE;
  1674. BusStatistics0->WorkerSignalCount =
  1675. devExt->Fdo.StatWorkSignalCount;
  1676. BusStatistics0->HardResetCount =
  1677. devExt->Fdo.StatHardResetCount;
  1678. BusStatistics0->WorkerIdleTimeMs =
  1679. devExt->Fdo.StatWorkIdleTime;
  1680. BusStatistics0->CommonBufferBytes =
  1681. devExt->Fdo.StatCommonBufferBytes;
  1682. if (rhDevExt != NULL) {
  1683. BusStatistics0->RootHubEnabled = TRUE;
  1684. switch(rhDevExt->CurrentDevicePowerState) {
  1685. case PowerDeviceD0:
  1686. BusStatistics0->RootHubDevicePowerState = 0;
  1687. break;
  1688. case PowerDeviceD1:
  1689. BusStatistics0->RootHubDevicePowerState = 1;
  1690. break;
  1691. case PowerDeviceD2:
  1692. BusStatistics0->RootHubDevicePowerState = 2;
  1693. break;
  1694. case PowerDeviceD3:
  1695. BusStatistics0->RootHubDevicePowerState = 3;
  1696. break;
  1697. }
  1698. }
  1699. BusStatistics0->PciInterruptCount =
  1700. devExt->Fdo.StatPciInterruptCount;
  1701. // if (ResetCounters) {
  1702. // devExt->Fdo.StatControlDataBytes =
  1703. // devExt->Fdo.StatInterruptBytes =
  1704. // devExt->Fdo.StatIsoBytes =
  1705. // devExt->Fdo.StatBulkBytes =
  1706. // devExt->Fdo.PciInterruptCount = 0;
  1707. // }
  1708. KeReleaseSpinLock(&devExt->Fdo.StatCounterSpin.sl, irql);
  1709. Header->ActualBufferLength =
  1710. sizeof(*Header)+sizeof(USB_BUS_STATISTICS_0);
  1711. }
  1712. // This was taken from usbioctl.h
  1713. //
  1714. #include <pshpack1.h>
  1715. typedef struct _USB_HCD_DRIVERKEY_NAME {
  1716. ULONG ActualLength;
  1717. WCHAR DriverKeyName[1]; // names are returned NULL terminated
  1718. } USB_HCD_DRIVERKEY_NAME, *PUSB_HCD_DRIVERKEY_NAME;
  1719. #include <poppack.h>
  1720. NTSTATUS
  1721. USBPORT_LegacyGetUnicodeName(
  1722. PDEVICE_OBJECT FdoDeviceObject,
  1723. PIRP Irp,
  1724. PULONG BytesReturned
  1725. )
  1726. /*++
  1727. Routine Description:
  1728. Handles the old style IOCTL to fetch the USB host controllers
  1729. driver key name.
  1730. NOTE: This function may be removed if we ever fix the UI to use the
  1731. newer APIs.
  1732. Arguments:
  1733. DeviceObject - Fdo for USB HC
  1734. Return Value:
  1735. NT status code
  1736. --*/
  1737. {
  1738. PDEVICE_EXTENSION devExt;
  1739. KIRQL irql;
  1740. PUSBUSER_CONTROLLER_UNICODE_NAME request;
  1741. NTSTATUS ntStatus;
  1742. ULONG need;
  1743. PUSB_HCD_DRIVERKEY_NAME ioBufferO;
  1744. PIO_STACK_LOCATION irpStack;
  1745. ULONG outputBufferLength;
  1746. ULONG ioCtl;
  1747. PAGED_CODE();
  1748. *BytesReturned = 0;
  1749. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1750. ioCtl = irpStack->Parameters.DeviceIoControl.IoControlCode;
  1751. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1752. ASSERT_FDOEXT(devExt);
  1753. USBPORT_ASSERT(irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL);
  1754. USBPORT_ASSERT(ioCtl == IOCTL_GET_HCD_DRIVERKEY_NAME ||
  1755. ioCtl == IOCTL_USB_GET_ROOT_HUB_NAME);
  1756. USBPORT_KdPrint((1,"'WARNING: Caller using obsolete user mode IOCTL\n"));
  1757. ioBufferO = Irp->AssociatedIrp.SystemBuffer;
  1758. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  1759. // Bail immediately if the output buffer is too small
  1760. //
  1761. if (outputBufferLength < sizeof(USB_HCD_DRIVERKEY_NAME)) {
  1762. return STATUS_BUFFER_TOO_SMALL;
  1763. }
  1764. // first get the driver key name using the standard API
  1765. need = sizeof(USBUSER_CONTROLLER_UNICODE_NAME);
  1766. retry:
  1767. ALLOC_POOL_Z(request,
  1768. PagedPool, need);
  1769. if (request != NULL) {
  1770. request->Header.RequestBufferLength = need;
  1771. if (ioCtl == IOCTL_GET_HCD_DRIVERKEY_NAME) {
  1772. request->Header.UsbUserRequest =
  1773. USBUSER_GET_CONTROLLER_DRIVER_KEY;
  1774. USBPORT_UserGetControllerKey(
  1775. FdoDeviceObject,
  1776. &request->Header,
  1777. &request->UnicodeName);
  1778. } else {
  1779. request->Header.UsbUserRequest =
  1780. USBUSER_GET_ROOTHUB_SYMBOLIC_NAME;
  1781. USBPORT_UserGetRootHubName(
  1782. FdoDeviceObject,
  1783. &request->Header,
  1784. &request->UnicodeName);
  1785. }
  1786. if (request->Header.UsbUserStatusCode ==
  1787. UsbUserBufferTooSmall) {
  1788. need = request->Header.ActualBufferLength;
  1789. FREE_POOL(FdoDeviceObject, request);
  1790. goto retry;
  1791. } else if (request->Header.UsbUserStatusCode ==
  1792. UsbUserSuccess) {
  1793. // map the result into the callers buffer
  1794. // note: actual length is the size of the request structure
  1795. // plus the name.
  1796. ioBufferO->ActualLength = request->UnicodeName.Length +
  1797. sizeof(ULONG);
  1798. if (outputBufferLength >= ioBufferO->ActualLength) {
  1799. // we can return the name
  1800. RtlCopyMemory(&ioBufferO->DriverKeyName[0],
  1801. &request->UnicodeName.String[0],
  1802. request->UnicodeName.Length);
  1803. *BytesReturned = ioBufferO->ActualLength;
  1804. } else {
  1805. ioBufferO->DriverKeyName[0] = L'\0';
  1806. *BytesReturned = sizeof(USB_HCD_DRIVERKEY_NAME);
  1807. }
  1808. ntStatus = STATUS_SUCCESS;
  1809. FREE_POOL(FdoDeviceObject, request);
  1810. } else {
  1811. ntStatus = STATUS_UNSUCCESSFUL;
  1812. }
  1813. } else {
  1814. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1815. }
  1816. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'gUNN', ntStatus, ioBufferO,
  1817. *BytesReturned);
  1818. return ntStatus;
  1819. }
  1820. NTSTATUS
  1821. USBPORT_GetSymbolicName(
  1822. PDEVICE_OBJECT FdoDeviceObject,
  1823. PDEVICE_OBJECT DeviceObject,
  1824. PUNICODE_STRING SymbolicNameUnicodeString
  1825. )
  1826. /*++
  1827. Routine Description:
  1828. Return the symbolic name for the device object with leading
  1829. \xxx\ removed
  1830. Arguments:
  1831. DeviceObject - Fdo OR Pdo for USB HC
  1832. Return Value:
  1833. none
  1834. --*/
  1835. {
  1836. PDEVICE_EXTENSION fdoDevExt;
  1837. PDEVICE_EXTENSION devExt;
  1838. ULONG length, offset = 0;
  1839. WCHAR *pwch, *buffer;
  1840. NTSTATUS ntStatus = STATUS_BOGUS;
  1841. ULONG bufferLength;
  1842. PUNICODE_STRING tmpUnicodeString;
  1843. PAGED_CODE();
  1844. GET_DEVICE_EXT(fdoDevExt, FdoDeviceObject);
  1845. ASSERT_FDOEXT(fdoDevExt);
  1846. GET_DEVICE_EXT(devExt, DeviceObject);
  1847. tmpUnicodeString =
  1848. &devExt->SymbolicLinkName;
  1849. //
  1850. // make sure there is enough room for the length,
  1851. // string and the NULL
  1852. //
  1853. // assuming the string is \xxx\name strip of '\xxx\' where
  1854. // x is zero or more chars
  1855. pwch = &tmpUnicodeString->Buffer[0];
  1856. // Under NT, if the controller is banged out in DeviceManager,
  1857. // this will be NULL.
  1858. if (pwch == NULL) {
  1859. return STATUS_UNSUCCESSFUL;
  1860. }
  1861. bufferLength = tmpUnicodeString->Length;
  1862. ALLOC_POOL_Z(buffer,
  1863. PagedPool, bufferLength);
  1864. if (buffer != NULL) {
  1865. USBPORT_ASSERT(*pwch == '\\');
  1866. if (*pwch == '\\') {
  1867. pwch++;
  1868. while (*pwch != '\\' && *pwch) {
  1869. pwch++;
  1870. }
  1871. USBPORT_ASSERT(*pwch == '\\');
  1872. if (*pwch == '\\') {
  1873. pwch++;
  1874. }
  1875. offset = (ULONG)((PUCHAR)pwch -
  1876. (PUCHAR)&tmpUnicodeString->Buffer[0]);
  1877. }
  1878. length = tmpUnicodeString->Length - offset;
  1879. RtlCopyMemory(buffer,
  1880. &tmpUnicodeString->Buffer[offset/2],
  1881. length);
  1882. RtlInitUnicodeString(SymbolicNameUnicodeString,
  1883. buffer);
  1884. ntStatus = STATUS_SUCCESS;
  1885. } else {
  1886. // init to null so subsequent free will not crash
  1887. RtlInitUnicodeString(SymbolicNameUnicodeString,
  1888. NULL);
  1889. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1890. }
  1891. return ntStatus;
  1892. }
  1893. VOID
  1894. USBPORT_UserGetDriverVersion(
  1895. PDEVICE_OBJECT FdoDeviceObject,
  1896. PUSBUSER_REQUEST_HEADER Header,
  1897. PUSB_DRIVER_VERSION_PARAMETERS Parameters
  1898. )
  1899. /*++
  1900. Routine Description:
  1901. Arguments:
  1902. DeviceObject - Fdo for USB HC
  1903. Return Value:
  1904. none.
  1905. --*/
  1906. {
  1907. PDEVICE_EXTENSION devExt;
  1908. KIRQL irql;
  1909. USBPORT_KdPrint((2, "'USBPORT_UserGetDriverVersion\n"));
  1910. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1911. ASSERT_FDOEXT(devExt);
  1912. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'gDrv', 0, 0, 0);
  1913. Parameters->DriverTrackingCode = USBPORT_TRACKING_ID;
  1914. /* USBDI Api set supported */
  1915. Parameters->USBDI_Version = USBDI_VERSION;
  1916. /* USB USER Api Set supported */
  1917. Parameters->USBUSER_Version = USBUSER_VERSION;
  1918. /* set to true if checked vesrion(s) on
  1919. the stack are loaded
  1920. */
  1921. #if DBG
  1922. Parameters->CheckedPortDriver = TRUE;
  1923. Parameters->CheckedMiniportDriver = TRUE;
  1924. #else
  1925. Parameters->CheckedPortDriver = FALSE;
  1926. Parameters->CheckedMiniportDriver = FALSE;
  1927. #endif
  1928. Header->ActualBufferLength =
  1929. sizeof(*Header)+sizeof(USB_DRIVER_VERSION_PARAMETERS);
  1930. }
  1931. BOOLEAN
  1932. USBPORT_ValidateRootPortApi(
  1933. PDEVICE_OBJECT FdoDeviceObject,
  1934. ULONG PortNumber
  1935. )
  1936. /*++
  1937. Routine Description:
  1938. Arguments:
  1939. DeviceObject - Fdo for USB HC
  1940. Return Value:
  1941. none.
  1942. --*/
  1943. {
  1944. PDEVICE_EXTENSION devExt;
  1945. KIRQL irql;
  1946. ROOTHUB_DATA hubData;
  1947. USBPORT_KdPrint((2, "'USBPORT_ValidateRootPortApi\n"));
  1948. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1949. ASSERT_FDOEXT(devExt);
  1950. MPRH_GetRootHubData(devExt, &hubData);
  1951. if (PortNumber > hubData.NumberOfPorts ||
  1952. PortNumber == 0) {
  1953. return FALSE;
  1954. }
  1955. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_SUSPENDED)) {
  1956. return FALSE;
  1957. }
  1958. return TRUE;
  1959. }
  1960. /*
  1961. Determine if direct controller access is enabled in registry.
  1962. */
  1963. BOOLEAN
  1964. USBPORT_DCA_KeyEnabled(
  1965. PDEVICE_OBJECT FdoDeviceObject
  1966. )
  1967. {
  1968. PDEVICE_EXTENSION devExt;
  1969. NTSTATUS ntStatus;
  1970. RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  1971. PWCHAR usb = L"usb";
  1972. ULONG k = 0;
  1973. ULONG dca = 0;
  1974. PAGED_CODE();
  1975. // bios hacks
  1976. QueryTable[k].QueryRoutine = USBPORT_GetConfigValue;
  1977. QueryTable[k].Flags = 0;
  1978. QueryTable[k].Name = ENABLE_DCA;
  1979. QueryTable[k].EntryContext = &dca;
  1980. QueryTable[k].DefaultType = REG_DWORD;
  1981. QueryTable[k].DefaultData = &dca;
  1982. QueryTable[k].DefaultLength = sizeof(dca);
  1983. k++;
  1984. // stop
  1985. QueryTable[k].QueryRoutine = NULL;
  1986. QueryTable[k].Flags = 0;
  1987. QueryTable[k].Name = NULL;
  1988. ntStatus = RtlQueryRegistryValues(
  1989. RTL_REGISTRY_SERVICES,
  1990. usb,
  1991. QueryTable, // QueryTable
  1992. NULL, // Context
  1993. NULL); // Environment
  1994. return NT_SUCCESS(ntStatus) && dca == 1;
  1995. }
  1996. /*
  1997. Determine if direct controller access is enabled in registry.
  1998. Also validate that the caller has load driver privilige.
  1999. */
  2000. BOOLEAN
  2001. USBPORT_DCA_Enabled(
  2002. PDEVICE_OBJECT FdoDeviceObject
  2003. )
  2004. {
  2005. if (USBPORT_DCA_KeyEnabled(FdoDeviceObject)) {
  2006. // verify privilage
  2007. // enable this code if the security APIs ever get
  2008. // added to WDM
  2009. #if 0
  2010. LUID securityLuid;
  2011. // first check for correct permissions
  2012. securityLuid = RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE);
  2013. return SeSinglePrivilegeCheck(securityLuid, UserMode);
  2014. #endif
  2015. return TRUE;
  2016. }
  2017. return FALSE;
  2018. }