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.

2349 lines
69 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. roothub.c
  5. Abstract:
  6. root hub emultation code for usbport driver
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. 6-21-99 : created
  12. --*/
  13. #include "common.h"
  14. // paged functions
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, USBPORT_RootHub_CreateDevice)
  17. #pragma alloc_text(PAGE, USBPORT_RootHub_RemoveDevice)
  18. #endif
  19. // non paged functions
  20. // USBPORT_RootHub_StandardCommand
  21. // USBPORT_RootHub_ClassCommand
  22. // USBPORT_RootHub_Endpoint0
  23. // USBPORT_RootHub_Endpoint1
  24. // USBPORT_RootHub_EndpointWorker
  25. // USBPORT_SetBit
  26. // USBPORTSVC_InvalidateRootHub
  27. // USBPORT_RootHub_PortRequest
  28. #define RH_STANDARD_REQ 0
  29. #define RH_CLASS_REQ 1
  30. #define MIN(x, y) (((x)<(y)) ? (x) : (y))
  31. //
  32. // HUB feature selectors
  33. //
  34. #define C_HUB_LOCAL_POWER 0
  35. #define C_HUB_OVER_CURRENT 1
  36. #define PORT_CONNECTION 0
  37. #define PORT_ENABLE 1
  38. #define PORT_SUSPEND 2
  39. #define PORT_OVER_CURRENT 3
  40. #define PORT_RESET 4
  41. #define PORT_POWER 8
  42. #define PORT_LOW_SPEED 9
  43. #define C_PORT_CONNECTION 16
  44. #define C_PORT_ENABLE 17
  45. #define C_PORT_SUSPEND 18
  46. #define C_PORT_OVER_CURRENT 19
  47. #define C_PORT_RESET 20
  48. #define HUB_REQUEST_GET_STATUS 0
  49. #define HUB_REQUEST_CLEAR_FEATURE 1
  50. #define HUB_REQUEST_GET_STATE 2
  51. #define HUB_REQUEST_SET_FEATURE 3
  52. #define HUB_REQUEST_GET_DESCRIPTOR 6
  53. #define HUB_REQUEST_SET_DESCRIPTOR 7
  54. // recipient codes in the bRequestType field
  55. #define RECIPIENT_DEVICE 0
  56. #define RECIPIENT_INTRFACE 1
  57. #define RECIPIENT_ENDPOINT 2
  58. #define RECIPIENT_PORT 3
  59. // Descriptor Templates
  60. // the following structures are emulated the same
  61. // way for all port drivers
  62. UCHAR RH_DeviceDescriptor[] = {0x12, //bLength
  63. 0x01, //bDescrpitorType
  64. 0x00, 0x01, //bcdUSB
  65. 0x09, //bDeviceClass
  66. 0x01, //bDeviceSubClass
  67. 0x00, //bDeviceProtocol
  68. 0x08, //bMaxPacketSize0
  69. 0x00, 0x00, //idVendor
  70. 0x00, 0x00, //idProduct
  71. 0x00, 0x00, //bcdDevice
  72. 0x00, //iManufacturer
  73. 0x00, //iProduct
  74. 0x00, //iSerialNumber
  75. 0x01};//bNumConfigurations
  76. UCHAR RH_ConfigurationDescriptor[] =
  77. /* Config Descriptor */
  78. {0x09, //bLength
  79. 0x02, //bDescriptorType
  80. 0x19, 0x00, //wTotalLength
  81. 0x01, //bNumInterfaces
  82. 0x23, //iConfigurationValue
  83. 0x00, //iConfiguration
  84. 0x40, //bmAttributes
  85. 0x00, //MaxPower
  86. /* Interface Descriptor */
  87. 0x09, //bLength
  88. 0x04, //bDescriptorType
  89. 0x00, //bInterfaceNumber
  90. 0x00, //bAlternateSetting
  91. 0x01, //bNumEndpoints
  92. 0x09, //bInterfaceClass
  93. 0x01, //bInterfaceSubClass
  94. 0x00, //bInterfaceProtocol
  95. 0x00, //iInterface
  96. /* Endpoint Descriptor */
  97. 0x07, //bLength
  98. 0x05, //bDescriptorType
  99. 0x81, //bEndpointAddress
  100. 0x03, //bmAttributes
  101. 0x08, 0x00, //wMaxPacketSize
  102. 0x0a};//bInterval
  103. UCHAR RH_HubDescriptor[] =
  104. {0x09, //bLength
  105. 0x29, //bDescriptorType
  106. 0x00, //bNbrPorts
  107. 0x00, 0x00, //wHubCharacteristics
  108. 0x00, // bPwrOn2PwrGood
  109. 0x00}; // bHubContrCurrent
  110. #define RH_DEV_TO_HOST 1
  111. #define RH_HOST_TO_DEV 0
  112. RHSTATUS
  113. USBPORT_RootHub_PortRequest(
  114. PDEVICE_OBJECT FdoDeviceObject,
  115. PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
  116. PORT_OPERATION PortOperation
  117. )
  118. /*++
  119. Routine Description:
  120. Process a standard command sent on the control endpoint
  121. of the root hub.
  122. Arguments:
  123. SetupPacket - pointer to a SetupPacket packet
  124. Return Value:
  125. Root Hub status code.
  126. --*/
  127. {
  128. PVOID descriptor = NULL;
  129. ULONG length;
  130. RHSTATUS rhStatus = RH_STALL;
  131. PDEVICE_EXTENSION devExt, rhDevExt;
  132. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  133. ASSERT_FDOEXT(devExt);
  134. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  135. ASSERT_PDOEXT(rhDevExt);
  136. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rSCM', SetupPacket, 0, 0);
  137. if (SetupPacket->wIndex.W > 0 &&
  138. SetupPacket->wIndex.W <= NUMBER_OF_PORTS(rhDevExt)) {
  139. USB_MINIPORT_STATUS mpStatus;
  140. switch(PortOperation) {
  141. case SetFeaturePortReset:
  142. mpStatus =
  143. devExt->Fdo.MiniportDriver->
  144. RegistrationPacket.MINIPORT_RH_SetFeaturePortReset(
  145. devExt->Fdo.MiniportDeviceData,
  146. SetupPacket->wIndex.W);
  147. break;
  148. case SetFeaturePortPower:
  149. if (USBPORT_IS_USB20(devExt)) {
  150. mpStatus = USBPORT_RootHub_PowerUsb2Port(FdoDeviceObject,
  151. SetupPacket->wIndex.W);
  152. } else if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_IS_CC)) {
  153. mpStatus = USBPORT_RootHub_PowerUsbCcPort(FdoDeviceObject,
  154. SetupPacket->wIndex.W);
  155. } else {
  156. mpStatus =
  157. devExt->Fdo.MiniportDriver->
  158. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  159. devExt->Fdo.MiniportDeviceData,
  160. SetupPacket->wIndex.W);
  161. }
  162. break;
  163. case SetFeaturePortEnable:
  164. mpStatus =
  165. devExt->Fdo.MiniportDriver->
  166. RegistrationPacket.MINIPORT_RH_SetFeaturePortEnable(
  167. devExt->Fdo.MiniportDeviceData,
  168. SetupPacket->wIndex.W);
  169. break;
  170. case SetFeaturePortSuspend:
  171. mpStatus =
  172. devExt->Fdo.MiniportDriver->
  173. RegistrationPacket.MINIPORT_RH_SetFeaturePortSuspend(
  174. devExt->Fdo.MiniportDeviceData,
  175. SetupPacket->wIndex.W);
  176. break;
  177. case ClearFeaturePortEnable:
  178. mpStatus =
  179. devExt->Fdo.MiniportDriver->
  180. RegistrationPacket.MINIPORT_RH_ClearFeaturePortEnable(
  181. devExt->Fdo.MiniportDeviceData,
  182. SetupPacket->wIndex.W);
  183. break;
  184. case ClearFeaturePortPower:
  185. mpStatus =
  186. devExt->Fdo.MiniportDriver->
  187. RegistrationPacket.MINIPORT_RH_ClearFeaturePortPower(
  188. devExt->Fdo.MiniportDeviceData,
  189. SetupPacket->wIndex.W);
  190. break;
  191. case ClearFeaturePortConnectChange:
  192. mpStatus =
  193. devExt->Fdo.MiniportDriver->
  194. RegistrationPacket.MINIPORT_RH_ClearFeaturePortConnectChange(
  195. devExt->Fdo.MiniportDeviceData,
  196. SetupPacket->wIndex.W);
  197. break;
  198. case ClearFeaturePortResetChange:
  199. mpStatus =
  200. devExt->Fdo.MiniportDriver->
  201. RegistrationPacket.MINIPORT_RH_ClearFeaturePortResetChange(
  202. devExt->Fdo.MiniportDeviceData,
  203. SetupPacket->wIndex.W);
  204. break;
  205. case ClearFeaturePortEnableChange:
  206. mpStatus =
  207. devExt->Fdo.MiniportDriver->
  208. RegistrationPacket.MINIPORT_RH_ClearFeaturePortEnableChange(
  209. devExt->Fdo.MiniportDeviceData,
  210. SetupPacket->wIndex.W);
  211. break;
  212. case ClearFeaturePortSuspend:
  213. mpStatus =
  214. devExt->Fdo.MiniportDriver->
  215. RegistrationPacket.MINIPORT_RH_ClearFeaturePortSuspend(
  216. devExt->Fdo.MiniportDeviceData,
  217. SetupPacket->wIndex.W);
  218. break;
  219. case ClearFeaturePortSuspendChange:
  220. mpStatus =
  221. devExt->Fdo.MiniportDriver->
  222. RegistrationPacket.MINIPORT_RH_ClearFeaturePortSuspendChange(
  223. devExt->Fdo.MiniportDeviceData,
  224. SetupPacket->wIndex.W);
  225. break;
  226. case ClearFeaturePortOvercurrentChange:
  227. mpStatus =
  228. devExt->Fdo.MiniportDriver->
  229. RegistrationPacket.MINIPORT_RH_ClearFeaturePortOvercurrentChange(
  230. devExt->Fdo.MiniportDeviceData,
  231. SetupPacket->wIndex.W);
  232. break;
  233. default:
  234. mpStatus = USBMP_STATUS_FAILURE;
  235. DEBUG_BREAK();
  236. }
  237. rhStatus = MPSTATUS_TO_RHSTATUS(mpStatus);
  238. } else {
  239. rhStatus = RH_STALL;
  240. DEBUG_BREAK();
  241. }
  242. return rhStatus;
  243. }
  244. RHSTATUS
  245. USBPORT_RootHub_HubRequest(
  246. PDEVICE_OBJECT FdoDeviceObject,
  247. PORT_OPERATION PortOperation
  248. )
  249. /*++
  250. Routine Description:
  251. Process a standard command sent on the control endpoint
  252. of the root hub.
  253. Arguments:
  254. SetupPacket - pointer to a SetupPacket packet
  255. Return Value:
  256. Root Hub status code.
  257. --*/
  258. {
  259. RHSTATUS rhStatus = RH_STALL;
  260. PDEVICE_EXTENSION devExt, rhDevExt;
  261. USB_MINIPORT_STATUS mpStatus;
  262. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  263. ASSERT_FDOEXT(devExt);
  264. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  265. ASSERT_PDOEXT(rhDevExt);
  266. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'hSCM', 0, 0, 0);
  267. switch(PortOperation) {
  268. case ClearFeaturePortOvercurrentChange:
  269. mpStatus =
  270. devExt->Fdo.MiniportDriver->
  271. RegistrationPacket.MINIPORT_RH_ClearFeaturePortOvercurrentChange(
  272. devExt->Fdo.MiniportDeviceData,
  273. 0);
  274. rhStatus = MPSTATUS_TO_RHSTATUS(mpStatus);
  275. break;
  276. }
  277. return rhStatus;
  278. }
  279. RHSTATUS
  280. USBPORT_RootHub_StandardCommand(
  281. PDEVICE_OBJECT FdoDeviceObject,
  282. PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
  283. PUCHAR Buffer,
  284. PULONG BufferLength
  285. )
  286. /*++
  287. Routine Description:
  288. Process a standard command sent on the control endpoint
  289. of the root hub.
  290. Arguments:
  291. SetupPacket - pointer to a SetupPacket packet
  292. Return Value:
  293. Root Hub status code.
  294. --*/
  295. {
  296. PVOID descriptor = NULL;
  297. ULONG length;
  298. RHSTATUS rhStatus = RH_STALL;
  299. PDEVICE_EXTENSION devExt, rhDevExt;
  300. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  301. ASSERT_FDOEXT(devExt);
  302. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  303. ASSERT_PDOEXT(rhDevExt);
  304. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rSCM', SetupPacket, 0, 0);
  305. //
  306. // switch on the command
  307. //
  308. switch (SetupPacket->bRequest) {
  309. case USB_REQUEST_SET_ADDRESS:
  310. //
  311. //
  312. //
  313. if (SetupPacket->wIndex.W == 0 &&
  314. SetupPacket->wLength == 0 &&
  315. SetupPacket->bmRequestType.Dir == RH_HOST_TO_DEV) {
  316. rhDevExt->Pdo.RootHubDeviceHandle.DeviceAddress =
  317. (UCHAR)SetupPacket->wValue.W;
  318. rhStatus = RH_SUCCESS;
  319. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rSAD', 0, 0, 0);
  320. }
  321. break;
  322. case USB_REQUEST_GET_DESCRIPTOR:
  323. {
  324. ULONG siz;
  325. UCHAR descriptorIndex, descriptorType;
  326. descriptorType = (UCHAR) SetupPacket->wValue.HiByte;
  327. descriptorIndex = (UCHAR) SetupPacket->wValue.LowByte;
  328. switch (descriptorType) {
  329. case USB_DEVICE_DESCRIPTOR_TYPE:
  330. if (descriptorIndex == 0 &&
  331. SetupPacket->bmRequestType.Dir == RH_DEV_TO_HOST) {
  332. siz = sizeof(RH_DeviceDescriptor);
  333. // use PDO specific copy
  334. descriptor = rhDevExt->Pdo.DeviceDescriptor;
  335. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rGDS', descriptor, siz, 0);
  336. }
  337. break;
  338. case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  339. if (descriptorIndex == 0 &&
  340. SetupPacket->bmRequestType.Dir == RH_DEV_TO_HOST) {
  341. siz = sizeof(RH_ConfigurationDescriptor);
  342. // use pdo specific copy
  343. descriptor = rhDevExt->Pdo.ConfigurationDescriptor;
  344. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rGCS', descriptor, siz, 0);
  345. }
  346. break;
  347. //
  348. // BUGBUG these descriptor types not handled
  349. //
  350. case USB_STRING_DESCRIPTOR_TYPE:
  351. // we will stall
  352. TEST_TRAP();
  353. default:
  354. // we will stall
  355. DEBUG_BREAK();
  356. } /* descriptorType */
  357. if (descriptor) {
  358. length = MIN(*BufferLength, siz);
  359. RtlCopyMemory(Buffer, descriptor, length);
  360. *BufferLength = length;
  361. rhStatus = RH_SUCCESS;
  362. }
  363. }
  364. break;
  365. case USB_REQUEST_GET_STATUS:
  366. //
  367. // get_device_status
  368. //
  369. // report that we are self powered
  370. //
  371. // BUGBUG
  372. // are we self powered?
  373. // are we a remote wakeup source?
  374. //
  375. // see section 9.4.5 USB 1.0 spec
  376. //
  377. {
  378. PUSHORT status = (PUSHORT) Buffer;
  379. if (SetupPacket->wValue.W == 0 && //mbz
  380. SetupPacket->wLength == 2 &&
  381. SetupPacket->wIndex.W == 0 && //device
  382. SetupPacket->bmRequestType.Dir == RH_DEV_TO_HOST) {
  383. USB_MINIPORT_STATUS mpStatus;
  384. MPRH_GetStatus(devExt, status, mpStatus);
  385. *BufferLength = sizeof(*status);
  386. rhStatus = MPSTATUS_TO_RHSTATUS(mpStatus);
  387. }
  388. }
  389. break;
  390. case USB_REQUEST_GET_CONFIGURATION:
  391. //
  392. // get_device_configuration
  393. //
  394. if (SetupPacket->wValue.W == 0 && //mbz
  395. SetupPacket->wIndex.W == 0 && //mbz
  396. SetupPacket->wLength == 1 &&
  397. SetupPacket->bmRequestType.Dir == RH_DEV_TO_HOST) {
  398. length = MIN(*BufferLength, sizeof(rhDevExt->Pdo.ConfigurationValue));
  399. RtlCopyMemory(Buffer, &rhDevExt->Pdo.ConfigurationValue, length);
  400. *BufferLength = length;
  401. rhStatus = RH_SUCCESS;
  402. }
  403. break;
  404. case USB_REQUEST_CLEAR_FEATURE:
  405. // bugbug, required
  406. TEST_TRAP();
  407. break;
  408. case USB_REQUEST_SET_CONFIGURATION:
  409. {
  410. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor =
  411. (PUSB_CONFIGURATION_DESCRIPTOR) RH_ConfigurationDescriptor;
  412. if (SetupPacket->wIndex.W == 0 && // mbz
  413. SetupPacket->wLength == 0 && // mbz
  414. SetupPacket->bmRequestType.Dir == RH_HOST_TO_DEV &&
  415. (SetupPacket->wValue.W ==
  416. configurationDescriptor->bConfigurationValue ||
  417. SetupPacket->wValue.W == 0)) {
  418. rhDevExt->Pdo.ConfigurationValue =
  419. (UCHAR) SetupPacket->wValue.W;
  420. rhStatus = RH_SUCCESS;
  421. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rSEC',
  422. rhDevExt->Pdo.ConfigurationValue, 0, 0);
  423. }
  424. }
  425. break;
  426. case USB_REQUEST_SET_FEATURE:
  427. // bugbug, required
  428. TEST_TRAP();
  429. break;
  430. //
  431. // these commands are optional for the hub
  432. //
  433. case USB_REQUEST_SET_DESCRIPTOR:
  434. case USB_REQUEST_SET_INTERFACE:
  435. case USB_REQUEST_GET_INTERFACE:
  436. case USB_REQUEST_SYNC_FRAME:
  437. default:
  438. // bad command, probably a bug in the
  439. // hub driver
  440. DEBUG_BREAK();
  441. break;
  442. }
  443. return rhStatus;
  444. }
  445. RHSTATUS
  446. USBPORT_RootHub_ClassCommand(
  447. PDEVICE_OBJECT FdoDeviceObject,
  448. PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
  449. PUCHAR Buffer,
  450. PULONG BufferLength
  451. )
  452. /*++
  453. Routine Description:
  454. Process a hub class command to the root hub control endpoint.
  455. Arguments:
  456. Return Value:
  457. Root Hub status code.
  458. --*/
  459. {
  460. PVOID descriptor = NULL;
  461. ULONG length;
  462. RHSTATUS rhStatus = RH_STALL;
  463. PDEVICE_EXTENSION devExt, rhDevExt;
  464. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  465. ASSERT_FDOEXT(devExt);
  466. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  467. ASSERT_PDOEXT(rhDevExt);
  468. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rCCM', SetupPacket, 0, 0);
  469. //
  470. // switch on the command
  471. //
  472. switch (SetupPacket->bRequest) {
  473. case HUB_REQUEST_GET_STATUS:
  474. //
  475. //
  476. //
  477. if (SetupPacket->bmRequestType.Recipient == RECIPIENT_PORT) {
  478. //
  479. // get port status
  480. //
  481. PRH_PORT_STATUS portStatus;
  482. //
  483. // see if we have a valid request
  484. //
  485. if (Buffer != NULL &&
  486. SetupPacket->wIndex.W > 0 &&
  487. SetupPacket->wIndex.W <= NUMBER_OF_PORTS(rhDevExt) &&
  488. SetupPacket->wLength >= sizeof(*portStatus)) {
  489. USB_MINIPORT_STATUS mpStatus;
  490. USBPORT_ASSERT(sizeof(*portStatus) == 4);
  491. USBPORT_ASSERT(*BufferLength >= sizeof(*portStatus));
  492. portStatus = (PRH_PORT_STATUS) Buffer;
  493. RtlZeroMemory(Buffer, sizeof(*portStatus));
  494. MPRH_GetPortStatus(devExt,
  495. SetupPacket->wIndex.W,
  496. portStatus,
  497. mpStatus);
  498. rhStatus = MPSTATUS_TO_RHSTATUS(mpStatus);
  499. }
  500. } else {
  501. //
  502. // get hub status
  503. //
  504. USB_MINIPORT_STATUS mpStatus;
  505. PRH_HUB_STATUS hubStatus;
  506. if (Buffer != NULL) {
  507. USBPORT_ASSERT(sizeof(*hubStatus) == 4);
  508. USBPORT_ASSERT(*BufferLength >= sizeof(*hubStatus));
  509. hubStatus = (PRH_HUB_STATUS) Buffer;
  510. RtlZeroMemory(Buffer, sizeof(*hubStatus));
  511. MPRH_GetHubStatus(devExt, hubStatus, mpStatus);
  512. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rGHS',
  513. *((PULONG) hubStatus), 0, 0);
  514. rhStatus = MPSTATUS_TO_RHSTATUS(mpStatus);
  515. }
  516. }
  517. break;
  518. case HUB_REQUEST_CLEAR_FEATURE:
  519. //
  520. // Hub/Port Clear Feature
  521. //
  522. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rCFR',
  523. SetupPacket->bmRequestType.Recipient, 0, 0);
  524. if (SetupPacket->bmRequestType.Recipient == RECIPIENT_PORT) {
  525. //
  526. // clear port feature
  527. //
  528. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rCPR',
  529. SetupPacket->wValue.W, 0, 0);
  530. switch(SetupPacket->wValue.W) {
  531. //
  532. //
  533. //
  534. case PORT_ENABLE:
  535. // disable the port
  536. rhStatus =
  537. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  538. SetupPacket,
  539. ClearFeaturePortEnable);
  540. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rDsP',
  541. SetupPacket->wIndex.W, 0, rhStatus);
  542. break;
  543. case PORT_POWER:
  544. rhStatus =
  545. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  546. SetupPacket,
  547. ClearFeaturePortPower);
  548. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rDpP',
  549. SetupPacket->wIndex.W, 0, rhStatus);
  550. break;
  551. //
  552. // the following are not valid commands,
  553. // return a stall since that is most likely
  554. // what a real hub would do
  555. //
  556. case PORT_CONNECTION:
  557. case PORT_OVER_CURRENT:
  558. case PORT_LOW_SPEED:
  559. case PORT_RESET:
  560. DEBUG_BREAK();
  561. break;
  562. case C_PORT_CONNECTION:
  563. rhStatus =
  564. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  565. SetupPacket,
  566. ClearFeaturePortConnectChange);
  567. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'cfCC',
  568. SetupPacket->wIndex.W, 0, rhStatus);
  569. break;
  570. case C_PORT_ENABLE:
  571. rhStatus =
  572. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  573. SetupPacket,
  574. ClearFeaturePortEnableChange);
  575. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'cfEC',
  576. SetupPacket->wIndex.W, 0, rhStatus);
  577. break;
  578. case C_PORT_RESET:
  579. rhStatus =
  580. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  581. SetupPacket,
  582. ClearFeaturePortResetChange);
  583. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'cfRC',
  584. SetupPacket->wIndex.W, 0, rhStatus);
  585. break;
  586. case PORT_SUSPEND:
  587. // clearing port suspend generates resume signalling
  588. rhStatus =
  589. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  590. SetupPacket,
  591. ClearFeaturePortSuspend);
  592. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'cfPS',
  593. SetupPacket->wIndex.W, 0, rhStatus);
  594. break;
  595. case C_PORT_SUSPEND:
  596. rhStatus =
  597. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  598. SetupPacket,
  599. ClearFeaturePortSuspendChange);
  600. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'cfPS',
  601. SetupPacket->wIndex.W, 0, rhStatus);
  602. break;
  603. case C_PORT_OVER_CURRENT:
  604. // overcuurent generated on NEC machines for ports with
  605. // no device attached. We want to find out:
  606. // 1. Does the port still function - Yes
  607. // 2. Does the UI popup No
  608. // the overcurrent occurs on the port with no device connected
  609. // and the system in question has only one USB port.
  610. rhStatus =
  611. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  612. SetupPacket,
  613. ClearFeaturePortOvercurrentChange);
  614. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'cfOC',
  615. SetupPacket->wIndex.W, 0, rhStatus);
  616. break;
  617. default:
  618. DEBUG_BREAK();
  619. }
  620. } else {
  621. //
  622. // clear hub feature
  623. //
  624. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rCHR', SetupPacket->wValue.W, 0, 0);
  625. switch(SetupPacket->wValue.W) {
  626. case C_HUB_LOCAL_POWER:
  627. rhStatus = RH_SUCCESS;
  628. break;
  629. case C_HUB_OVER_CURRENT:
  630. rhStatus =
  631. USBPORT_RootHub_HubRequest(FdoDeviceObject,
  632. ClearFeaturePortOvercurrentChange);
  633. break;
  634. default:
  635. DEBUG_BREAK();
  636. }
  637. }
  638. break;
  639. case HUB_REQUEST_GET_STATE:
  640. //
  641. //
  642. //
  643. DEBUG_BREAK();
  644. break;
  645. case HUB_REQUEST_SET_FEATURE:
  646. //
  647. // Hub/Port feature request
  648. //
  649. if (SetupPacket->bmRequestType.Recipient == RECIPIENT_PORT) {
  650. //
  651. // set port feature
  652. //
  653. switch(SetupPacket->wValue.W) {
  654. case PORT_RESET:
  655. rhStatus =
  656. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  657. SetupPacket,
  658. SetFeaturePortReset);
  659. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'sfPR',
  660. SetupPacket->wIndex.W, 0, rhStatus);
  661. break;
  662. case PORT_SUSPEND:
  663. rhStatus =
  664. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  665. SetupPacket,
  666. SetFeaturePortSuspend);
  667. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'sfPS',
  668. SetupPacket->wIndex.W, 0, rhStatus);
  669. break;
  670. case PORT_ENABLE:
  671. rhStatus =
  672. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  673. SetupPacket,
  674. SetFeaturePortEnable);
  675. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'sfPE',
  676. SetupPacket->wIndex.W, 0, rhStatus);
  677. break;
  678. case PORT_POWER:
  679. rhStatus =
  680. USBPORT_RootHub_PortRequest(FdoDeviceObject,
  681. SetupPacket,
  682. SetFeaturePortPower);
  683. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'sfPP',
  684. SetupPacket->wIndex.W, 0, rhStatus);
  685. break;
  686. case PORT_CONNECTION:
  687. case PORT_OVER_CURRENT:
  688. case PORT_LOW_SPEED:
  689. case C_PORT_CONNECTION:
  690. case C_PORT_ENABLE:
  691. case C_PORT_SUSPEND:
  692. case C_PORT_OVER_CURRENT:
  693. case C_PORT_RESET:
  694. default:
  695. DEBUG_BREAK();
  696. }
  697. } else {
  698. //
  699. // set hub feature
  700. //
  701. switch(SetupPacket->wValue.W) {
  702. case C_HUB_LOCAL_POWER:
  703. case C_HUB_OVER_CURRENT:
  704. default:
  705. DEBUG_BREAK();
  706. }
  707. }
  708. break;
  709. case HUB_REQUEST_GET_DESCRIPTOR:
  710. //
  711. // return the hub descriptor
  712. //
  713. if (Buffer != NULL &&
  714. SetupPacket->wValue.W == 0 &&
  715. // we already know it is a class command
  716. SetupPacket->bmRequestType.Dir == RH_DEV_TO_HOST) {
  717. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rGHD', SetupPacket, SetupPacket->wLength, 0);
  718. length = MIN(*BufferLength, HUB_DESRIPTOR_LENGTH(rhDevExt));
  719. RtlCopyMemory(Buffer, rhDevExt->Pdo.HubDescriptor, length);
  720. *BufferLength = length;
  721. rhStatus = RH_SUCCESS;
  722. }
  723. break;
  724. case HUB_REQUEST_SET_DESCRIPTOR:
  725. //
  726. //
  727. //
  728. TEST_TRAP();
  729. break;
  730. default:
  731. // bad command
  732. DEBUG_BREAK();
  733. break;
  734. }
  735. return rhStatus;
  736. }
  737. VOID
  738. USBPORT_SetBit(
  739. PVOID Bitmap,
  740. ULONG BitNumber
  741. )
  742. /* ++
  743. Description:
  744. Set a bit in a given a string of bytes.
  745. Arguments:
  746. Return:
  747. -- */
  748. {
  749. ULONG dwordOffset;
  750. ULONG bitOffset;
  751. PULONG l = (PULONG) Bitmap;
  752. dwordOffset = BitNumber / 32;
  753. bitOffset = BitNumber % 32;
  754. l[dwordOffset] |= (1 << bitOffset);
  755. }
  756. RHSTATUS
  757. USBPORT_RootHub_Endpoint1(
  758. PHCD_TRANSFER_CONTEXT Transfer
  759. )
  760. /*++
  761. Routine Description:
  762. simulates an interrupt transfer
  763. Arguments:
  764. Return Value:
  765. root hub transfer status code
  766. --*/
  767. {
  768. PDEVICE_OBJECT fdoDeviceObject;
  769. PDEVICE_EXTENSION rhDevExt, devExt;
  770. RHSTATUS rhStatus;
  771. ULONG need;
  772. RH_HUB_STATUS hubStatus;
  773. PHCD_ENDPOINT endpoint;
  774. PTRANSFER_URB urb;
  775. PVOID buffer;
  776. USB_MINIPORT_STATUS mpStatus;
  777. ULONG i;
  778. ASSERT_TRANSFER(Transfer);
  779. // assume no change
  780. rhStatus = RH_NAK;
  781. endpoint = Transfer->Endpoint;
  782. ASSERT_ENDPOINT(endpoint);
  783. fdoDeviceObject = endpoint->FdoDeviceObject;
  784. GET_DEVICE_EXT(devExt, fdoDeviceObject);
  785. ASSERT_FDOEXT(devExt);
  786. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_CONTROLLER_GONE)) {
  787. return rhStatus;
  788. }
  789. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  790. ASSERT_PDOEXT(rhDevExt);
  791. USBPORT_ASSERT(rhDevExt->Pdo.HubInitCallback == NULL);
  792. // validate the buffer length
  793. urb = Transfer->Urb;
  794. buffer = Transfer->Tp.TransferBufferLength ?
  795. urb->TransferBufferMDL->MappedSystemVa :
  796. NULL;
  797. // compute how many bytes do we need to report a status
  798. // change for any port
  799. // 0,1-7 = 1
  800. // 8-15 = 2
  801. need = (NUMBER_OF_PORTS(rhDevExt)/8)+1;
  802. if (buffer == NULL ||
  803. Transfer->Tp.TransferBufferLength < need) {
  804. DEBUG_BREAK();
  805. rhStatus = RH_STALL;
  806. goto USBPORT_RootHub_Endpoint1_Done;
  807. }
  808. // zero buffer in case hub driver did not
  809. RtlZeroMemory(buffer, Transfer->Tp.TransferBufferLength);
  810. // get the current port status and
  811. // construct a bitmask of changed ports
  812. for (i=0; i< NUMBER_OF_PORTS(rhDevExt); i++) {
  813. RH_PORT_STATUS portStatus;
  814. // usb spec does not allow more than 255 ports
  815. USBPORT_ASSERT(i<256);
  816. MPRH_GetPortStatus(devExt, (USHORT)(i+1), &portStatus, mpStatus);
  817. LOGENTRY(NULL, fdoDeviceObject, LOG_RH, 'gPS+', portStatus.ul,
  818. mpStatus, i+1);
  819. if (mpStatus != USBMP_STATUS_SUCCESS ) {
  820. DEBUG_BREAK();
  821. rhStatus = RH_STALL;
  822. goto USBPORT_RootHub_Endpoint1_Done;
  823. }
  824. if (portStatus.ConnectChange ||
  825. portStatus.EnableChange ||
  826. portStatus.SuspendChange ||
  827. portStatus.OverCurrentChange ||
  828. portStatus.ResetChange) {
  829. USBPORT_SetBit(buffer,
  830. i+1);
  831. rhStatus = RH_SUCCESS;
  832. }
  833. }
  834. //
  835. // We created a bit map (base of 1 not 0) listing whether or not
  836. // change has occurred on any of the down stream ports of the
  837. // root hub.
  838. // Bit 0 is reserved for the status change of the hub itself.
  839. //
  840. MPRH_GetHubStatus(devExt, &hubStatus, mpStatus);
  841. if (mpStatus != USBMP_STATUS_SUCCESS ) {
  842. DEBUG_BREAK();
  843. rhStatus = RH_STALL;
  844. goto USBPORT_RootHub_Endpoint1_Done;
  845. }
  846. if (hubStatus.LocalPowerChange ||
  847. hubStatus.OverCurrentChange) {
  848. USBPORT_SetBit(buffer,
  849. 0);
  850. rhStatus = RH_SUCCESS;
  851. }
  852. switch (rhStatus) {
  853. case RH_NAK:
  854. // we have a transfer pending but no changes yet
  855. // enable the controller to generate an interrupt
  856. // if a root hub change occurs
  857. MPRH_EnableIrq(devExt);
  858. break;
  859. case RH_SUCCESS:
  860. // set bytes transferred for this interrupt
  861. // endpoint
  862. urb->TransferBufferLength =
  863. Transfer->Tp.TransferBufferLength;
  864. break;
  865. case RH_STALL:
  866. DEBUG_BREAK();
  867. break;
  868. }
  869. USBPORT_RootHub_Endpoint1_Done:
  870. return rhStatus;
  871. }
  872. RHSTATUS
  873. USBPORT_RootHub_Endpoint0(
  874. PHCD_TRANSFER_CONTEXT Transfer
  875. )
  876. /*++
  877. Routine Description:
  878. Arguments:
  879. Return Value:
  880. root hub transfer status code
  881. --*/
  882. {
  883. RHSTATUS rhStatus;
  884. PTRANSFER_URB urb;
  885. PUSB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
  886. PUCHAR buffer;
  887. ULONG bufferLength;
  888. PHCD_ENDPOINT endpoint;
  889. PDEVICE_OBJECT fdoDeviceObject;
  890. ASSERT_TRANSFER(Transfer);
  891. urb = Transfer->Urb;
  892. endpoint = Transfer->Endpoint;
  893. ASSERT_ENDPOINT(endpoint);
  894. fdoDeviceObject = endpoint->FdoDeviceObject;
  895. //
  896. // convert transfer buffer from MDL
  897. //
  898. buffer =
  899. Transfer->Tp.TransferBufferLength ?
  900. urb->TransferBufferMDL->MappedSystemVa :
  901. NULL;
  902. bufferLength = Transfer->Tp.TransferBufferLength;
  903. setupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
  904. &urb->u.SetupPacket[0];
  905. if (setupPacket->bmRequestType.Type == RH_STANDARD_REQ) {
  906. rhStatus =
  907. USBPORT_RootHub_StandardCommand(fdoDeviceObject,
  908. setupPacket,
  909. buffer,
  910. &bufferLength);
  911. if (rhStatus == RH_SUCCESS) {
  912. // set the return length
  913. Transfer->MiniportBytesTransferred = bufferLength;
  914. }
  915. } else if (setupPacket->bmRequestType.Type == RH_CLASS_REQ) {
  916. rhStatus =
  917. USBPORT_RootHub_ClassCommand(fdoDeviceObject,
  918. setupPacket,
  919. buffer,
  920. &bufferLength);
  921. if (rhStatus == RH_SUCCESS) {
  922. // set the return length
  923. Transfer->MiniportBytesTransferred = bufferLength;
  924. }
  925. } else {
  926. rhStatus = RH_STALL;
  927. // probably a bug in the hub driver
  928. DEBUG_BREAK();
  929. }
  930. return rhStatus;
  931. }
  932. NTSTATUS
  933. USBPORT_RootHub_CreateDevice(
  934. PDEVICE_OBJECT FdoDeviceObject,
  935. PDEVICE_OBJECT PdoDeviceObject
  936. )
  937. /*++
  938. Routine Description:
  939. Create the 'ROOT HUB' USB Device
  940. Arguments:
  941. Return Value:
  942. --*/
  943. {
  944. PDEVICE_EXTENSION rhDevExt, devExt;
  945. NTSTATUS ntStatus;
  946. PUCHAR descriptors;
  947. ROOTHUB_DATA hubData;
  948. ULONG hubDescriptorLength, length;
  949. ULONG i, portbytes;
  950. PAGED_CODE();
  951. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  952. ASSERT_FDOEXT(devExt);
  953. GET_DEVICE_EXT(rhDevExt, PdoDeviceObject);
  954. ASSERT_PDOEXT(rhDevExt);
  955. USBPORT_ASSERT(devExt->Fdo.RootHubPdo == PdoDeviceObject);
  956. // init the device handle
  957. rhDevExt->Pdo.RootHubDeviceHandle.Sig = SIG_DEVICE_HANDLE;
  958. rhDevExt->Pdo.RootHubDeviceHandle.DeviceAddress = 0;
  959. rhDevExt->Pdo.RootHubDeviceHandle.ConfigurationHandle = NULL;
  960. rhDevExt->Pdo.RootHubDeviceHandle.DeviceFlags =
  961. USBPORT_DEVICEFLAG_ROOTHUB;
  962. // define root hub speed based on the type of conroller
  963. if (USBPORT_IS_USB20(devExt)) {
  964. rhDevExt->Pdo.RootHubDeviceHandle.DeviceSpeed = UsbHighSpeed;
  965. } else {
  966. rhDevExt->Pdo.RootHubDeviceHandle.DeviceSpeed = UsbFullSpeed;
  967. }
  968. InitializeListHead(&rhDevExt->Pdo.RootHubDeviceHandle.PipeHandleList);
  969. InitializeListHead(&rhDevExt->Pdo.RootHubDeviceHandle.TtList);
  970. USBPORT_AddDeviceHandle(FdoDeviceObject,
  971. &rhDevExt->Pdo.RootHubDeviceHandle);
  972. // assume success
  973. ntStatus = STATUS_SUCCESS;
  974. // root hub device is not configured yet
  975. rhDevExt->Pdo.ConfigurationValue = 0;
  976. // get root hub information from the miniport
  977. MPRH_GetRootHubData(devExt, &hubData);
  978. // use hub data to fabricate a hub descriptor
  979. // figure out how many bytes the variable part
  980. // it will be based on the nuber of ports
  981. // ie how many bytes does it take to represent
  982. // n ports
  983. // 1-8 ports = 1 bytes
  984. // 9-16 ports = 2 bytes
  985. // 17-24 ports = 3 bytes
  986. // 25-36 ports = 4 bytes
  987. //...
  988. USBPORT_ASSERT(hubData.NumberOfPorts != 0);
  989. // number of bytes we need to represnt the ports
  990. portbytes = ((((hubData.NumberOfPorts-1)/8)+1));
  991. hubDescriptorLength = 7+(portbytes*2);
  992. length =
  993. sizeof(RH_ConfigurationDescriptor) +
  994. sizeof(RH_DeviceDescriptor) +
  995. hubDescriptorLength;
  996. // allocate space for our descriports
  997. ALLOC_POOL_Z(descriptors, NonPagedPool,
  998. length);
  999. if (descriptors) {
  1000. LOGENTRY(NULL, FdoDeviceObject,
  1001. LOG_RH, 'rhDS', descriptors, length, portbytes);
  1002. rhDevExt->Pdo.Descriptors = descriptors;
  1003. // set up device descriptor
  1004. rhDevExt->Pdo.DeviceDescriptor =
  1005. (PUSB_DEVICE_DESCRIPTOR) descriptors;
  1006. descriptors += sizeof(RH_DeviceDescriptor);
  1007. RtlCopyMemory(rhDevExt->Pdo.DeviceDescriptor,
  1008. &RH_DeviceDescriptor[0],
  1009. sizeof(RH_DeviceDescriptor));
  1010. // hack it up for USB2
  1011. if (USBPORT_IS_USB20(devExt)) {
  1012. rhDevExt->Pdo.DeviceDescriptor->bcdUSB = 0x0200;
  1013. }
  1014. // use HC vendor and device for root hub
  1015. rhDevExt->Pdo.DeviceDescriptor->idVendor =
  1016. devExt->Fdo.PciVendorId;
  1017. rhDevExt->Pdo.DeviceDescriptor->idProduct =
  1018. devExt->Fdo.PciDeviceId;
  1019. rhDevExt->Pdo.DeviceDescriptor->bcdDevice =
  1020. devExt->Fdo.PciRevisionId;
  1021. // set up config descriptor
  1022. rhDevExt->Pdo.ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)
  1023. descriptors;
  1024. LOGENTRY(NULL, FdoDeviceObject,
  1025. LOG_RH, 'rhCS', descriptors,0, 0);
  1026. descriptors += sizeof(RH_ConfigurationDescriptor);
  1027. RtlCopyMemory(rhDevExt->Pdo.ConfigurationDescriptor,
  1028. &RH_ConfigurationDescriptor[0],
  1029. sizeof(RH_ConfigurationDescriptor));
  1030. // set up the hub descriptor
  1031. rhDevExt->Pdo.HubDescriptor =
  1032. (PUSB_HUB_DESCRIPTOR) descriptors;
  1033. LOGENTRY(NULL, FdoDeviceObject,
  1034. LOG_RH, 'rhHS', descriptors,0, 0);
  1035. RtlCopyMemory(rhDevExt->Pdo.HubDescriptor,
  1036. &RH_HubDescriptor[0],
  1037. sizeof(RH_HubDescriptor));
  1038. rhDevExt->Pdo.HubDescriptor->bDescriptorLength =
  1039. hubDescriptorLength;
  1040. rhDevExt->Pdo.HubDescriptor->bNumberOfPorts =
  1041. (UCHAR) hubData.NumberOfPorts;
  1042. rhDevExt->Pdo.HubDescriptor->wHubCharacteristics =
  1043. hubData.HubCharacteristics.us;
  1044. rhDevExt->Pdo.HubDescriptor->bPowerOnToPowerGood =
  1045. hubData.PowerOnToPowerGood;
  1046. rhDevExt->Pdo.HubDescriptor->bHubControlCurrent =
  1047. hubData.HubControlCurrent;
  1048. // fill in the var part
  1049. for (i=0; i<portbytes; i++) {
  1050. rhDevExt->Pdo.HubDescriptor->bRemoveAndPowerMask[i] =
  1051. 0;
  1052. rhDevExt->Pdo.HubDescriptor->bRemoveAndPowerMask[i+portbytes] =
  1053. 0xff;
  1054. }
  1055. INITIALIZE_DEFAULT_PIPE(rhDevExt->Pdo.RootHubDeviceHandle.DefaultPipe,
  1056. USB_DEFAULT_MAX_PACKET);
  1057. // init the default pipe
  1058. ntStatus = USBPORT_OpenEndpoint(
  1059. &rhDevExt->Pdo.RootHubDeviceHandle,
  1060. FdoDeviceObject,
  1061. &rhDevExt->Pdo.RootHubDeviceHandle.DefaultPipe,
  1062. NULL,
  1063. TRUE);
  1064. } else {
  1065. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1066. }
  1067. return ntStatus;
  1068. }
  1069. VOID
  1070. USBPORT_RootHub_RemoveDevice(
  1071. PDEVICE_OBJECT FdoDeviceObject,
  1072. PDEVICE_OBJECT PdoDeviceObject
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. Remove the 'ROOT HUB' USB Device
  1077. Arguments:
  1078. Return Value:
  1079. --*/
  1080. {
  1081. PDEVICE_EXTENSION rhDevExt;
  1082. LOGENTRY(NULL, FdoDeviceObject,
  1083. LOG_RH, 'rhrm', 0, 0, 0);
  1084. ASSERT_PASSIVE();
  1085. GET_DEVICE_EXT(rhDevExt, PdoDeviceObject);
  1086. ASSERT_PDOEXT(rhDevExt);
  1087. // close the current config
  1088. USBPORT_InternalCloseConfiguration(
  1089. &rhDevExt->Pdo.RootHubDeviceHandle,
  1090. FdoDeviceObject,
  1091. 0);
  1092. // close the default pipe
  1093. USBPORT_ClosePipe(
  1094. &rhDevExt->Pdo.RootHubDeviceHandle,
  1095. FdoDeviceObject,
  1096. &rhDevExt->Pdo.RootHubDeviceHandle.DefaultPipe);
  1097. USBPORT_RemoveDeviceHandle(FdoDeviceObject,
  1098. &rhDevExt->Pdo.RootHubDeviceHandle);
  1099. FREE_POOL(FdoDeviceObject, rhDevExt->Pdo.Descriptors);
  1100. rhDevExt->Pdo.Descriptors = USBPORT_BAD_POINTER;
  1101. }
  1102. VOID
  1103. USBPORT_RootHub_EndpointWorker(
  1104. PHCD_ENDPOINT Endpoint
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. process transfers for the root hub
  1109. Arguments:
  1110. Return Value:
  1111. None.
  1112. --*/
  1113. {
  1114. PIRP irp;
  1115. PLIST_ENTRY listEntry;
  1116. PTRANSFER_URB urb;
  1117. PHCD_TRANSFER_CONTEXT transfer = NULL;
  1118. USBD_STATUS usbdStatus;
  1119. RHSTATUS rhStatus;
  1120. PDEVICE_OBJECT fdoDeviceObject;
  1121. PDEVICE_EXTENSION devExt;
  1122. ASSERT_ENDPOINT(Endpoint);
  1123. fdoDeviceObject = Endpoint->FdoDeviceObject;
  1124. GET_DEVICE_EXT(devExt, fdoDeviceObject);
  1125. ASSERT_FDOEXT(devExt);
  1126. MP_CheckController(devExt);
  1127. ACQUIRE_ENDPOINT_LOCK(Endpoint, fdoDeviceObject, 'LeA0');
  1128. // Now check the active list, and process
  1129. // the transfers on it
  1130. GET_HEAD_LIST(Endpoint->ActiveList, listEntry);
  1131. if (listEntry) {
  1132. // ACTIVE(r)->
  1133. // extract the urb that is currently on the active
  1134. // list, there should only be one
  1135. transfer = (PHCD_TRANSFER_CONTEXT) CONTAINING_RECORD(
  1136. listEntry,
  1137. struct _HCD_TRANSFER_CONTEXT,
  1138. TransferLink);
  1139. LOGENTRY(NULL, fdoDeviceObject, LOG_RH, 'rACT', transfer, 0, 0);
  1140. ASSERT_TRANSFER(transfer);
  1141. }
  1142. if (transfer) {
  1143. ASSERT_TRANSFER(transfer);
  1144. // is this transfer canceled?
  1145. if ((transfer->Flags & USBPORT_TXFLAG_CANCELED) ||
  1146. (transfer->Flags & USBPORT_TXFLAG_ABORTED)) {
  1147. // yes,
  1148. // just put it on the cancel list
  1149. // since this routine is NOT renetrant
  1150. // it will not be completed
  1151. // remove from active
  1152. RemoveEntryList(&transfer->TransferLink);
  1153. // insert on cancel
  1154. InsertTailList(&Endpoint->CancelList, &transfer->TransferLink);
  1155. // removed from active list
  1156. RELEASE_ENDPOINT_LOCK(Endpoint, fdoDeviceObject, 'UeA0');
  1157. } else {
  1158. // transfer is not canceled, process it
  1159. // NOTE: if the transfer is canceled at
  1160. // this point it is only marked since it
  1161. // is on the active list
  1162. RELEASE_ENDPOINT_LOCK(Endpoint, fdoDeviceObject, 'UeA1');
  1163. // relaese the lock no so that the miniport may freely
  1164. // call InvalidateRootHub. Root hub functions so not take
  1165. // the core spinlock
  1166. // call root hub code
  1167. if (Endpoint->Parameters.TransferType == Control) {
  1168. rhStatus = USBPORT_RootHub_Endpoint0(transfer);
  1169. } else {
  1170. rhStatus = USBPORT_RootHub_Endpoint1(transfer);
  1171. // if the interrupt ep nak'ed enable interrupt
  1172. // changes
  1173. }
  1174. LOGENTRY(NULL, fdoDeviceObject, LOG_RH, 'ACT+', transfer, rhStatus, 0);
  1175. if (rhStatus != RH_NAK) {
  1176. // transfer is done.
  1177. // NOTE: that donetransfer can only be called from this
  1178. // routine and that this routine is NOT reentrant.
  1179. // Hence, we don't need to worry about race conditions
  1180. // caused by multiple calls to DoneTransfer
  1181. usbdStatus = RHSTATUS_TO_USBDSTATUS(rhStatus);
  1182. // This function expects the endpoint lock to be held
  1183. // although it is not necessary in the case of the root
  1184. // hub
  1185. ACQUIRE_ENDPOINT_LOCK(Endpoint, fdoDeviceObject, 'LeX0');
  1186. USBPORT_QueueDoneTransfer(transfer,
  1187. usbdStatus);
  1188. RELEASE_ENDPOINT_LOCK(Endpoint, fdoDeviceObject, 'UeX0');
  1189. }
  1190. }
  1191. } else {
  1192. // transfer queues empty
  1193. if (Endpoint->CurrentState == ENDPOINT_REMOVE) {
  1194. // put the endpoint on the closed list
  1195. LOGENTRY(NULL, fdoDeviceObject, LOG_PNP, 'rmRE', 0, Endpoint, 0);
  1196. ExInterlockedInsertTailList(&devExt->Fdo.EpClosedList,
  1197. &Endpoint->ClosedLink,
  1198. &devExt->Fdo.EpClosedListSpin.sl);
  1199. }
  1200. RELEASE_ENDPOINT_LOCK(Endpoint, fdoDeviceObject, 'UeA2');
  1201. }
  1202. // flush out canceled requests
  1203. USBPORT_FlushCancelList(Endpoint);
  1204. }
  1205. VOID
  1206. USBPORT_InvalidateRootHub(
  1207. PDEVICE_OBJECT FdoDeviceObject
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. Invalidates the state of the root hub, this will
  1212. trigger USBPORT to poll the root hub for any
  1213. changes.
  1214. Arguments:
  1215. Return Value:
  1216. None.
  1217. --*/
  1218. {
  1219. PHCD_ENDPOINT endpoint = NULL;
  1220. PDEVICE_EXTENSION devExt, rhDevExt;
  1221. KIRQL irql;
  1222. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1223. ASSERT_FDOEXT(devExt);
  1224. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'rhIV', 0, 0, 0);
  1225. // disable the root hub notification interrupt
  1226. MPRH_DisableIrq(devExt);
  1227. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_SUSPENDED)) {
  1228. USBPORT_HcQueueWakeDpc(FdoDeviceObject);
  1229. return;
  1230. }
  1231. // make sure we have an endpoint
  1232. ACQUIRE_ROOTHUB_LOCK(FdoDeviceObject, irql);
  1233. if (devExt->Fdo.RootHubPdo) {
  1234. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  1235. ASSERT_PDOEXT(rhDevExt);
  1236. endpoint = rhDevExt->Pdo.RootHubInterruptEndpoint;
  1237. }
  1238. RELEASE_ROOTHUB_LOCK(FdoDeviceObject, irql);
  1239. // if we have an endpoint, hence, a root hub then
  1240. // process requests
  1241. if (endpoint) {
  1242. USBPORT_InvalidateEndpoint(FdoDeviceObject,
  1243. rhDevExt->Pdo.RootHubInterruptEndpoint,
  1244. IEP_SIGNAL_WORKER);
  1245. }
  1246. }
  1247. VOID
  1248. USBPORTSVC_InvalidateRootHub(
  1249. PDEVICE_DATA DeviceData
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. Service exported to miniports.
  1254. Arguments:
  1255. Return Value:
  1256. None.
  1257. --*/
  1258. {
  1259. PDEVICE_EXTENSION devExt;
  1260. PDEVICE_OBJECT fdoDeviceObject;
  1261. DEVEXT_FROM_DEVDATA(devExt, DeviceData);
  1262. ASSERT_FDOEXT(devExt);
  1263. fdoDeviceObject = devExt->HcFdoDeviceObject;
  1264. LOGENTRY(NULL, fdoDeviceObject, LOG_RH, 'rhNO', 0, 0, 0);
  1265. USBPORT_InvalidateRootHub(fdoDeviceObject);
  1266. }
  1267. VOID
  1268. USBPORT_UserSetRootPortFeature(
  1269. PDEVICE_OBJECT FdoDeviceObject,
  1270. PUSBUSER_REQUEST_HEADER Header,
  1271. PRAW_ROOTPORT_FEATURE Parameters
  1272. )
  1273. /*++
  1274. Routine Description:
  1275. Cycle a specific Root Port
  1276. Arguments:
  1277. DeviceObject - Fdo for USB HC
  1278. Return Value:
  1279. none.
  1280. --*/
  1281. {
  1282. ULONG currentFrame, nextFrame;
  1283. PDEVICE_EXTENSION devExt;
  1284. USB_MINIPORT_STATUS mpStatus;
  1285. USB_USER_ERROR_CODE usbUserStatus;
  1286. RH_PORT_STATUS portStatus;
  1287. USBPORT_KdPrint((2, "'USBPORT_UserSetRootPortFeature\n"));
  1288. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1289. ASSERT_FDOEXT(devExt);
  1290. usbUserStatus = UsbUserSuccess;
  1291. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'SRpF', 0, Parameters->PortNumber, Parameters->PortFeature);
  1292. if (!USBPORT_ValidateRootPortApi(FdoDeviceObject, Parameters->PortNumber)) {
  1293. Header->UsbUserStatusCode =
  1294. usbUserStatus = UsbUserInvalidParameter;
  1295. return;
  1296. }
  1297. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  1298. Header->UsbUserStatusCode = UsbUserFeatureDisabled;
  1299. return;
  1300. }
  1301. switch(Parameters->PortFeature) {
  1302. case PORT_RESET:
  1303. {
  1304. ULONG loopCount = 0;
  1305. // attempt a reset
  1306. devExt->Fdo.MiniportDriver->
  1307. RegistrationPacket.MINIPORT_RH_SetFeaturePortReset(
  1308. devExt->Fdo.MiniportDeviceData,
  1309. Parameters->PortNumber);
  1310. // wait for reset change, this process is drive byn the
  1311. // HC root hub hardware or miniport
  1312. do {
  1313. /*
  1314. USBPORT_Wait(FdoDeviceObject, 1);
  1315. */
  1316. MP_Get32BitFrameNumber(devExt, currentFrame);
  1317. do {
  1318. MP_Get32BitFrameNumber(devExt, nextFrame);
  1319. if(nextFrame < currentFrame) {
  1320. // roll-over
  1321. //
  1322. currentFrame = nextFrame;
  1323. MP_Get32BitFrameNumber(devExt, nextFrame);
  1324. }
  1325. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1326. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1327. &portStatus, mpStatus);
  1328. loopCount++;
  1329. } while ((portStatus.ResetChange == 0) &&
  1330. (loopCount < 5));
  1331. // clear the change bit
  1332. devExt->Fdo.MiniportDriver->
  1333. RegistrationPacket.MINIPORT_RH_ClearFeaturePortResetChange(
  1334. devExt->Fdo.MiniportDeviceData,
  1335. Parameters->PortNumber);
  1336. // status is low 16 bits
  1337. Parameters->PortStatus = (USHORT) portStatus.ul;
  1338. break;
  1339. }
  1340. case PORT_POWER:
  1341. // power the port
  1342. devExt->Fdo.MiniportDriver->
  1343. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  1344. devExt->Fdo.MiniportDeviceData,
  1345. Parameters->PortNumber);
  1346. /*
  1347. USBPORT_Wait(FdoDeviceObject, 1);
  1348. */
  1349. MP_Get32BitFrameNumber(devExt, currentFrame);
  1350. do {
  1351. MP_Get32BitFrameNumber(devExt, nextFrame);
  1352. if(nextFrame < currentFrame) {
  1353. // roll-over
  1354. //
  1355. currentFrame = nextFrame;
  1356. MP_Get32BitFrameNumber(devExt, nextFrame);
  1357. }
  1358. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1359. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1360. &portStatus, mpStatus);
  1361. // status is low 16 bits
  1362. Parameters->PortStatus = (USHORT) portStatus.ul;
  1363. break;
  1364. case PORT_ENABLE:
  1365. // enable the port
  1366. devExt->Fdo.MiniportDriver->
  1367. RegistrationPacket.MINIPORT_RH_SetFeaturePortEnable(
  1368. devExt->Fdo.MiniportDeviceData,
  1369. Parameters->PortNumber);
  1370. /*
  1371. USBPORT_Wait(FdoDeviceObject, 1);
  1372. */
  1373. MP_Get32BitFrameNumber(devExt, currentFrame);
  1374. do {
  1375. MP_Get32BitFrameNumber(devExt, nextFrame);
  1376. if(nextFrame < currentFrame) {
  1377. // roll-over
  1378. //
  1379. currentFrame = nextFrame;
  1380. MP_Get32BitFrameNumber(devExt, nextFrame);
  1381. }
  1382. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1383. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1384. &portStatus, mpStatus);
  1385. // status is low 16 bits
  1386. Parameters->PortStatus = (USHORT) portStatus.ul;
  1387. break;
  1388. case PORT_SUSPEND:
  1389. // suspend the port
  1390. devExt->Fdo.MiniportDriver->
  1391. RegistrationPacket.MINIPORT_RH_SetFeaturePortSuspend(
  1392. devExt->Fdo.MiniportDeviceData,
  1393. Parameters->PortNumber);
  1394. /*
  1395. USBPORT_Wait(FdoDeviceObject, 1);
  1396. */
  1397. MP_Get32BitFrameNumber(devExt, currentFrame);
  1398. do {
  1399. MP_Get32BitFrameNumber(devExt, nextFrame);
  1400. if(nextFrame < currentFrame) {
  1401. // roll-over
  1402. //
  1403. currentFrame = nextFrame;
  1404. MP_Get32BitFrameNumber(devExt, nextFrame);
  1405. }
  1406. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1407. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1408. &portStatus, mpStatus);
  1409. // status is low 16 bits
  1410. Parameters->PortStatus = (USHORT) portStatus.ul;
  1411. break;
  1412. default:
  1413. usbUserStatus = UsbUserNotSupported;
  1414. break;
  1415. }
  1416. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'SRp>', 0, 0, usbUserStatus);
  1417. Header->UsbUserStatusCode = usbUserStatus;
  1418. }
  1419. VOID
  1420. USBPORT_UserClearRootPortFeature(
  1421. PDEVICE_OBJECT FdoDeviceObject,
  1422. PUSBUSER_REQUEST_HEADER Header,
  1423. PRAW_ROOTPORT_FEATURE Parameters
  1424. )
  1425. /*++
  1426. Routine Description:
  1427. Cycle a specific Root Port
  1428. Arguments:
  1429. DeviceObject - Fdo for USB HC
  1430. Return Value:
  1431. none.
  1432. --*/
  1433. {
  1434. ULONG currentFrame, nextFrame;
  1435. PDEVICE_EXTENSION devExt;
  1436. USB_MINIPORT_STATUS mpStatus;
  1437. USB_USER_ERROR_CODE usbUserStatus;
  1438. RH_PORT_STATUS portStatus;
  1439. USBPORT_KdPrint((2, "'USBPORT_UserRawResetPort\n"));
  1440. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1441. ASSERT_FDOEXT(devExt);
  1442. usbUserStatus = UsbUserSuccess;
  1443. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'CFRp', 0, Parameters->PortNumber, Parameters->PortFeature);
  1444. if (!USBPORT_ValidateRootPortApi(FdoDeviceObject, Parameters->PortNumber)) {
  1445. Header->UsbUserStatusCode =
  1446. usbUserStatus = UsbUserInvalidParameter;
  1447. return;
  1448. }
  1449. if (!USBPORT_DCA_Enabled(FdoDeviceObject)) {
  1450. Header->UsbUserStatusCode = UsbUserFeatureDisabled;
  1451. return;
  1452. }
  1453. switch(Parameters->PortFeature) {
  1454. case PORT_ENABLE:
  1455. devExt->Fdo.MiniportDriver->
  1456. RegistrationPacket.MINIPORT_RH_ClearFeaturePortEnable(
  1457. devExt->Fdo.MiniportDeviceData,
  1458. Parameters->PortNumber);
  1459. /*
  1460. USBPORT_Wait(FdoDeviceObject, 1);
  1461. */
  1462. MP_Get32BitFrameNumber(devExt, currentFrame);
  1463. do {
  1464. MP_Get32BitFrameNumber(devExt, nextFrame);
  1465. if(nextFrame < currentFrame) {
  1466. // roll-over
  1467. //
  1468. currentFrame = nextFrame;
  1469. MP_Get32BitFrameNumber(devExt, nextFrame);
  1470. }
  1471. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1472. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1473. &portStatus, mpStatus);
  1474. // status is low 16 bits
  1475. Parameters->PortStatus = (USHORT) portStatus.ul;
  1476. break;
  1477. case PORT_POWER:
  1478. devExt->Fdo.MiniportDriver->
  1479. RegistrationPacket.MINIPORT_RH_ClearFeaturePortPower(
  1480. devExt->Fdo.MiniportDeviceData,
  1481. Parameters->PortNumber);
  1482. /*
  1483. USBPORT_Wait(FdoDeviceObject, 1);
  1484. */
  1485. MP_Get32BitFrameNumber(devExt, currentFrame);
  1486. do {
  1487. MP_Get32BitFrameNumber(devExt, nextFrame);
  1488. if(nextFrame < currentFrame) {
  1489. // roll-over
  1490. //
  1491. currentFrame = nextFrame;
  1492. MP_Get32BitFrameNumber(devExt, nextFrame);
  1493. }
  1494. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1495. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1496. &portStatus, mpStatus);
  1497. // status is low 16 bits
  1498. Parameters->PortStatus = (USHORT) portStatus.ul;
  1499. break;
  1500. case PORT_SUSPEND:
  1501. devExt->Fdo.MiniportDriver->
  1502. RegistrationPacket.MINIPORT_RH_ClearFeaturePortSuspend(
  1503. devExt->Fdo.MiniportDeviceData,
  1504. Parameters->PortNumber);
  1505. /*
  1506. USBPORT_Wait(FdoDeviceObject, 1);
  1507. */
  1508. MP_Get32BitFrameNumber(devExt, currentFrame);
  1509. do {
  1510. MP_Get32BitFrameNumber(devExt, nextFrame);
  1511. if(nextFrame < currentFrame) {
  1512. // roll-over
  1513. //
  1514. currentFrame = nextFrame;
  1515. MP_Get32BitFrameNumber(devExt, nextFrame);
  1516. }
  1517. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1518. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1519. &portStatus, mpStatus);
  1520. // status is low 16 bits
  1521. Parameters->PortStatus = (USHORT) portStatus.ul;
  1522. break;
  1523. case C_PORT_ENABLE:
  1524. devExt->Fdo.MiniportDriver->
  1525. RegistrationPacket.MINIPORT_RH_ClearFeaturePortEnableChange(
  1526. devExt->Fdo.MiniportDeviceData,
  1527. Parameters->PortNumber);
  1528. /*
  1529. USBPORT_Wait(FdoDeviceObject, 1);
  1530. */
  1531. MP_Get32BitFrameNumber(devExt, currentFrame);
  1532. do {
  1533. MP_Get32BitFrameNumber(devExt, nextFrame);
  1534. if(nextFrame < currentFrame) {
  1535. // roll-over
  1536. //
  1537. currentFrame = nextFrame;
  1538. MP_Get32BitFrameNumber(devExt, nextFrame);
  1539. }
  1540. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1541. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1542. &portStatus, mpStatus);
  1543. // status is low 16 bits
  1544. Parameters->PortStatus = (USHORT) portStatus.ul;
  1545. break;
  1546. case C_PORT_CONNECTION:
  1547. devExt->Fdo.MiniportDriver->
  1548. RegistrationPacket.MINIPORT_RH_ClearFeaturePortConnectChange(
  1549. devExt->Fdo.MiniportDeviceData,
  1550. Parameters->PortNumber);
  1551. /*
  1552. USBPORT_Wait(FdoDeviceObject, 1);
  1553. */
  1554. MP_Get32BitFrameNumber(devExt, currentFrame);
  1555. do {
  1556. MP_Get32BitFrameNumber(devExt, nextFrame);
  1557. if(nextFrame < currentFrame) {
  1558. // roll-over
  1559. //
  1560. currentFrame = nextFrame;
  1561. MP_Get32BitFrameNumber(devExt, nextFrame);
  1562. }
  1563. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1564. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1565. &portStatus, mpStatus);
  1566. // status is low 16 bits
  1567. Parameters->PortStatus = (USHORT) portStatus.ul;
  1568. break;
  1569. case C_PORT_RESET:
  1570. devExt->Fdo.MiniportDriver->
  1571. RegistrationPacket.MINIPORT_RH_ClearFeaturePortResetChange(
  1572. devExt->Fdo.MiniportDeviceData,
  1573. Parameters->PortNumber);
  1574. /*
  1575. USBPORT_Wait(FdoDeviceObject, 1);
  1576. */
  1577. MP_Get32BitFrameNumber(devExt, currentFrame);
  1578. do {
  1579. MP_Get32BitFrameNumber(devExt, nextFrame);
  1580. if(nextFrame < currentFrame) {
  1581. // roll-over
  1582. //
  1583. currentFrame = nextFrame;
  1584. MP_Get32BitFrameNumber(devExt, nextFrame);
  1585. }
  1586. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1587. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1588. &portStatus, mpStatus);
  1589. // status is low 16 bits
  1590. Parameters->PortStatus = (USHORT) portStatus.ul;
  1591. break;
  1592. case C_PORT_SUSPEND:
  1593. devExt->Fdo.MiniportDriver->
  1594. RegistrationPacket.MINIPORT_RH_ClearFeaturePortSuspendChange(
  1595. devExt->Fdo.MiniportDeviceData,
  1596. Parameters->PortNumber);
  1597. /*
  1598. USBPORT_Wait(FdoDeviceObject, 1);
  1599. */
  1600. MP_Get32BitFrameNumber(devExt, currentFrame);
  1601. do {
  1602. MP_Get32BitFrameNumber(devExt, nextFrame);
  1603. if(nextFrame < currentFrame) {
  1604. // roll-over
  1605. //
  1606. currentFrame = nextFrame;
  1607. MP_Get32BitFrameNumber(devExt, nextFrame);
  1608. }
  1609. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1610. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1611. &portStatus, mpStatus);
  1612. // status is low 16 bits
  1613. Parameters->PortStatus = (USHORT) portStatus.ul;
  1614. break;
  1615. case C_PORT_OVER_CURRENT:
  1616. devExt->Fdo.MiniportDriver->
  1617. RegistrationPacket.MINIPORT_RH_ClearFeaturePortOvercurrentChange(
  1618. devExt->Fdo.MiniportDeviceData,
  1619. Parameters->PortNumber);
  1620. /*
  1621. USBPORT_Wait(FdoDeviceObject, 1);
  1622. */
  1623. MP_Get32BitFrameNumber(devExt, currentFrame);
  1624. do {
  1625. MP_Get32BitFrameNumber(devExt, nextFrame);
  1626. if(nextFrame < currentFrame) {
  1627. // roll-over
  1628. //
  1629. currentFrame = nextFrame;
  1630. MP_Get32BitFrameNumber(devExt, nextFrame);
  1631. }
  1632. } while ((nextFrame - currentFrame) < FRAME_COUNT_WAIT);
  1633. MPRH_GetPortStatus(devExt, (USHORT)(Parameters->PortNumber),
  1634. &portStatus, mpStatus);
  1635. // status is low 16 bits
  1636. Parameters->PortStatus = (USHORT) portStatus.ul;
  1637. break;
  1638. default:
  1639. usbUserStatus = UsbUserNotSupported;
  1640. break;
  1641. }
  1642. LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'CFR>', 0, 0, usbUserStatus);
  1643. Header->UsbUserStatusCode = usbUserStatus;
  1644. }
  1645. USB_MINIPORT_STATUS
  1646. USBPORT_RootHub_PowerUsb2Port(
  1647. PDEVICE_OBJECT FdoDeviceObject,
  1648. USHORT Port
  1649. )
  1650. /*++
  1651. Routine Description:
  1652. Power up the USB 2 port and the assocaited CC port
  1653. Arguments:
  1654. DeviceObject - Fdo for USB HC
  1655. Return Value:
  1656. miniport status
  1657. --*/
  1658. {
  1659. PDEVICE_EXTENSION devExt, rhDevExt;
  1660. USB_MINIPORT_STATUS mpStatus;
  1661. PDEVICE_RELATIONS devRelations;
  1662. USHORT p;
  1663. ULONG i;
  1664. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1665. ASSERT_FDOEXT(devExt);
  1666. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  1667. ASSERT_PDOEXT(rhDevExt);
  1668. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, '20pw', 0, 0, 0);
  1669. // power the associated CC controllers ports
  1670. // for now power all ports for any CC
  1671. devRelations =
  1672. USBPORT_FindCompanionControllers(FdoDeviceObject,
  1673. FALSE,
  1674. TRUE);
  1675. // may get NULL here if no CCs found or are registered
  1676. for (i=0; devRelations && i< devRelations->Count; i++) {
  1677. PDEVICE_OBJECT fdo = devRelations->Objects[i];
  1678. PDEVICE_EXTENSION ccDevExt, ccRhDevExt;
  1679. LOGENTRY(NULL, FdoDeviceObject, LOG_PNP, 'pwCC', fdo,
  1680. 0, 0);
  1681. GET_DEVICE_EXT(ccDevExt, fdo);
  1682. ASSERT_FDOEXT(ccDevExt);
  1683. GET_DEVICE_EXT(ccRhDevExt, ccDevExt->Fdo.RootHubPdo);
  1684. ASSERT_PDOEXT(ccRhDevExt);
  1685. // power the port
  1686. for (p=0;
  1687. (ccRhDevExt->PnpStateFlags & USBPORT_PNP_STARTED) &&
  1688. p< NUMBER_OF_PORTS(ccRhDevExt);
  1689. p++) {
  1690. ccDevExt->Fdo.MiniportDriver->
  1691. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  1692. ccDevExt->Fdo.MiniportDeviceData,
  1693. p+1);
  1694. }
  1695. }
  1696. devExt->Fdo.MiniportDriver->
  1697. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  1698. devExt->Fdo.MiniportDeviceData,
  1699. Port);
  1700. // jd xxx
  1701. // chirp it
  1702. //devExt->Fdo.MiniportDriver->
  1703. // RegistrationPacket.MINIPORT_Chirp_RH_Port(
  1704. // devExt->Fdo.MiniportDeviceData,
  1705. // Port);
  1706. // thou shall not leak memory
  1707. if (devRelations != NULL) {
  1708. FREE_POOL(FdoDeviceObject, devRelations);
  1709. }
  1710. return USBMP_STATUS_SUCCESS;
  1711. }
  1712. USB_MINIPORT_STATUS
  1713. USBPORT_RootHub_PowerUsbCcPort(
  1714. PDEVICE_OBJECT FdoDeviceObject,
  1715. USHORT Port
  1716. )
  1717. /*++
  1718. Routine Description:
  1719. Power up the USB port on a CC
  1720. Arguments:
  1721. DeviceObject - Fdo for USB HC
  1722. Return Value:
  1723. miniport status
  1724. --*/
  1725. {
  1726. PDEVICE_EXTENSION devExt, rhDevExt;
  1727. // PDEVICE_OBJECT usb2Fdo;
  1728. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1729. ASSERT_FDOEXT(devExt);
  1730. GET_DEVICE_EXT(rhDevExt, devExt->Fdo.RootHubPdo);
  1731. ASSERT_PDOEXT(rhDevExt);
  1732. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'CCpw', 0, 0, Port);
  1733. // if there is a 2.0 controller then
  1734. // this a noop, port should already be powered
  1735. //usb2Fdo = USBPORT_FindUSB2Controller(FdoDeviceObject);
  1736. // no 2.0 controller power this port
  1737. devExt->Fdo.MiniportDriver->
  1738. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  1739. devExt->Fdo.MiniportDeviceData,
  1740. Port);
  1741. return USBMP_STATUS_SUCCESS;
  1742. }
  1743. USB_MINIPORT_STATUS
  1744. USBPORT_RootHub_PowerAndChirpAllCcPorts(
  1745. PDEVICE_OBJECT FdoDeviceObject
  1746. )
  1747. /*++
  1748. Routine Description:
  1749. Power up all the USB ports on a CC
  1750. Arguments:
  1751. DeviceObject - Fdo for USB Companion
  1752. Return Value:
  1753. miniport status
  1754. --*/
  1755. {
  1756. PDEVICE_EXTENSION devExt;
  1757. USB_MINIPORT_STATUS mpStatus;
  1758. USHORT p;
  1759. ULONG i;
  1760. PDEVICE_OBJECT usb2Fdo;
  1761. ROOTHUB_DATA hubData;
  1762. ULONG nPorts;
  1763. ASSERT_PASSIVE();
  1764. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  1765. ASSERT_FDOEXT(devExt);
  1766. MPRH_GetRootHubData(devExt, &hubData);
  1767. nPorts = hubData.NumberOfPorts;
  1768. LOGENTRY(NULL, FdoDeviceObject, LOG_RH, 'CCpw', 0, 0, 0);
  1769. usb2Fdo = USBPORT_FindUSB2Controller(FdoDeviceObject);
  1770. // may get NULL if no 2.0 controller registered
  1771. if (usb2Fdo) {
  1772. PDEVICE_EXTENSION usb2DevExt;
  1773. ULONG usb2Nports;
  1774. LOGENTRY(NULL, FdoDeviceObject, LOG_PNP, 'p120', usb2Fdo,
  1775. 0, 0);
  1776. GET_DEVICE_EXT(usb2DevExt, usb2Fdo);
  1777. ASSERT_FDOEXT(usb2DevExt);
  1778. MPRH_GetRootHubData(usb2DevExt, &hubData);
  1779. usb2Nports = hubData.NumberOfPorts;
  1780. KeWaitForSingleObject(&usb2DevExt->Fdo.CcLock,
  1781. Executive,
  1782. KernelMode,
  1783. FALSE,
  1784. NULL);
  1785. SET_FDO_FLAG(devExt, USBPORT_FDOFLAG_CC_LOCK);
  1786. USBPORT_KdPrint((1, "'**> powering/chirping CC ports\n"));
  1787. for (p=0;
  1788. p< nPorts;
  1789. p++) {
  1790. devExt->Fdo.MiniportDriver->
  1791. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  1792. devExt->Fdo.MiniportDeviceData,
  1793. p+1);
  1794. }
  1795. // some ammount of time must elapse between powering the CC port and
  1796. // attempting to chirp.
  1797. USBPORT_Wait(FdoDeviceObject, 10);
  1798. // chirp all the ports on the USB 2 parent
  1799. for (p=0;
  1800. (usb2DevExt->Fdo.MiniportDriver->HciVersion >= USB_MINIPORT_HCI_VERSION_2)
  1801. &&
  1802. p < usb2Nports;
  1803. p++) {
  1804. usb2DevExt->Fdo.MiniportDriver->
  1805. RegistrationPacket.MINIPORT_Chirp_RH_Port(
  1806. usb2DevExt->Fdo.MiniportDeviceData,
  1807. p+1);
  1808. }
  1809. USBPORT_KdPrint((1, "'**< powering/chirping CC ports\n"));
  1810. CLEAR_FDO_FLAG(devExt, USBPORT_FDOFLAG_CC_LOCK);
  1811. KeReleaseSemaphore(&usb2DevExt->Fdo.CcLock,
  1812. LOW_REALTIME_PRIORITY,
  1813. 1,
  1814. FALSE);
  1815. } else {
  1816. USBPORT_KdPrint((1, "'** powering CC ports\n"));
  1817. // no CC, just power them
  1818. for (p=0;
  1819. p< nPorts;
  1820. p++) {
  1821. devExt->Fdo.MiniportDriver->
  1822. RegistrationPacket.MINIPORT_RH_SetFeaturePortPower(
  1823. devExt->Fdo.MiniportDeviceData,
  1824. p+1);
  1825. }
  1826. }
  1827. return USBMP_STATUS_SUCCESS;
  1828. }