hub.c 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. hub.c
  5. Abstract:
  6. This module implements support for interacting with standard USB Hubs.
  7. Author:
  8. Evan Green 19-Jan-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/driver.h>
  16. #include "usbcore.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. //
  21. // ------------------------------------------------------ Data Type Definitions
  22. //
  23. /*++
  24. Structure Description:
  25. This structure stores internal USB hub context.
  26. Members:
  27. DeviceHandle - Stores a pointer to the USB device handle.
  28. IoBuffer - Stores a pointer to the I/O buffer used to back the hub data
  29. transfers.
  30. ControlTransfer - Stores a pointer to the control transfer used to
  31. communicate with the hub.
  32. ControlTransferLock - Stores a pointer to the lock that synchronizes
  33. access to the control transfer.
  34. InterruptTransfer - Stores a pointer to the interrupt transfer used for
  35. hub status notifications.
  36. PortCount - Stores the number of downstream ports in the hub.
  37. PowerDelayIn2ms - Stores the time, in 2ms intervals, from the time the
  38. power-on sequence begins on a port until the power is good on that
  39. port. Software uses this value to determine how long to wait before
  40. accessing a powered-on port.
  41. HasIndicators - Stores a boolean indicating whether or not the hub has
  42. port indicator LEDs.
  43. HubStatus - Stores the status of each of the hub's ports.
  44. Interface - Stores a pointer to the hub interface description.
  45. InterruptWorkItem - Stores a pointer to the work item queued when the
  46. interrupt transfer completes.
  47. ChangedPorts - Stores the result of the interrupt transfer, the bitfield
  48. of changed ports.
  49. --*/
  50. struct _USB_HUB {
  51. HANDLE DeviceHandle;
  52. PIO_BUFFER IoBuffer;
  53. PUSB_TRANSFER ControlTransfer;
  54. PQUEUED_LOCK ControlTransferLock;
  55. PUSB_TRANSFER InterruptTransfer;
  56. UCHAR PortCount;
  57. UCHAR PowerUpDelayIn2ms;
  58. BOOL HasIndicators;
  59. USB_HUB_STATUS HubStatus;
  60. PUSB_INTERFACE_DESCRIPTION Interface;
  61. PWORK_ITEM InterruptWorkItem;
  62. USHORT ChangedPorts;
  63. };
  64. //
  65. // ----------------------------------------------- Internal Function Prototypes
  66. //
  67. KSTATUS
  68. UsbpGetHubStatus (
  69. PUSB_HUB Hub,
  70. BOOL ForceRefresh
  71. );
  72. KSTATUS
  73. UsbpGetRootHubStatus (
  74. PUSB_HUB RootHub
  75. );
  76. KSTATUS
  77. UsbpSetHubStatus (
  78. PUSB_HUB Hub
  79. );
  80. VOID
  81. UsbpHubUpdatePortStatus (
  82. PUSB_HUB Hub,
  83. ULONG PortIndex,
  84. ULONG HardwareStatus
  85. );
  86. KSTATUS
  87. UsbpResetHub (
  88. PUSB_HUB Hub
  89. );
  90. KSTATUS
  91. UsbpReadHubDescriptor (
  92. PUSB_HUB Hub
  93. );
  94. KSTATUS
  95. UsbpHubSendControlTransfer (
  96. PUSB_HUB Hub,
  97. PULONG LengthTransferred
  98. );
  99. KSTATUS
  100. UsbpHubGetHubStatus (
  101. PUSB_HUB Hub,
  102. PULONG HubStatus
  103. );
  104. KSTATUS
  105. UsbpHubGetPortStatus (
  106. PUSB_HUB Hub,
  107. ULONG PortNumber,
  108. PULONG PortStatus
  109. );
  110. KSTATUS
  111. UsbpHubSetOrClearFeature (
  112. PUSB_HUB Hub,
  113. BOOL SetFeature,
  114. USHORT Feature,
  115. USHORT Port
  116. );
  117. VOID
  118. UsbpHubInterruptTransferCompletion (
  119. PUSB_TRANSFER Transfer
  120. );
  121. VOID
  122. UsbpHubInterruptTransferCompletionWorker (
  123. PVOID Parameter
  124. );
  125. KSTATUS
  126. UsbpHubClearPortChangeBits (
  127. PUSB_HUB Hub,
  128. ULONG PortNumber,
  129. ULONG PortStatus
  130. );
  131. VOID
  132. UsbpHubAddDevice (
  133. PUSB_HUB Hub,
  134. ULONG PortIndex
  135. );
  136. KSTATUS
  137. UsbpHubEnablePortPower (
  138. PUSB_HUB Hub,
  139. ULONG PortIndex
  140. );
  141. //
  142. // -------------------------------------------------------------------- Globals
  143. //
  144. //
  145. // ------------------------------------------------------------------ Functions
  146. //
  147. USB_API
  148. KSTATUS
  149. UsbCreateHub (
  150. HANDLE DeviceHandle,
  151. PUSB_HUB *Hub
  152. )
  153. /*++
  154. Routine Description:
  155. This routine creates a new USB hub device. This routine must be called at
  156. low level.
  157. Arguments:
  158. DeviceHandle - Supplies the open device handle to the hub.
  159. Hub - Supplies a pointer where a pointer to the hub context will be
  160. returned.
  161. Return Value:
  162. Status code.
  163. --*/
  164. {
  165. ULONG AllocationSize;
  166. UINTN BufferAlignment;
  167. UINTN BufferSize;
  168. PUSB_DEVICE Device;
  169. PVOID HubStatus;
  170. ULONG IoBufferFlags;
  171. ULONG MaxControlTransferSize;
  172. ULONG MaxInterruptSize;
  173. PUSB_HUB NewHub;
  174. KSTATUS Status;
  175. ASSERT(Hub != NULL);
  176. ASSERT(KeGetRunLevel() == RunLevelLow);
  177. HubStatus = NULL;
  178. NewHub = MmAllocatePagedPool(sizeof(USB_HUB), USB_CORE_ALLOCATION_TAG);
  179. if (NewHub == NULL) {
  180. Status = STATUS_INSUFFICIENT_RESOURCES;
  181. goto CreateHubEnd;
  182. }
  183. RtlZeroMemory(NewHub, sizeof(USB_HUB));
  184. NewHub->DeviceHandle = DeviceHandle;
  185. //
  186. // Create an I/O buffer for both control and interrupt transfers. Since the
  187. // I/O buffer allocation rounds up to a page anyway, this allocation
  188. // accounts for the maximum possible number of ports on a hub: 127.
  189. //
  190. BufferAlignment = MmGetIoBufferAlignment();
  191. MaxControlTransferSize = ALIGN_RANGE_UP(USB_HUB_MAX_CONTROL_TRANSFER_SIZE,
  192. BufferAlignment);
  193. MaxInterruptSize = ALIGN_RANGE_UP(USB_HUB_MAX_INTERRUPT_SIZE,
  194. BufferAlignment);
  195. BufferSize = MaxControlTransferSize + MaxInterruptSize;
  196. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  197. NewHub->IoBuffer = MmAllocateNonPagedIoBuffer(0,
  198. MAX_ULONG,
  199. BufferAlignment,
  200. BufferSize,
  201. IoBufferFlags);
  202. if (NewHub->IoBuffer == NULL) {
  203. Status = STATUS_INSUFFICIENT_RESOURCES;
  204. goto CreateHubEnd;
  205. }
  206. ASSERT(NewHub->IoBuffer->FragmentCount == 1);
  207. //
  208. // Create a control transfer.
  209. //
  210. NewHub->ControlTransfer = UsbAllocateTransfer(
  211. NewHub->DeviceHandle,
  212. 0,
  213. USB_HUB_MAX_CONTROL_TRANSFER_SIZE,
  214. 0);
  215. if (NewHub->ControlTransfer == NULL) {
  216. Status = STATUS_INSUFFICIENT_RESOURCES;
  217. goto CreateHubEnd;
  218. }
  219. NewHub->ControlTransfer->Buffer =
  220. NewHub->IoBuffer->Fragment[0].VirtualAddress;
  221. NewHub->ControlTransfer->BufferPhysicalAddress =
  222. NewHub->IoBuffer->Fragment[0].PhysicalAddress;
  223. NewHub->ControlTransfer->BufferActualLength = MaxControlTransferSize;
  224. NewHub->ControlTransferLock = KeCreateQueuedLock();
  225. if (NewHub->ControlTransferLock == NULL) {
  226. Status = STATUS_INSUFFICIENT_RESOURCES;
  227. goto CreateHubEnd;
  228. }
  229. //
  230. // Create the interrupt work item.
  231. //
  232. NewHub->InterruptWorkItem = KeCreateWorkItem(
  233. UsbCoreWorkQueue,
  234. WorkPriorityNormal,
  235. UsbpHubInterruptTransferCompletionWorker,
  236. NewHub,
  237. USB_CORE_ALLOCATION_TAG);
  238. if (NewHub->InterruptWorkItem == NULL) {
  239. Status = STATUS_INSUFFICIENT_RESOURCES;
  240. goto CreateHubEnd;
  241. }
  242. //
  243. // Get the number of ports for this hub and finish creating the hub's port
  244. // count dependent structures.
  245. //
  246. Device = (PUSB_DEVICE)DeviceHandle;
  247. if (Device->Type == UsbDeviceTypeRootHub) {
  248. NewHub->PortCount = Device->Controller->Device.RootHubPortCount;
  249. } else {
  250. Status = UsbpReadHubDescriptor(NewHub);
  251. if (!KSUCCESS(Status)) {
  252. goto CreateHubEnd;
  253. }
  254. }
  255. //
  256. // Allocate space for the hub status arrays.
  257. //
  258. AllocationSize = (sizeof(USB_PORT_STATUS) * NewHub->PortCount) +
  259. (sizeof(USB_DEVICE_SPEED) * NewHub->PortCount);
  260. HubStatus = MmAllocatePagedPool(AllocationSize, USB_CORE_ALLOCATION_TAG);
  261. if (HubStatus == NULL) {
  262. Status = STATUS_INSUFFICIENT_RESOURCES;
  263. goto CreateHubEnd;
  264. }
  265. RtlZeroMemory(HubStatus, AllocationSize);
  266. NewHub->HubStatus.PortStatus = HubStatus;
  267. HubStatus += (sizeof(USB_PORT_STATUS) * NewHub->PortCount);
  268. NewHub->HubStatus.PortDeviceSpeed = HubStatus;
  269. //
  270. // If this is the root hub, link it up with the host controller.
  271. //
  272. if (Device->Type == UsbDeviceTypeRootHub) {
  273. Device->Controller->RootHub = NewHub;
  274. }
  275. Status = STATUS_SUCCESS;
  276. CreateHubEnd:
  277. if (!KSUCCESS(Status)) {
  278. if (NewHub != NULL) {
  279. if (NewHub->InterruptWorkItem != NULL) {
  280. KeDestroyWorkItem(NewHub->InterruptWorkItem);
  281. }
  282. if (NewHub->ControlTransferLock != NULL) {
  283. KeDestroyQueuedLock(NewHub->ControlTransferLock);
  284. }
  285. if (NewHub->ControlTransfer != NULL) {
  286. UsbDestroyTransfer(NewHub->ControlTransfer);
  287. }
  288. if (NewHub->IoBuffer != NULL) {
  289. MmFreeIoBuffer(NewHub->IoBuffer);
  290. }
  291. if (HubStatus != NULL) {
  292. MmFreePagedPool(HubStatus);
  293. }
  294. MmFreePagedPool(NewHub);
  295. NewHub = NULL;
  296. }
  297. }
  298. *Hub = NewHub;
  299. return Status;
  300. }
  301. USB_API
  302. VOID
  303. UsbDestroyHub (
  304. PUSB_HUB Hub
  305. )
  306. /*++
  307. Routine Description:
  308. This routine destroys a USB hub context. This should only be called once
  309. all of the hub's transfers have completed.
  310. Arguments:
  311. Hub - Supplies a pointer to the hub to tear down.
  312. Return Value:
  313. None.
  314. --*/
  315. {
  316. PUSB_DEVICE Child;
  317. PUSB_DEVICE HubDevice;
  318. ASSERT(Hub != NULL);
  319. ASSERT(KeGetRunLevel() == RunLevelLow);
  320. //
  321. // Get the hub's USB device. It should be disconnected.
  322. //
  323. HubDevice = (PUSB_DEVICE)Hub->DeviceHandle;
  324. ASSERT(HubDevice->Connected == FALSE);
  325. //
  326. // Clean up the hub's children, who should all be disconnected. The list
  327. // will be empty after this.
  328. //
  329. KeAcquireQueuedLock(HubDevice->ChildLock);
  330. while (LIST_EMPTY(&(HubDevice->ChildList)) == FALSE) {
  331. Child = (PUSB_DEVICE)LIST_VALUE(HubDevice->ChildList.Next,
  332. USB_DEVICE,
  333. ListEntry);
  334. //
  335. // Assert that the child is disconnected or that there is only one
  336. // reference on the child. It is not enough to assert that it is
  337. // disconnected, because devices whose functional driver never came
  338. // online will not get the remove IRP to disconnect themselves.
  339. // They may still be "connected". Devices that were connected and are
  340. // now disconnected may have more than 1 reference if something in the
  341. // system still holds a handle to the device.
  342. //
  343. ASSERT((Child->Connected == FALSE) || (Child->ReferenceCount == 1));
  344. UsbpRemoveDevice(Child);
  345. }
  346. KeReleaseQueuedLock(HubDevice->ChildLock);
  347. //
  348. // The hub's interrupt transfer callback queues a work item, which then
  349. // attempts to re-submit the transfer. Re-submission will fail at this
  350. // point, so flush the work item, destroy it, and then the transfer can
  351. // be safely destroyed. The work item is guaranteed to have been queued
  352. // because the transfer is currently in the inactive state, not in the
  353. // callback state.
  354. //
  355. // The destroy routine attempts to cancel the work item and then flush if
  356. // the cancel was too late.
  357. //
  358. KeDestroyWorkItem(Hub->InterruptWorkItem);
  359. //
  360. // There is no guarantee the interrupt transfer was allocated in cases
  361. // where the hub never got the start IRP. Only release what is necessary.
  362. //
  363. if (Hub->InterruptTransfer != NULL) {
  364. UsbDestroyTransfer(Hub->InterruptTransfer);
  365. }
  366. //
  367. // Release the interface used for the transfer, if necessary.
  368. //
  369. if (Hub->Interface != NULL) {
  370. UsbReleaseInterface(Hub->DeviceHandle,
  371. Hub->Interface->Descriptor.InterfaceNumber);
  372. }
  373. //
  374. // The control transfer is only used during start, query children, and
  375. // interrupt callback operations. Given that the interrupt transfer has
  376. // been destroyed, it is safe to destroy the control transfer and lock.
  377. //
  378. UsbDestroyTransfer(Hub->ControlTransfer);
  379. KeDestroyQueuedLock(Hub->ControlTransferLock);
  380. //
  381. // Destroy remaining data and the hub itself.
  382. //
  383. MmFreeIoBuffer(Hub->IoBuffer);
  384. MmFreePagedPool(Hub->HubStatus.PortStatus);
  385. MmFreePagedPool(Hub);
  386. return;
  387. }
  388. USB_API
  389. KSTATUS
  390. UsbStartHub (
  391. PUSB_HUB Hub
  392. )
  393. /*++
  394. Routine Description:
  395. This routine starts a USB hub.
  396. Arguments:
  397. Hub - Supplies a pointer to the hub to start.
  398. Return Value:
  399. None.
  400. --*/
  401. {
  402. PUSB_DEVICE Device;
  403. BOOL LockHeld;
  404. KSTATUS Status;
  405. LockHeld = FALSE;
  406. Device = (PUSB_DEVICE)(Hub->DeviceHandle);
  407. //
  408. // If this is not the root hub, reset the hub. This consists of turning the
  409. // power on for each port, collecting the hub status, and starting the
  410. // change notification interrupts.
  411. //
  412. if (Device->Type != UsbDeviceTypeRootHub) {
  413. ASSERT(Device->Type == UsbDeviceTypeHub);
  414. Status = UsbpResetHub(Hub);
  415. if (!KSUCCESS(Status)) {
  416. goto StartHubEnd;
  417. }
  418. //
  419. // Otherwise, just read the port status information out of the hub.
  420. // Synchronize this with port status change notifications that may also
  421. // modify the hub's software status.
  422. //
  423. } else {
  424. KeAcquireQueuedLock(Device->ChildLock);
  425. LockHeld = TRUE;
  426. Status = UsbpGetHubStatus(Hub, TRUE);
  427. if (!KSUCCESS(Status)) {
  428. goto StartHubEnd;
  429. }
  430. }
  431. StartHubEnd:
  432. if (LockHeld != FALSE) {
  433. KeReleaseQueuedLock(Device->ChildLock);
  434. }
  435. return Status;
  436. }
  437. USB_API
  438. KSTATUS
  439. UsbHubQueryChildren (
  440. PIRP Irp,
  441. PUSB_HUB Hub
  442. )
  443. /*++
  444. Routine Description:
  445. This routine responds to the Query Children IRP for a USB Hub. This routine
  446. must be called at low level.
  447. Arguments:
  448. Irp - Supplies a pointer to the Query Children IRP.
  449. Hub - Supplies a pointer to the hub to query.
  450. Return Value:
  451. Status code.
  452. --*/
  453. {
  454. ULONG AllocationSize;
  455. PUSB_DEVICE Child;
  456. ULONG ChildCount;
  457. ULONG ChildIndex;
  458. PDEVICE *Children;
  459. PLIST_ENTRY CurrentEntry;
  460. PUSB_DEVICE Device;
  461. BOOL DeviceLockHeld;
  462. UCHAR PortIndex;
  463. PUSB_PORT_STATUS PortStatus;
  464. KSTATUS Status;
  465. ASSERT(KeGetRunLevel() == RunLevelLow);
  466. Children = NULL;
  467. Device = (PUSB_DEVICE)(Hub->DeviceHandle);
  468. DeviceLockHeld = FALSE;
  469. //
  470. // Loop over all possible ports in the hub.
  471. //
  472. KeAcquireQueuedLock(Device->ChildLock);
  473. DeviceLockHeld = TRUE;
  474. ASSERT(Hub->PortCount != 0);
  475. ASSERT(Hub->HubStatus.PortStatus != NULL);
  476. for (PortIndex = 0; PortIndex < Hub->PortCount; PortIndex += 1) {
  477. //
  478. // Loop over all children of this device to find one corresponding to
  479. // this port.
  480. //
  481. CurrentEntry = Device->ChildList.Next;
  482. while (CurrentEntry != &(Device->ChildList)) {
  483. Child = LIST_VALUE(CurrentEntry, USB_DEVICE, ListEntry);
  484. if (Child->PortNumber == PortIndex + 1) {
  485. break;
  486. }
  487. CurrentEntry = CurrentEntry->Next;
  488. }
  489. if (CurrentEntry == &(Device->ChildList)) {
  490. Child = NULL;
  491. }
  492. //
  493. // Handle cases where the port status changed.
  494. //
  495. PortStatus = &(Hub->HubStatus.PortStatus[PortIndex]);
  496. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_CONNECTED) != 0) {
  497. //
  498. // If there had previously been a child at the current port, then
  499. // remove it from the list. The port is either empty or the child
  500. // was replaced. It will be reported as missing when this call
  501. // completes, triggering the removal process.
  502. //
  503. if (Child != NULL) {
  504. UsbpRemoveDevice(Child);
  505. }
  506. //
  507. // If there is a device present, then it's new. Create the new
  508. // device. Ignore failures here to allow other devices to be
  509. // enumerated.
  510. //
  511. if ((PortStatus->Status & USB_PORT_STATUS_CONNECTED) != 0) {
  512. UsbpHubAddDevice(Hub, PortIndex);
  513. }
  514. //
  515. // Clear the changed status in the port.
  516. //
  517. PortStatus->Change &= ~USB_PORT_STATUS_CHANGE_CONNECTED;
  518. }
  519. }
  520. //
  521. // Loop once to determine how many children there are. A child should only
  522. // not have an OS device if it is the debug device.
  523. //
  524. ChildCount = 0;
  525. CurrentEntry = Device->ChildList.Next;
  526. while (CurrentEntry != &(Device->ChildList)) {
  527. Child = LIST_VALUE(CurrentEntry, USB_DEVICE, ListEntry);
  528. ASSERT((Child->Device != NULL) || (Child->DebugDevice != FALSE));
  529. if (Child->Device != NULL) {
  530. ChildCount += 1;
  531. }
  532. CurrentEntry = CurrentEntry->Next;
  533. }
  534. if (ChildCount == 0) {
  535. Status = STATUS_SUCCESS;
  536. goto HubEnumerateChildrenEnd;
  537. }
  538. //
  539. // Create the array of OS device objects to report the children.
  540. //
  541. AllocationSize = sizeof(PDEVICE) * ChildCount;
  542. Children = MmAllocatePagedPool(AllocationSize, USB_CORE_ALLOCATION_TAG);
  543. if (Children == NULL) {
  544. Status = STATUS_INSUFFICIENT_RESOURCES;
  545. goto HubEnumerateChildrenEnd;
  546. }
  547. RtlZeroMemory(Children, AllocationSize);
  548. ChildIndex = 0;
  549. CurrentEntry = Device->ChildList.Next;
  550. while (CurrentEntry != &(Device->ChildList)) {
  551. Child = LIST_VALUE(CurrentEntry, USB_DEVICE, ListEntry);
  552. CurrentEntry = CurrentEntry->Next;
  553. if (Child->Device != NULL) {
  554. Children[ChildIndex] = Child->Device;
  555. ChildIndex += 1;
  556. }
  557. }
  558. ASSERT(ChildIndex == ChildCount);
  559. //
  560. // Merge this child array with the children already in the IRP. This
  561. // routine allocates a new array, so release the array allocated here
  562. // upon the completion of query children.
  563. //
  564. Status = IoMergeChildArrays(Irp,
  565. Children,
  566. ChildCount,
  567. USB_CORE_ALLOCATION_TAG);
  568. if (!KSUCCESS(Status)) {
  569. goto HubEnumerateChildrenEnd;
  570. }
  571. Status = STATUS_SUCCESS;
  572. HubEnumerateChildrenEnd:
  573. if (Children != NULL) {
  574. MmFreePagedPool(Children);
  575. }
  576. if (DeviceLockHeld != FALSE) {
  577. KeReleaseQueuedLock(Device->ChildLock);
  578. }
  579. return Status;
  580. }
  581. VOID
  582. UsbpNotifyRootHubStatusChange (
  583. PUSB_HUB RootHub
  584. )
  585. /*++
  586. Routine Description:
  587. This routine handles notifications from the host controller indicating that
  588. a port on the root hub has changed. It queries the port status for the hub
  589. and notifies the system if something is different.
  590. Arguments:
  591. RootHub - Supplies a pointer to the USB root hub.
  592. Return Value:
  593. None.
  594. --*/
  595. {
  596. BOOL LockHeld;
  597. BOOL PortChanged;
  598. ULONG PortCount;
  599. ULONG PortIndex;
  600. PUSB_PORT_STATUS PortStatus;
  601. PUSB_DEVICE RootDevice;
  602. KSTATUS Status;
  603. ASSERT(RootHub != NULL);
  604. ASSERT(RootHub->HubStatus.PortStatus != NULL);
  605. //
  606. // Acquire the device's child lock to synchronize with other accesses to
  607. // the ports.
  608. //
  609. RootDevice = (PUSB_DEVICE)RootHub->DeviceHandle;
  610. KeAcquireQueuedLock(RootDevice->ChildLock);
  611. LockHeld = TRUE;
  612. //
  613. // Get the status for the root hub.
  614. //
  615. Status = UsbpGetRootHubStatus(RootHub);
  616. if (!KSUCCESS(Status)) {
  617. goto NotifyRootHubStatusChange;
  618. }
  619. //
  620. // Search through the ports for change notifications.
  621. //
  622. PortChanged = FALSE;
  623. PortCount = RootHub->PortCount;
  624. for (PortIndex = 0; PortIndex < PortCount; PortIndex += 1) {
  625. PortStatus = &(RootHub->HubStatus.PortStatus[PortIndex]);
  626. //
  627. // Run through the over-current reset sequence as defined in section
  628. // 11.12.5 of the USB 2.0 Specification.
  629. //
  630. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_OVER_CURRENT) != 0) {
  631. //
  632. // Wait until the over current bit is clear.
  633. //
  634. while ((PortStatus->Status & USB_PORT_STATUS_OVER_CURRENT) != 0) {
  635. Status = UsbpGetRootHubStatus(RootHub);
  636. if (!KSUCCESS(Status)) {
  637. goto NotifyRootHubStatusChange;
  638. }
  639. }
  640. //
  641. // Now wipe the port status and reset the port. There is no
  642. // mechanism to power on a root port, so settle for a reset. The
  643. // USB specification is not clear on what to do for the root hub's
  644. // ports.
  645. //
  646. RtlZeroMemory(PortStatus, sizeof(USB_PORT_STATUS));
  647. RootHub->HubStatus.PortDeviceSpeed[PortIndex] =
  648. UsbDeviceSpeedInvalid;
  649. Status = UsbpResetHubPort(RootHub, PortIndex);
  650. if (!KSUCCESS(Status)) {
  651. continue;
  652. }
  653. //
  654. // Collect the status one more time after the power on. If there is
  655. // something behind the port then the connection changed bit should
  656. // get set.
  657. //
  658. Status = UsbpGetRootHubStatus(RootHub);
  659. if (!KSUCCESS(Status)) {
  660. goto NotifyRootHubStatusChange;
  661. }
  662. }
  663. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_CONNECTED) != 0) {
  664. PortChanged = TRUE;
  665. break;
  666. }
  667. }
  668. KeReleaseQueuedLock(RootDevice->ChildLock);
  669. LockHeld = FALSE;
  670. //
  671. // A change was found. Notify the system.
  672. //
  673. if (PortChanged != FALSE) {
  674. IoNotifyDeviceTopologyChange(RootDevice->Device);
  675. }
  676. NotifyRootHubStatusChange:
  677. if (LockHeld != FALSE) {
  678. KeReleaseQueuedLock(RootDevice->ChildLock);
  679. }
  680. return;
  681. }
  682. KSTATUS
  683. UsbpResetHubPort (
  684. PUSB_HUB Hub,
  685. UCHAR PortIndex
  686. )
  687. /*++
  688. Routine Description:
  689. This routine resets the device behind the given port. The controller lock
  690. must be held.
  691. Arguments:
  692. Hub - Supplies a pointer to the context of the hub whose port is to be
  693. reset.
  694. PortIndex - Supplies the zero-based port index on the hub to reset.
  695. Return Value:
  696. Status code.
  697. --*/
  698. {
  699. PUSB_DEVICE HubDevice;
  700. PUSB_PORT_STATUS PortStatus;
  701. KSTATUS Status;
  702. ASSERT(Hub->HubStatus.PortStatus != NULL);
  703. HubDevice = (PUSB_DEVICE)Hub->DeviceHandle;
  704. ASSERT(KeIsQueuedLockHeld(HubDevice->ChildLock) != FALSE);
  705. //
  706. // Reset the port in question.
  707. //
  708. PortStatus = &(Hub->HubStatus.PortStatus[PortIndex]);
  709. PortStatus->Status |= USB_PORT_STATUS_RESET;
  710. PortStatus->Status &= ~USB_PORT_STATUS_ENABLED;
  711. PortStatus->Change |= (USB_PORT_STATUS_CHANGE_RESET |
  712. USB_PORT_STATUS_CHANGE_ENABLED);
  713. Status = UsbpSetHubStatus(Hub);
  714. if (!KSUCCESS(Status)) {
  715. goto ResetHubPortEnd;
  716. }
  717. //
  718. // Stall for 10ms per section 7.1.7.5 of the USB specification (TDRST).
  719. // This is reduced because around 10ms devices start to suspend themselves
  720. // and stop responding to requests.
  721. //
  722. HlBusySpin(5 * MICROSECONDS_PER_MILLISECOND);
  723. //
  724. // Now enable the port.
  725. //
  726. PortStatus->Status &= ~USB_PORT_STATUS_RESET;
  727. PortStatus->Status |= USB_PORT_STATUS_ENABLED;
  728. PortStatus->Change |= (USB_PORT_STATUS_CHANGE_RESET |
  729. USB_PORT_STATUS_CHANGE_ENABLED);
  730. Status = UsbpSetHubStatus(Hub);
  731. if (!KSUCCESS(Status)) {
  732. goto ResetHubPortEnd;
  733. }
  734. //
  735. // Stall for 10ms per section 7.1.7.5 of the USB specification (TRSTRCY).
  736. //
  737. HlBusySpin(25 * MICROSECONDS_PER_MILLISECOND);
  738. //
  739. // Get the status of the port now (actively request it, don't rely on the
  740. // interrupt transfer, as it's blocked waiting to hold the hub lock.
  741. //
  742. Status = UsbpGetHubStatus(Hub, TRUE);
  743. if (!KSUCCESS(Status)) {
  744. goto ResetHubPortEnd;
  745. }
  746. //
  747. // If the reset did not enable the port, then clear the changed bit.
  748. //
  749. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_ENABLED) != 0) {
  750. ASSERT((PortStatus->Status & USB_PORT_STATUS_ENABLED) == 0);
  751. PortStatus->Change &= ~USB_PORT_STATUS_CHANGE_ENABLED;
  752. }
  753. //
  754. // If the device is not present, then exit claiming success. It may have
  755. // been removed during the reset.
  756. //
  757. if ((PortStatus->Status & USB_PORT_STATUS_CONNECTED) == 0) {
  758. Status = STATUS_SUCCESS;
  759. goto ResetHubPortEnd;
  760. }
  761. //
  762. // If the port got disabled, fail the reset. Note that a device might still
  763. // be in the connected state even though it is in the disabled state, so
  764. // this must fail. See Section 11.24.2.7.1 PORT_CONNECTION of the USB 2.0
  765. // Specification.
  766. //
  767. if ((PortStatus->Status & USB_PORT_STATUS_ENABLED) == 0) {
  768. Status = STATUS_NOT_READY;
  769. goto ResetHubPortEnd;
  770. }
  771. ASSERT(Hub->HubStatus.PortDeviceSpeed[PortIndex] != UsbDeviceSpeedInvalid);
  772. //
  773. // Stall again to allow the device time to initialize.
  774. //
  775. HlBusySpin(20 * MICROSECONDS_PER_MILLISECOND);
  776. Status = STATUS_SUCCESS;
  777. ResetHubPortEnd:
  778. if (((UsbDebugFlags & (USB_DEBUG_HUB | USB_DEBUG_ENUMERATION)) != 0) ||
  779. ((!KSUCCESS(Status)) && ((UsbDebugFlags & USB_DEBUG_ERRORS) != 0))) {
  780. RtlDebugPrint("USB: Hub %x reset port %d, status %x.\n",
  781. Hub,
  782. PortIndex,
  783. Status);
  784. }
  785. return Status;
  786. }
  787. //
  788. // --------------------------------------------------------- Internal Functions
  789. //
  790. KSTATUS
  791. UsbpGetHubStatus (
  792. PUSB_HUB Hub,
  793. BOOL ForceRefresh
  794. )
  795. /*++
  796. Routine Description:
  797. This routine gets the current hub and port status out of a USB hub.
  798. Arguments:
  799. Hub - Supplies the pointer to the hub context for this device.
  800. ForceRefresh - Supplies a boolean indicating if all ports should be
  801. re-queried.
  802. Return Value:
  803. Status code.
  804. --*/
  805. {
  806. PUSB_DEVICE Device;
  807. ULONG PortIndex;
  808. ULONG PortStatus;
  809. KSTATUS Status;
  810. Device = (PUSB_DEVICE)(Hub->DeviceHandle);
  811. ASSERT(KeIsQueuedLockHeld(Device->ChildLock) != FALSE);
  812. //
  813. // For root hubs, just farm off the question to the host controller.
  814. //
  815. if (Device->Type == UsbDeviceTypeRootHub) {
  816. Status = UsbpGetRootHubStatus(Hub);
  817. goto GetHubStatusEnd;
  818. }
  819. ASSERT(Device->Type == UsbDeviceTypeHub);
  820. //
  821. // If no refresh is required, just return what's already found. An interrupt
  822. // transfer will automatically update these values when they change.
  823. //
  824. if (ForceRefresh == FALSE) {
  825. Status = STATUS_SUCCESS;
  826. goto GetHubStatusEnd;
  827. }
  828. //
  829. // If a refresh is requested, get each port's status.
  830. //
  831. for (PortIndex = 0; PortIndex < Hub->PortCount; PortIndex += 1) {
  832. Status = UsbpHubGetPortStatus(Hub, PortIndex + 1, &PortStatus);
  833. if (!KSUCCESS(Status)) {
  834. goto GetHubStatusEnd;
  835. }
  836. //
  837. // Set the software bits based on the hardware bits.
  838. //
  839. UsbpHubUpdatePortStatus(Hub, PortIndex, PortStatus);
  840. //
  841. // Clear out any change bits.
  842. //
  843. Status = UsbpHubClearPortChangeBits(Hub, PortIndex + 1, PortStatus);
  844. if (!KSUCCESS(Status)) {
  845. goto GetHubStatusEnd;
  846. }
  847. }
  848. Status = STATUS_SUCCESS;
  849. GetHubStatusEnd:
  850. return Status;
  851. }
  852. KSTATUS
  853. UsbpGetRootHubStatus (
  854. PUSB_HUB RootHub
  855. )
  856. /*++
  857. Routine Description:
  858. This routine gets the root hub's port status out of the USB host controller.
  859. Arguments:
  860. RootHub - Supplies a pointer to hub context for the root USB hub.
  861. Return Value:
  862. Status code.
  863. --*/
  864. {
  865. PUSB_DEVICE Device;
  866. PUSB_HOST_GET_ROOT_HUB_STATUS GetRootHubStatus;
  867. PVOID HostControllerContext;
  868. ULONG PortIndex;
  869. PUSB_PORT_STATUS PortStatus;
  870. KSTATUS Status;
  871. Device = (PUSB_DEVICE)RootHub->DeviceHandle;
  872. ASSERT(Device->Type == UsbDeviceTypeRootHub);
  873. ASSERT(RootHub->HubStatus.PortStatus != NULL);
  874. //
  875. // Farm the question off to the host controller.
  876. //
  877. HostControllerContext = Device->Controller->Device.HostControllerContext;
  878. GetRootHubStatus = Device->Controller->Device.GetRootHubStatus;
  879. Status = GetRootHubStatus(HostControllerContext, &(RootHub->HubStatus));
  880. if (((UsbDebugFlags & USB_DEBUG_HUB) != 0) ||
  881. ((!KSUCCESS(Status)) && ((UsbDebugFlags & USB_DEBUG_ERRORS) != 0))) {
  882. for (PortIndex = 0; PortIndex < RootHub->PortCount; PortIndex += 1) {
  883. PortStatus = &(RootHub->HubStatus.PortStatus[PortIndex]);
  884. RtlDebugPrint(
  885. "USB: Root Hub %x Port %d SoftwareStatus %x, SoftwareChange "
  886. "%x Status %x.\n"
  887. "USB: Speed %d Enabled %d Suspended %d OverCurrent %d "
  888. "Present %d\n",
  889. RootHub,
  890. PortIndex,
  891. PortStatus->Status,
  892. PortStatus->Change,
  893. Status,
  894. RootHub->HubStatus.PortDeviceSpeed[PortIndex],
  895. (PortStatus->Status & USB_PORT_STATUS_ENABLED) != 0,
  896. (PortStatus->Status & USB_PORT_STATUS_SUSPENDED) != 0,
  897. (PortStatus->Status & USB_PORT_STATUS_OVER_CURRENT) != 0,
  898. (PortStatus->Status & USB_PORT_STATUS_CONNECTED) != 0);
  899. }
  900. }
  901. return Status;
  902. }
  903. KSTATUS
  904. UsbpSetHubStatus (
  905. PUSB_HUB Hub
  906. )
  907. /*++
  908. Routine Description:
  909. This routine sets the current hub and port status out of a USB hub.
  910. Arguments:
  911. Hub - Supplies a pointer to the hub context.
  912. Return Value:
  913. Status code.
  914. --*/
  915. {
  916. PUSB_HOST_CONTROLLER Controller;
  917. PUSB_DEVICE Device;
  918. PVOID HostControllerContext;
  919. ULONG PortIndex;
  920. PUSB_PORT_STATUS PortStatus;
  921. BOOL SetFeature;
  922. PUSB_HOST_SET_ROOT_HUB_STATUS SetRootHubStatus;
  923. KSTATUS Status;
  924. ASSERT(Hub->HubStatus.PortStatus != NULL);
  925. Device = (PUSB_DEVICE)(Hub->DeviceHandle);
  926. //
  927. // For root hubs, just farm off the work to the host controller.
  928. //
  929. if (Device->Type == UsbDeviceTypeRootHub) {
  930. Controller = Device->Controller;
  931. HostControllerContext = Controller->Device.HostControllerContext;
  932. SetRootHubStatus = Controller->Device.SetRootHubStatus;
  933. Status = SetRootHubStatus(HostControllerContext, &(Hub->HubStatus));
  934. goto SetHubStatusEnd;
  935. }
  936. ASSERT(Device->Type == UsbDeviceTypeHub);
  937. //
  938. // Loop through each port looking for a change.
  939. //
  940. for (PortIndex = 0; PortIndex < Hub->PortCount; PortIndex += 1) {
  941. //
  942. // Determine what changed between the previous status and the current
  943. // status, and act on those bits.
  944. //
  945. PortStatus = &(Hub->HubStatus.PortStatus[PortIndex]);
  946. //
  947. // If no bits changed, then there is nothing to do really.
  948. //
  949. if (PortStatus->Change == 0) {
  950. continue;
  951. }
  952. //
  953. // Handle port enabled change events.
  954. //
  955. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_ENABLED) != 0) {
  956. //
  957. // Disable the port if it changed and is no longer enabled.
  958. // Enabling a port directly is not allowed. This must be done
  959. // through a reset.
  960. //
  961. if ((PortStatus->Status & USB_PORT_STATUS_ENABLED) == 0) {
  962. Status = UsbpHubSetOrClearFeature(Hub,
  963. FALSE,
  964. USB_HUB_FEATURE_PORT_ENABLE,
  965. PortIndex + 1);
  966. if (!KSUCCESS(Status)) {
  967. goto SetHubStatusEnd;
  968. }
  969. }
  970. //
  971. // Clear the change bit now that it has been handled.
  972. //
  973. PortStatus->Change &= ~USB_PORT_STATUS_CHANGE_ENABLED;
  974. }
  975. //
  976. // Handle port reset changes.
  977. //
  978. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_RESET) != 0) {
  979. //
  980. // If the port is to be reset, then issue a reset. Note that a port
  981. // cannot be "un-reset", the hardware handles this.
  982. //
  983. if ((PortStatus->Status & USB_PORT_STATUS_RESET) != 0) {
  984. Status = UsbpHubSetOrClearFeature(Hub,
  985. TRUE,
  986. USB_HUB_FEATURE_PORT_RESET,
  987. PortIndex + 1);
  988. if (!KSUCCESS(Status)) {
  989. goto SetHubStatusEnd;
  990. }
  991. }
  992. //
  993. // Clear the change bit now that it has been handled.
  994. //
  995. PortStatus->Change &= ~USB_PORT_STATUS_CHANGE_RESET;
  996. }
  997. //
  998. // Handle port suspend changes.
  999. //
  1000. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_SUSPENDED) != 0) {
  1001. if ((PortStatus->Status & USB_PORT_STATUS_SUSPENDED) != 0) {
  1002. SetFeature = TRUE;
  1003. } else {
  1004. SetFeature = FALSE;
  1005. }
  1006. Status = UsbpHubSetOrClearFeature(Hub,
  1007. SetFeature,
  1008. USB_HUB_FEATURE_PORT_SUSPEND,
  1009. PortIndex + 1);
  1010. if (!KSUCCESS(Status)) {
  1011. goto SetHubStatusEnd;
  1012. }
  1013. PortStatus->Change &= ~USB_PORT_STATUS_CHANGE_SUSPENDED;
  1014. }
  1015. }
  1016. Status = STATUS_SUCCESS;
  1017. SetHubStatusEnd:
  1018. return Status;
  1019. }
  1020. VOID
  1021. UsbpHubUpdatePortStatus (
  1022. PUSB_HUB Hub,
  1023. ULONG PortIndex,
  1024. ULONG HardwareStatus
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This routine converts the given hardware port status to software status and
  1029. updates the port status of the given hub at the given index. It saves the
  1030. old port status in the process.
  1031. Arguments:
  1032. Hub - Supplies a pointer to the USB hub device whose port status is to be
  1033. updated.
  1034. PortIndex - Supplies the index of the port whose status is to be updated.
  1035. This is zero-indexed.
  1036. HardwareStatus - Supplies the port's hardware status that needs to be
  1037. converted to software status.
  1038. Return Value:
  1039. None.
  1040. --*/
  1041. {
  1042. USHORT ChangeBits;
  1043. PUSB_PORT_STATUS PortStatus;
  1044. USHORT SoftwareStatus;
  1045. USB_DEVICE_SPEED Speed;
  1046. ASSERT(Hub->HubStatus.PortStatus != NULL);
  1047. Speed = UsbDeviceSpeedInvalid;
  1048. SoftwareStatus = 0;
  1049. if ((HardwareStatus & USB_HUB_PORT_STATUS_DEVICE_CONNECTED) != 0) {
  1050. SoftwareStatus |= USB_PORT_STATUS_CONNECTED;
  1051. if ((HardwareStatus & USB_HUB_PORT_STATUS_HIGH_SPEED) != 0) {
  1052. Speed = UsbDeviceSpeedHigh;
  1053. } else if ((HardwareStatus & USB_HUB_PORT_STATUS_LOW_SPEED) != 0) {
  1054. Speed = UsbDeviceSpeedLow;
  1055. } else {
  1056. Speed = UsbDeviceSpeedFull;
  1057. }
  1058. }
  1059. if ((HardwareStatus & USB_HUB_PORT_STATUS_ENABLED) != 0) {
  1060. SoftwareStatus |= USB_PORT_STATUS_ENABLED;
  1061. }
  1062. if ((HardwareStatus & USB_HUB_PORT_STATUS_SUSPENDED) != 0) {
  1063. SoftwareStatus |= USB_PORT_STATUS_SUSPENDED;
  1064. }
  1065. if ((HardwareStatus & USB_HUB_PORT_STATUS_OVER_CURRENT) != 0) {
  1066. SoftwareStatus |= USB_PORT_STATUS_OVER_CURRENT;
  1067. }
  1068. //
  1069. // If the new status does not match the current status, then mark the
  1070. // appropriate fields as changed and set the new status.
  1071. //
  1072. PortStatus = &(Hub->HubStatus.PortStatus[PortIndex]);
  1073. if (SoftwareStatus != PortStatus->Status) {
  1074. ChangeBits = SoftwareStatus ^ PortStatus->Status;
  1075. //
  1076. // Because the port status bits and changed bits match 1-to-1, just OR
  1077. // in the changed bits.
  1078. //
  1079. PortStatus->Change |= ChangeBits;
  1080. PortStatus->Status = SoftwareStatus;
  1081. }
  1082. if ((UsbDebugFlags & USB_DEBUG_HUB) != 0) {
  1083. RtlDebugPrint(
  1084. "USB: Hub %x Port %d HardwareStatus 0x%x, SoftwareStatus "
  1085. "0x%x, SoftwareChange 0x%x\n"
  1086. "USB: Speed %d Enabled %d Suspended %d OverCurrent %d "
  1087. "Present %d\n",
  1088. Hub,
  1089. PortIndex,
  1090. HardwareStatus,
  1091. PortStatus->Status,
  1092. PortStatus->Change,
  1093. Speed,
  1094. (HardwareStatus & USB_HUB_PORT_STATUS_ENABLED) != 0,
  1095. (HardwareStatus & USB_HUB_PORT_STATUS_SUSPENDED) != 0,
  1096. (HardwareStatus & USB_HUB_PORT_STATUS_OVER_CURRENT) != 0,
  1097. (HardwareStatus & USB_HUB_PORT_STATUS_DEVICE_CONNECTED) != 0);
  1098. }
  1099. //
  1100. // Save the new speed.
  1101. //
  1102. Hub->HubStatus.PortDeviceSpeed[PortIndex] = Speed;
  1103. return;
  1104. }
  1105. KSTATUS
  1106. UsbpResetHub (
  1107. PUSB_HUB Hub
  1108. )
  1109. /*++
  1110. Routine Description:
  1111. This routine resets a USB hub.
  1112. Arguments:
  1113. Hub - Supplies a pointer to the hub to reset.
  1114. Return Value:
  1115. Status code.
  1116. --*/
  1117. {
  1118. ULONG BufferAlignment;
  1119. PUSB_CONFIGURATION_DESCRIPTION Configuration;
  1120. PUSB_DEVICE Device;
  1121. PUSB_ENDPOINT_DESCRIPTION Endpoint;
  1122. UCHAR EndpointNumber;
  1123. PUSB_INTERFACE_DESCRIPTION Interface;
  1124. BOOL LockHeld;
  1125. ULONG MaxControlSize;
  1126. ULONG MaxInterruptSize;
  1127. ULONG PortIndex;
  1128. KSTATUS Status;
  1129. ULONG TransferLength;
  1130. ASSERT(Hub->PortCount != 0);
  1131. Device = (PUSB_DEVICE)Hub->DeviceHandle;
  1132. LockHeld = FALSE;
  1133. //
  1134. // Send the SET_CONFIGURATION request to the port.
  1135. //
  1136. Status = UsbSetConfiguration(Hub->DeviceHandle, 0, TRUE);
  1137. if (!KSUCCESS(Status)) {
  1138. goto ResetHubEnd;
  1139. }
  1140. if (Hub->Interface == NULL) {
  1141. //
  1142. // Get the only configuration.
  1143. //
  1144. Status = UsbGetConfiguration(Hub->DeviceHandle,
  1145. 0,
  1146. TRUE,
  1147. &Configuration);
  1148. if (!KSUCCESS(Status)) {
  1149. goto ResetHubEnd;
  1150. }
  1151. //
  1152. // Find and claim the only interface.
  1153. //
  1154. if (LIST_EMPTY(&(Configuration->InterfaceListHead)) != FALSE) {
  1155. Status = STATUS_INVALID_CONFIGURATION;
  1156. goto ResetHubEnd;
  1157. }
  1158. Interface = LIST_VALUE(Configuration->InterfaceListHead.Next,
  1159. USB_INTERFACE_DESCRIPTION,
  1160. ListEntry);
  1161. Status = UsbClaimInterface(Hub->DeviceHandle,
  1162. Interface->Descriptor.InterfaceNumber);
  1163. if (!KSUCCESS(Status)) {
  1164. goto ResetHubEnd;
  1165. }
  1166. //
  1167. // Get the interrupt endpoint.
  1168. //
  1169. if (LIST_EMPTY(&(Interface->EndpointListHead)) != FALSE) {
  1170. Status = STATUS_INVALID_CONFIGURATION;
  1171. goto ResetHubEnd;
  1172. }
  1173. Endpoint = LIST_VALUE(Interface->EndpointListHead.Next,
  1174. USB_ENDPOINT_DESCRIPTION,
  1175. ListEntry);
  1176. if ((Endpoint->Descriptor.Attributes &
  1177. USB_ENDPOINT_ATTRIBUTES_TYPE_MASK) !=
  1178. USB_ENDPOINT_ATTRIBUTES_TYPE_INTERRUPT) {
  1179. Status = STATUS_INVALID_CONFIGURATION;
  1180. goto ResetHubEnd;
  1181. }
  1182. //
  1183. // Create the interrupt transfer that goes on the status change
  1184. // endpoint.
  1185. //
  1186. BufferAlignment = MmGetIoBufferAlignment();
  1187. ASSERT(POWER_OF_2(BufferAlignment) != FALSE);
  1188. ASSERT(Hub->InterruptTransfer == NULL);
  1189. EndpointNumber = Endpoint->Descriptor.EndpointAddress;
  1190. TransferLength = ALIGN_RANGE_UP(Hub->PortCount + 1, BITS_PER_BYTE) /
  1191. BITS_PER_BYTE;
  1192. Hub->InterruptTransfer = UsbAllocateTransfer(Hub->DeviceHandle,
  1193. EndpointNumber,
  1194. TransferLength,
  1195. 0);
  1196. if (Hub->InterruptTransfer == NULL) {
  1197. Status = STATUS_INSUFFICIENT_RESOURCES;
  1198. goto ResetHubEnd;
  1199. }
  1200. MaxControlSize = ALIGN_RANGE_UP(USB_HUB_MAX_CONTROL_TRANSFER_SIZE,
  1201. BufferAlignment);
  1202. MaxInterruptSize = ALIGN_RANGE_UP(USB_HUB_MAX_INTERRUPT_SIZE,
  1203. BufferAlignment);
  1204. ASSERT(Hub->IoBuffer->Fragment[0].Size >=
  1205. (MaxControlSize + MaxInterruptSize));
  1206. Hub->InterruptTransfer->Buffer =
  1207. Hub->IoBuffer->Fragment[0].VirtualAddress +
  1208. MaxControlSize;
  1209. Hub->InterruptTransfer->BufferPhysicalAddress =
  1210. Hub->IoBuffer->Fragment[0].PhysicalAddress +
  1211. MaxControlSize;
  1212. Hub->InterruptTransfer->BufferActualLength = MaxInterruptSize;
  1213. Hub->InterruptTransfer->Direction = UsbTransferDirectionIn;
  1214. Hub->InterruptTransfer->Length = TransferLength;
  1215. Hub->InterruptTransfer->CallbackRoutine =
  1216. UsbpHubInterruptTransferCompletion;
  1217. Hub->InterruptTransfer->UserData = Hub;
  1218. Hub->Interface = Interface;
  1219. //
  1220. // This is not the first time the hub has been reset.
  1221. //
  1222. } else {
  1223. //
  1224. // Attempt to cancel the interrupt transfer. If the transfer is on the
  1225. // hardware queue, then the cancel will succeed. Otherwise, it is too
  1226. // late to cancel it. Since the interrupt transfer's callback resubmits
  1227. // the transfer, it should get cancelled if this keeps trying.
  1228. //
  1229. while (TRUE) {
  1230. //
  1231. // Cancel the transfer, which tries to cancel and just waits until
  1232. // the transfer is in the inactive state. It returns successfully
  1233. // only if the transfer was actually pulled off the hardware queue.
  1234. // If this fails with status too early, then the transfer is not in
  1235. // the hardware queue and not in the callback. This means that the
  1236. // hub status change worker is queued or running. It is likely the
  1237. // one requesting a reset. Let it go through.
  1238. //
  1239. Status = UsbCancelTransfer(Hub->InterruptTransfer, TRUE);
  1240. if (KSUCCESS(Status) || (Status == STATUS_TOO_EARLY)) {
  1241. break;
  1242. }
  1243. //
  1244. // If the device has been disconnected, the transfer might not go
  1245. // around again and might have missed the cancel. Just exit.
  1246. //
  1247. // N.B. This case is currently not possible since hub reset is only
  1248. // called during the hub start IRP. This needs to be here,
  1249. // however, if the system tried to reset the hub in parallel
  1250. // with a removal IRP.
  1251. //
  1252. if (Device->Connected == FALSE) {
  1253. Status = STATUS_SUCCESS;
  1254. goto ResetHubEnd;
  1255. }
  1256. //
  1257. // Rest a bit to let stuff progress. This may not be fruitful or
  1258. // necessary since the cancel will do some yielding.
  1259. //
  1260. KeYield();
  1261. }
  1262. }
  1263. //
  1264. // Acquire the hub's child lock so no state changes during the reset.
  1265. //
  1266. KeAcquireQueuedLock(Device->ChildLock);
  1267. LockHeld = TRUE;
  1268. //
  1269. // Reset the state for every port. That is, zero out the state ignoring any
  1270. // change bits.
  1271. //
  1272. RtlZeroMemory(Hub->HubStatus.PortStatus,
  1273. (sizeof(USB_PORT_STATUS) * Hub->PortCount));
  1274. RtlZeroMemory(Hub->HubStatus.PortDeviceSpeed,
  1275. (sizeof(USB_DEVICE_SPEED) * Hub->PortCount));
  1276. //
  1277. // Loop through and power on each port.
  1278. //
  1279. for (PortIndex = 0; PortIndex < Hub->PortCount; PortIndex += 1) {
  1280. Status = UsbpHubSetOrClearFeature(Hub,
  1281. TRUE,
  1282. USB_HUB_FEATURE_PORT_POWER,
  1283. PortIndex + 1);
  1284. if (!KSUCCESS(Status)) {
  1285. goto ResetHubEnd;
  1286. }
  1287. }
  1288. //
  1289. // Set the port indicators to auto. The set power feature set them to the
  1290. // off state.
  1291. //
  1292. if (Hub->HasIndicators != FALSE) {
  1293. for (PortIndex = 0; PortIndex < Hub->PortCount; PortIndex += 1) {
  1294. Status = UsbpHubSetOrClearFeature(
  1295. Hub,
  1296. TRUE,
  1297. USB_HUB_FEATURE_PORT_INDICATOR,
  1298. (PortIndex + 1) | USB_HUB_INDICATOR_AUTOMATIC);
  1299. if (!KSUCCESS(Status)) {
  1300. goto ResetHubEnd;
  1301. }
  1302. }
  1303. }
  1304. //
  1305. // Now that the ports have been powered up, delay for the appropriate
  1306. // amount of time before accessing them again.
  1307. //
  1308. KeDelayExecution(FALSE,
  1309. FALSE,
  1310. Hub->PowerUpDelayIn2ms * 2 * MICROSECONDS_PER_MILLISECOND);
  1311. //
  1312. // After waiting for the ports to power up, get the current status.
  1313. //
  1314. Status = UsbpGetHubStatus(Hub, TRUE);
  1315. if (!KSUCCESS(Status)) {
  1316. goto ResetHubEnd;
  1317. }
  1318. KeReleaseQueuedLock(Device->ChildLock);
  1319. LockHeld = FALSE;
  1320. //
  1321. // Submit the interrupt transfer.
  1322. //
  1323. Status = UsbSubmitTransfer(Hub->InterruptTransfer);
  1324. if (!KSUCCESS(Status)) {
  1325. goto ResetHubEnd;
  1326. }
  1327. ResetHubEnd:
  1328. if (LockHeld != FALSE) {
  1329. KeReleaseQueuedLock(Device->ChildLock);
  1330. }
  1331. return Status;
  1332. }
  1333. KSTATUS
  1334. UsbpReadHubDescriptor (
  1335. PUSB_HUB Hub
  1336. )
  1337. /*++
  1338. Routine Description:
  1339. This routine sends a request to read in the hub descriptor, and sets the
  1340. various fields of the hub structure according to the result.
  1341. Arguments:
  1342. Hub - Supplies a pointer to the hub.
  1343. Return Value:
  1344. Status code.
  1345. --*/
  1346. {
  1347. PUSB_HUB_DESCRIPTOR HubDescriptor;
  1348. ULONG LengthTransferred;
  1349. PUSB_SETUP_PACKET Setup;
  1350. KSTATUS Status;
  1351. Setup = (PUSB_SETUP_PACKET)Hub->ControlTransfer->Buffer;
  1352. KeAcquireQueuedLock(Hub->ControlTransferLock);
  1353. Hub->ControlTransfer->Direction = UsbTransferDirectionIn;
  1354. //
  1355. // Send the GET_DESCRIPTOR request.
  1356. //
  1357. Setup->RequestType = USB_SETUP_REQUEST_TO_HOST |
  1358. USB_SETUP_REQUEST_CLASS |
  1359. USB_SETUP_REQUEST_DEVICE_RECIPIENT;
  1360. Setup->Request = USB_DEVICE_REQUEST_GET_DESCRIPTOR;
  1361. Setup->Value = USB_HUB_DESCRIPTOR_TYPE << 8;
  1362. Setup->Index = 0;
  1363. Setup->Length = USB_HUB_DESCRIPTOR_MAX_SIZE;
  1364. Hub->ControlTransfer->Length = sizeof(USB_SETUP_PACKET) +
  1365. USB_HUB_DESCRIPTOR_MAX_SIZE;
  1366. Status = UsbpHubSendControlTransfer(Hub, &LengthTransferred);
  1367. if (!KSUCCESS(Status)) {
  1368. goto ReadHubDescriptorEnd;
  1369. }
  1370. if (LengthTransferred < sizeof(USB_HUB_DESCRIPTOR)) {
  1371. Status = STATUS_NOT_SUPPORTED;
  1372. goto ReadHubDescriptorEnd;
  1373. }
  1374. HubDescriptor = (PUSB_HUB_DESCRIPTOR)(Setup + 1);
  1375. if ((HubDescriptor->DescriptorType != USB_HUB_DESCRIPTOR_TYPE) ||
  1376. (HubDescriptor->Length < sizeof(USB_HUB_DESCRIPTOR))) {
  1377. Status = STATUS_NOT_SUPPORTED;
  1378. goto ReadHubDescriptorEnd;
  1379. }
  1380. Hub->PortCount = HubDescriptor->PortCount;
  1381. Hub->PowerUpDelayIn2ms = HubDescriptor->PowerUpDelayIn2ms;
  1382. if ((HubDescriptor->HubCharacteristics &
  1383. USB_HUB_CHARACTERISTIC_INDICATORS_SUPPORTED) != 0) {
  1384. Hub->HasIndicators = TRUE;
  1385. }
  1386. Status = STATUS_SUCCESS;
  1387. ReadHubDescriptorEnd:
  1388. KeReleaseQueuedLock(Hub->ControlTransferLock);
  1389. return Status;
  1390. }
  1391. KSTATUS
  1392. UsbpHubSendControlTransfer (
  1393. PUSB_HUB Hub,
  1394. PULONG LengthTransferred
  1395. )
  1396. /*++
  1397. Routine Description:
  1398. This routine sends a synchronous control transfer. It assumes that the hub's
  1399. buffer is already all set up and ready to go.
  1400. Arguments:
  1401. Hub - Supplies a pointer to the hub.
  1402. LengthTransferred - Supplies a pointer to the length to transfer.
  1403. Return Value:
  1404. Status code.
  1405. --*/
  1406. {
  1407. KSTATUS Status;
  1408. ULONG TransferCount;
  1409. ASSERT(Hub->ControlTransfer->Direction != UsbTransferDirectionInvalid);
  1410. TransferCount = 0;
  1411. Status = UsbSubmitSynchronousTransfer(Hub->ControlTransfer);
  1412. if (!KSUCCESS(Status)) {
  1413. goto HubSendControlTransferEnd;
  1414. }
  1415. ASSERT(KSUCCESS(Hub->ControlTransfer->Status));
  1416. TransferCount = Hub->ControlTransfer->LengthTransferred -
  1417. sizeof(USB_SETUP_PACKET);
  1418. Hub->ControlTransfer->Direction = UsbTransferDirectionInvalid;
  1419. Status = STATUS_SUCCESS;
  1420. HubSendControlTransferEnd:
  1421. if (LengthTransferred != NULL) {
  1422. *LengthTransferred = TransferCount;
  1423. }
  1424. return Status;
  1425. }
  1426. KSTATUS
  1427. UsbpHubGetHubStatus (
  1428. PUSB_HUB Hub,
  1429. PULONG HubStatus
  1430. )
  1431. /*++
  1432. Routine Description:
  1433. This routine performs a control transfer to get the current status of the
  1434. given USB hub.
  1435. Arguments:
  1436. Hub - Supplies a pointer to the hub to query.
  1437. HubStatus - Supplies a pointer where the hub status will be returned upon
  1438. success.
  1439. Return Value:
  1440. Status code.
  1441. --*/
  1442. {
  1443. ULONG LengthTransferred;
  1444. PUSB_SETUP_PACKET Setup;
  1445. KSTATUS Status;
  1446. Setup = (PUSB_SETUP_PACKET)Hub->ControlTransfer->Buffer;
  1447. KeAcquireQueuedLock(Hub->ControlTransferLock);
  1448. Setup->RequestType = USB_SETUP_REQUEST_TO_HOST |
  1449. USB_SETUP_REQUEST_CLASS |
  1450. USB_SETUP_REQUEST_DEVICE_RECIPIENT;
  1451. Setup->Request = USB_DEVICE_REQUEST_GET_STATUS;
  1452. Setup->Value = 0;
  1453. Setup->Index = 0;
  1454. Setup->Length = sizeof(ULONG);
  1455. Hub->ControlTransfer->Direction = UsbTransferDirectionIn;
  1456. Hub->ControlTransfer->Length = sizeof(USB_SETUP_PACKET) + sizeof(ULONG);
  1457. Status = UsbpHubSendControlTransfer(Hub, &LengthTransferred);
  1458. if (!KSUCCESS(Status)) {
  1459. goto HubGetHubStatusEnd;
  1460. }
  1461. if (LengthTransferred != sizeof(ULONG)) {
  1462. Status = STATUS_DATA_LENGTH_MISMATCH;
  1463. goto HubGetHubStatusEnd;
  1464. }
  1465. HubGetHubStatusEnd:
  1466. KeReleaseQueuedLock(Hub->ControlTransferLock);
  1467. if (!KSUCCESS(Status)) {
  1468. *HubStatus = 0;
  1469. } else {
  1470. *HubStatus = *((PULONG)(Setup + 1));
  1471. }
  1472. return Status;
  1473. }
  1474. KSTATUS
  1475. UsbpHubGetPortStatus (
  1476. PUSB_HUB Hub,
  1477. ULONG PortNumber,
  1478. PULONG PortStatus
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. This routine performs a control transfer to get the current status of the
  1483. given USB hub port.
  1484. Arguments:
  1485. Hub - Supplies a pointer to the hub to query.
  1486. PortNumber - Supplies the one-indexed port number to query.
  1487. PortStatus - Supplies a pointer where the port status will be returned upon
  1488. success.
  1489. Return Value:
  1490. Status code.
  1491. --*/
  1492. {
  1493. ULONG LengthTransferred;
  1494. PUSB_SETUP_PACKET Setup;
  1495. KSTATUS Status;
  1496. ASSERT(PortNumber != 0);
  1497. ASSERT(PortNumber <= Hub->PortCount);
  1498. Setup = (PUSB_SETUP_PACKET)Hub->ControlTransfer->Buffer;
  1499. KeAcquireQueuedLock(Hub->ControlTransferLock);
  1500. Setup->RequestType = USB_SETUP_REQUEST_TO_HOST |
  1501. USB_SETUP_REQUEST_CLASS |
  1502. USB_SETUP_REQUEST_OTHER_RECIPIENT;
  1503. Setup->Request = USB_DEVICE_REQUEST_GET_STATUS;
  1504. Setup->Value = 0;
  1505. Setup->Index = PortNumber;
  1506. Setup->Length = sizeof(ULONG);
  1507. Hub->ControlTransfer->Direction = UsbTransferDirectionIn;
  1508. Hub->ControlTransfer->Length = sizeof(USB_SETUP_PACKET) + sizeof(ULONG);
  1509. Status = UsbpHubSendControlTransfer(Hub, &LengthTransferred);
  1510. if (!KSUCCESS(Status)) {
  1511. goto HubGetPortStatusEnd;
  1512. }
  1513. if (LengthTransferred != sizeof(ULONG)) {
  1514. Status = STATUS_DATA_LENGTH_MISMATCH;
  1515. goto HubGetPortStatusEnd;
  1516. }
  1517. HubGetPortStatusEnd:
  1518. KeReleaseQueuedLock(Hub->ControlTransferLock);
  1519. if (!KSUCCESS(Status)) {
  1520. *PortStatus = 0;
  1521. } else {
  1522. *PortStatus = *((PULONG)(Setup + 1));
  1523. }
  1524. return Status;
  1525. }
  1526. KSTATUS
  1527. UsbpHubSetOrClearFeature (
  1528. PUSB_HUB Hub,
  1529. BOOL SetFeature,
  1530. USHORT Feature,
  1531. USHORT Port
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. This routine sends a set feature or clear feature request to the hub.
  1536. Arguments:
  1537. Hub - Supplies a pointer to the hub to send the transfer to.
  1538. SetFeature - Supplies a boolean indicating whether this is a SET_FEATURE
  1539. request (TRUE) or a CLEAR_FEATURE request (FALSE).
  1540. Feature - Supplies the feature selector to set or clear. This is the value
  1541. that goes in the Value field of the setup packet.
  1542. Port - Supplies the port number to set or clear. This is the value that
  1543. goes in the Index field of the setup packet. The first port is port 1.
  1544. Supply 0 to set or clear a hub feature.
  1545. Return Value:
  1546. Status code.
  1547. --*/
  1548. {
  1549. ULONG LengthTransferred;
  1550. PUSB_SETUP_PACKET Setup;
  1551. KSTATUS Status;
  1552. Setup = (PUSB_SETUP_PACKET)Hub->ControlTransfer->Buffer;
  1553. KeAcquireQueuedLock(Hub->ControlTransferLock);
  1554. Setup->RequestType = USB_SETUP_REQUEST_TO_DEVICE |
  1555. USB_SETUP_REQUEST_CLASS;
  1556. //
  1557. // Treat port 0 as the hub itself.
  1558. //
  1559. if (Port == 0) {
  1560. Setup->RequestType |= USB_SETUP_REQUEST_DEVICE_RECIPIENT;
  1561. } else {
  1562. ASSERT(Port <= Hub->PortCount);
  1563. Setup->RequestType |= USB_SETUP_REQUEST_OTHER_RECIPIENT;
  1564. }
  1565. if (SetFeature != FALSE) {
  1566. Setup->Request = USB_DEVICE_REQUEST_SET_FEATURE;
  1567. } else {
  1568. Setup->Request = USB_DEVICE_REQUEST_CLEAR_FEATURE;
  1569. }
  1570. Setup->Value = Feature;
  1571. Setup->Index = Port;
  1572. Setup->Length = 0;
  1573. Hub->ControlTransfer->Direction = UsbTransferDirectionOut;
  1574. Hub->ControlTransfer->Length = sizeof(USB_SETUP_PACKET);
  1575. Status = UsbpHubSendControlTransfer(Hub, &LengthTransferred);
  1576. KeReleaseQueuedLock(Hub->ControlTransferLock);
  1577. return Status;
  1578. }
  1579. VOID
  1580. UsbpHubInterruptTransferCompletion (
  1581. PUSB_TRANSFER Transfer
  1582. )
  1583. /*++
  1584. Routine Description:
  1585. This routine is called when the interrupt transfer on the hub's status
  1586. change endpoint completes.
  1587. Arguments:
  1588. Transfer - Supplies a pointer to the transfer that completed.
  1589. Return Value:
  1590. None.
  1591. --*/
  1592. {
  1593. USHORT ChangedPorts;
  1594. PVOID DeviceToken;
  1595. PUSB_HUB Hub;
  1596. PUSB_TRANSFER_INTERNAL InternalTransfer;
  1597. KSTATUS Status;
  1598. BOOL SubmitTransfer;
  1599. ASSERT(KeGetRunLevel() == RunLevelLow);
  1600. Hub = (PUSB_HUB)Transfer->UserData;
  1601. ASSERT(Transfer == Hub->InterruptTransfer);
  1602. //
  1603. // Handle errors.
  1604. //
  1605. SubmitTransfer = FALSE;
  1606. if (!KSUCCESS(Transfer->Status)) {
  1607. //
  1608. // Exit on cancelled transfers. Something else will restart the
  1609. // transfer if necessary.
  1610. //
  1611. if (Transfer->Status == STATUS_OPERATION_CANCELLED) {
  1612. ASSERT(Transfer->Error == UsbErrorTransferCancelled);
  1613. //
  1614. // On IO errors, do not queue the work item, just re-submit.
  1615. //
  1616. } else if (Transfer->Status == STATUS_DEVICE_IO_ERROR) {
  1617. //
  1618. // If the endpoint halted, try to clear the halted feature bit.
  1619. //
  1620. if (Transfer->Error == UsbErrorTransferStalled) {
  1621. InternalTransfer = (PUSB_TRANSFER_INTERNAL)Transfer;
  1622. Status = UsbClearFeature(Hub->DeviceHandle,
  1623. USB_SETUP_REQUEST_ENDPOINT_RECIPIENT,
  1624. USB_FEATURE_ENDPOINT_HALT,
  1625. InternalTransfer->EndpointNumber);
  1626. if (!KSUCCESS(Status)) {
  1627. if ((UsbDebugFlags &
  1628. (USB_DEBUG_HUB | USB_DEBUG_ERRORS)) != 0) {
  1629. RtlDebugPrint("USB HUB: status change transfer "
  1630. "(0x%08x) on hub 0x%08x stalled. Failed "
  1631. "to clear HALT feature on endpoint with "
  1632. "status 0x%08x.\n",
  1633. Transfer,
  1634. Hub,
  1635. Status);
  1636. }
  1637. DeviceToken = UsbGetDeviceToken(Hub->DeviceHandle);
  1638. IoSetDeviceDriverError(DeviceToken,
  1639. UsbCoreDriver,
  1640. Status,
  1641. USB_CORE_ERROR_ENDPOINT_HALTED);
  1642. goto HubInterruptCompletionEnd;
  1643. }
  1644. }
  1645. SubmitTransfer = TRUE;
  1646. //
  1647. // On all other errors, notify the debugger and try again.
  1648. //
  1649. } else {
  1650. RtlDebugPrint("USB HUB: Unexpected error for hub (0x%08x) status "
  1651. "change transfer (0x%08x): status 0x%08x, error "
  1652. "%d.\n",
  1653. Hub,
  1654. Transfer,
  1655. Transfer->Status,
  1656. Transfer->Error);
  1657. SubmitTransfer = TRUE;
  1658. }
  1659. goto HubInterruptCompletionEnd;
  1660. }
  1661. //
  1662. // If the length transferred is correct, read in the changed port data.
  1663. //
  1664. ChangedPorts = 0;
  1665. if (Transfer->LengthTransferred == Transfer->Length) {
  1666. ChangedPorts = *((PUSHORT)Transfer->Buffer);
  1667. }
  1668. Hub->ChangedPorts = ChangedPorts;
  1669. //
  1670. // If something changed, queue the interrupt work item to get off of the
  1671. // callback routine. While running in the callback, the control transfers
  1672. // kicked off here won't complete.
  1673. //
  1674. if (ChangedPorts != 0) {
  1675. Status = KeQueueWorkItem(Hub->InterruptWorkItem);
  1676. ASSERT(KSUCCESS(Status));
  1677. } else {
  1678. SubmitTransfer = TRUE;
  1679. }
  1680. HubInterruptCompletionEnd:
  1681. if (SubmitTransfer != FALSE) {
  1682. UsbSubmitTransfer(Hub->InterruptTransfer);
  1683. }
  1684. return;
  1685. }
  1686. VOID
  1687. UsbpHubInterruptTransferCompletionWorker (
  1688. PVOID Parameter
  1689. )
  1690. /*++
  1691. Routine Description:
  1692. This routine is a work item routine called when the interrupt transfer on
  1693. the hub's status change endpoint completes.
  1694. Arguments:
  1695. Parameter - Supplies a pointer to the work item parameter, which in this
  1696. case is a pointer to the USB hub.
  1697. Return Value:
  1698. None.
  1699. --*/
  1700. {
  1701. USHORT ChangedPorts;
  1702. BOOL ChildLockHeld;
  1703. PUSB_DEVICE Device;
  1704. ULONG HardwareStatus;
  1705. PUSB_HUB Hub;
  1706. USHORT HubChange;
  1707. ULONG HubStatus;
  1708. BOOL PortChanged;
  1709. ULONG PortIndex;
  1710. PUSB_PORT_STATUS PortStatus;
  1711. KSTATUS Status;
  1712. BOOL SubmitTransfer;
  1713. BOOL TopologyChanged;
  1714. PUSB_DEVICE UsbDevice;
  1715. Hub = (PUSB_HUB)Parameter;
  1716. Device = (PUSB_DEVICE)Hub->DeviceHandle;
  1717. ChangedPorts = Hub->ChangedPorts;
  1718. ChildLockHeld = FALSE;
  1719. SubmitTransfer = TRUE;
  1720. TopologyChanged = FALSE;
  1721. ASSERT(KeGetRunLevel() == RunLevelLow);
  1722. ASSERT(Hub->HubStatus.PortStatus != NULL);
  1723. //
  1724. // Bit zero is the hub's index.
  1725. //
  1726. if ((ChangedPorts & 0x0001) != 0) {
  1727. Status = UsbpHubGetHubStatus(Hub, &HubStatus);
  1728. if (KSUCCESS(Status)) {
  1729. HubChange = HubStatus >> USB_HUB_HUB_STATUS_CHANGE_SHIFT;
  1730. //
  1731. // Just clear the local power status.
  1732. //
  1733. if ((HubChange & USB_HUB_HUB_STATUS_LOCAL_POWER) != 0) {
  1734. UsbpHubSetOrClearFeature(Hub,
  1735. FALSE,
  1736. USB_HUB_FEATURE_C_HUB_LOCAL_POWER,
  1737. 0);
  1738. }
  1739. //
  1740. // Handle over current changes according to section 11.12.5 of the
  1741. // USB 2.0 Specification.
  1742. //
  1743. if ((HubChange & USB_HUB_HUB_STATUS_OVER_CURRENT) != 0) {
  1744. //
  1745. // Wait for the hub's over current status bit to go to zero.
  1746. // Assumably, this is to wait for the hub to power off.
  1747. //
  1748. while ((HubStatus & USB_HUB_HUB_STATUS_OVER_CURRENT) != 0) {
  1749. Status = UsbpHubGetHubStatus(Hub, &HubStatus);
  1750. if (!KSUCCESS(Status)) {
  1751. goto HubInterruptTransferCompletionWorkerEnd;
  1752. }
  1753. }
  1754. //
  1755. // Clear the over current change bit.
  1756. //
  1757. Status = UsbpHubSetOrClearFeature(
  1758. Hub,
  1759. FALSE,
  1760. USB_HUB_FEATURE_C_HUB_OVER_CURRENT,
  1761. 0);
  1762. if (!KSUCCESS(Status)) {
  1763. goto HubInterruptTransferCompletionWorkerEnd;
  1764. }
  1765. //
  1766. // Reset the hub. If this succeeds, then it will have
  1767. // re-submitted the interrupt transfer.
  1768. //
  1769. Status = UsbpResetHub(Hub);
  1770. if (!KSUCCESS(Status)) {
  1771. goto HubInterruptTransferCompletionWorkerEnd;
  1772. }
  1773. SubmitTransfer = FALSE;
  1774. //
  1775. // Mark that the topology changed so that the system
  1776. // re-enumerates all the ports on this hub.
  1777. //
  1778. TopologyChanged = TRUE;
  1779. //
  1780. // Exit without checking the individual port status. The whole
  1781. // hub just got reset.
  1782. //
  1783. goto HubInterruptTransferCompletionWorkerEnd;
  1784. }
  1785. }
  1786. }
  1787. ChangedPorts = ChangedPorts >> 1;
  1788. ASSERT(Hub->PortCount != 0);
  1789. for (PortIndex = 0; PortIndex < Hub->PortCount; PortIndex += 1) {
  1790. //
  1791. // Determine if the port changed. If it didn't, move on.
  1792. //
  1793. PortChanged = FALSE;
  1794. if ((ChangedPorts & 0x1) != 0) {
  1795. PortChanged = TRUE;
  1796. }
  1797. ChangedPorts = ChangedPorts >> 1;
  1798. if (PortChanged == FALSE) {
  1799. continue;
  1800. }
  1801. //
  1802. // If the port changed, read its status. Synchronize this with any
  1803. // other port status changes.
  1804. //
  1805. KeAcquireQueuedLock(Device->ChildLock);
  1806. ChildLockHeld = TRUE;
  1807. Status = UsbpHubGetPortStatus(Hub, PortIndex + 1, &HardwareStatus);
  1808. if (!KSUCCESS(Status)) {
  1809. goto HubInterruptTransferCompletionWorkerEnd;
  1810. }
  1811. //
  1812. // Update the software status stored in the hub.
  1813. //
  1814. UsbpHubUpdatePortStatus(Hub, PortIndex, HardwareStatus);
  1815. if ((UsbDebugFlags & USB_DEBUG_HUB) != 0) {
  1816. RtlDebugPrint("USB: Hub %x Port %d Hardware Status %x.\n",
  1817. Hub,
  1818. PortIndex,
  1819. HardwareStatus);
  1820. }
  1821. //
  1822. // Handle over current change notifications.
  1823. //
  1824. PortStatus = &(Hub->HubStatus.PortStatus[PortIndex]);
  1825. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_OVER_CURRENT) != 0) {
  1826. //
  1827. // Wait until the over current bit is clear.
  1828. //
  1829. while ((PortStatus->Status & USB_PORT_STATUS_OVER_CURRENT) != 0) {
  1830. Status = UsbpHubGetPortStatus(Hub,
  1831. PortIndex + 1,
  1832. &HardwareStatus);
  1833. if (!KSUCCESS(Status)) {
  1834. goto HubInterruptTransferCompletionWorkerEnd;
  1835. }
  1836. UsbpHubUpdatePortStatus(Hub, PortIndex, HardwareStatus);
  1837. }
  1838. //
  1839. // Now wipe the port status and enable the power on the port.
  1840. //
  1841. RtlZeroMemory(PortStatus, sizeof(USB_PORT_STATUS));
  1842. Hub->HubStatus.PortDeviceSpeed[PortIndex] = UsbDeviceSpeedInvalid;
  1843. Status = UsbpHubEnablePortPower(Hub, PortIndex);
  1844. if (!KSUCCESS(Status)) {
  1845. goto HubInterruptTransferCompletionWorkerEnd;
  1846. }
  1847. //
  1848. // Collect the status one more time after the power on. If there is
  1849. // something behind the port then the connection changed bit should
  1850. // get set.
  1851. //
  1852. Status = UsbpHubGetPortStatus(Hub, PortIndex + 1, &HardwareStatus);
  1853. if (!KSUCCESS(Status)) {
  1854. goto HubInterruptTransferCompletionWorkerEnd;
  1855. }
  1856. UsbpHubUpdatePortStatus(Hub, PortIndex, HardwareStatus);
  1857. }
  1858. //
  1859. // Attempt to clear out any change bits.
  1860. //
  1861. Status = UsbpHubClearPortChangeBits(Hub,
  1862. PortIndex + 1,
  1863. HardwareStatus);
  1864. if (!KSUCCESS(Status)) {
  1865. goto HubInterruptTransferCompletionWorkerEnd;
  1866. }
  1867. //
  1868. // If the connection status has changed, then notify the system of a
  1869. // topology change.
  1870. //
  1871. if ((PortStatus->Change & USB_PORT_STATUS_CHANGE_CONNECTED) != 0) {
  1872. TopologyChanged = TRUE;
  1873. }
  1874. KeReleaseQueuedLock(Device->ChildLock);
  1875. ChildLockHeld = FALSE;
  1876. }
  1877. HubInterruptTransferCompletionWorkerEnd:
  1878. if (ChildLockHeld != FALSE) {
  1879. KeReleaseQueuedLock(Device->ChildLock);
  1880. }
  1881. //
  1882. // If there was a topology change on the hub, notify the system.
  1883. //
  1884. if (TopologyChanged != FALSE) {
  1885. UsbDevice = (PUSB_DEVICE)Hub->DeviceHandle;
  1886. IoNotifyDeviceTopologyChange(UsbDevice->Device);
  1887. }
  1888. //
  1889. // Resubmit the transfer even if this routine failed.
  1890. //
  1891. if (SubmitTransfer != FALSE) {
  1892. Status = UsbSubmitTransfer(Hub->InterruptTransfer);
  1893. ASSERT(KSUCCESS(Status));
  1894. }
  1895. return;
  1896. }
  1897. KSTATUS
  1898. UsbpHubClearPortChangeBits (
  1899. PUSB_HUB Hub,
  1900. ULONG PortNumber,
  1901. ULONG PortStatus
  1902. )
  1903. /*++
  1904. Routine Description:
  1905. This routine communicates with the given hub to clear any change status
  1906. bits set in the port status.
  1907. Arguments:
  1908. Hub - Supplies a pointer to the hub that owns the port.
  1909. PortNumber - Supplies the one-indexed port number (zero is not a valid
  1910. value here).
  1911. PortStatus - Supplies the port status bits. Any change bits set here will
  1912. be cleared.
  1913. Return Value:
  1914. Status code.
  1915. --*/
  1916. {
  1917. KSTATUS Status;
  1918. ASSERT(PortNumber != 0);
  1919. //
  1920. // Clear out any change bits.
  1921. //
  1922. PortStatus = PortStatus >> USB_HUB_PORT_STATUS_CHANGE_SHIFT;
  1923. if ((PortStatus & USB_HUB_PORT_STATUS_DEVICE_CONNECTED) != 0) {
  1924. Status = UsbpHubSetOrClearFeature(Hub,
  1925. FALSE,
  1926. USB_HUB_FEATURE_C_PORT_CONNECTION,
  1927. PortNumber);
  1928. if (!KSUCCESS(Status)) {
  1929. goto HubClearPortChangeBits;
  1930. }
  1931. }
  1932. if ((PortStatus & USB_HUB_PORT_STATUS_ENABLED) != 0) {
  1933. Status = UsbpHubSetOrClearFeature(Hub,
  1934. FALSE,
  1935. USB_HUB_FEATURE_C_PORT_ENABLE,
  1936. PortNumber);
  1937. if (!KSUCCESS(Status)) {
  1938. goto HubClearPortChangeBits;
  1939. }
  1940. }
  1941. if ((PortStatus & USB_HUB_PORT_STATUS_SUSPENDED) != 0) {
  1942. Status = UsbpHubSetOrClearFeature(Hub,
  1943. FALSE,
  1944. USB_HUB_FEATURE_C_PORT_SUSPEND,
  1945. PortNumber);
  1946. if (!KSUCCESS(Status)) {
  1947. goto HubClearPortChangeBits;
  1948. }
  1949. }
  1950. if ((PortStatus & USB_HUB_PORT_STATUS_OVER_CURRENT) != 0) {
  1951. Status = UsbpHubSetOrClearFeature(
  1952. Hub,
  1953. FALSE,
  1954. USB_HUB_FEATURE_C_PORT_OVER_CURRENT,
  1955. PortNumber);
  1956. if (!KSUCCESS(Status)) {
  1957. goto HubClearPortChangeBits;
  1958. }
  1959. }
  1960. if ((PortStatus & USB_HUB_PORT_STATUS_RESET) != 0) {
  1961. Status = UsbpHubSetOrClearFeature(Hub,
  1962. FALSE,
  1963. USB_HUB_FEATURE_C_PORT_RESET,
  1964. PortNumber);
  1965. if (!KSUCCESS(Status)) {
  1966. goto HubClearPortChangeBits;
  1967. }
  1968. }
  1969. Status = STATUS_SUCCESS;
  1970. HubClearPortChangeBits:
  1971. return Status;
  1972. }
  1973. VOID
  1974. UsbpHubAddDevice (
  1975. PUSB_HUB Hub,
  1976. ULONG PortIndex
  1977. )
  1978. /*++
  1979. Routine Description:
  1980. This routine attempts to add a device to the given hub at the given port
  1981. index. It resets the port and then tries to enumerate a device.
  1982. Arguments:
  1983. Hub - Supplies a pointer to the USB hub that is adding the new device.
  1984. PortIndex - Supplies the index of the hub port at which the new device is
  1985. to be added.
  1986. Return Value:
  1987. None.
  1988. --*/
  1989. {
  1990. PUSB_DEVICE Child;
  1991. PUSB_DEVICE Device;
  1992. PUSB_PORT_STATUS PortStatus;
  1993. KSTATUS Status;
  1994. Child = NULL;
  1995. Device = (PUSB_DEVICE)Hub->DeviceHandle;
  1996. ASSERT(KeIsQueuedLockHeld(Device->ChildLock) != FALSE);
  1997. ASSERT(Hub->HubStatus.PortStatus != NULL);
  1998. //
  1999. // When the system last checked, there was a device present on this port.
  2000. // Wait the minimum debounce interval according to section 7.1.7.3 of the
  2001. // USB specification, and then recheck the state and proceed only if the
  2002. // device is still present.
  2003. //
  2004. KeDelayExecution(FALSE, FALSE, 100 * MICROSECONDS_PER_MILLISECOND);
  2005. //
  2006. // Get the current hub status.
  2007. //
  2008. Status = UsbpGetHubStatus(Hub, TRUE);
  2009. if (!KSUCCESS(Status)) {
  2010. goto HubAddDevice;
  2011. }
  2012. //
  2013. // If the device is not present, exit.
  2014. //
  2015. PortStatus = &(Hub->HubStatus.PortStatus[PortIndex]);
  2016. ASSERT((PortStatus->Change & USB_PORT_STATUS_CHANGE_CONNECTED) != 0);
  2017. if ((PortStatus->Status & USB_PORT_STATUS_CONNECTED) == 0) {
  2018. Status = STATUS_SUCCESS;
  2019. goto HubAddDevice;
  2020. }
  2021. //
  2022. // Reset the port. If the device is still there after the reset, then
  2023. // create a device.
  2024. //
  2025. Status = UsbpResetHubPort(Hub, PortIndex);
  2026. if (!KSUCCESS(Status)) {
  2027. goto HubAddDevice;
  2028. }
  2029. if ((PortStatus->Status & USB_PORT_STATUS_CONNECTED) != 0) {
  2030. Status = UsbpEnumerateDevice(Hub,
  2031. Device,
  2032. PortIndex + 1,
  2033. Hub->HubStatus.PortDeviceSpeed[PortIndex],
  2034. (PVOID)&Child);
  2035. if (!KSUCCESS(Status)) {
  2036. goto HubAddDevice;
  2037. }
  2038. ASSERT(Child != NULL);
  2039. }
  2040. HubAddDevice:
  2041. return;
  2042. }
  2043. KSTATUS
  2044. UsbpHubEnablePortPower (
  2045. PUSB_HUB Hub,
  2046. ULONG PortIndex
  2047. )
  2048. /*++
  2049. Routine Description:
  2050. This routine enables power on a hub port.
  2051. Arguments:
  2052. Hub - Supplies a pointer to a hub.
  2053. PortIndex - Supplies the zero-based index of the port to be powered on.
  2054. Return Value:
  2055. Status code.
  2056. --*/
  2057. {
  2058. KSTATUS Status;
  2059. Status = UsbpHubSetOrClearFeature(Hub,
  2060. TRUE,
  2061. USB_HUB_FEATURE_PORT_POWER,
  2062. PortIndex + 1);
  2063. if (!KSUCCESS(Status)) {
  2064. goto HubEnablePortPowerEnd;
  2065. }
  2066. if (Hub->HasIndicators != FALSE) {
  2067. Status = UsbpHubSetOrClearFeature(
  2068. Hub,
  2069. TRUE,
  2070. USB_HUB_FEATURE_PORT_INDICATOR,
  2071. (PortIndex + 1) | USB_HUB_INDICATOR_AUTOMATIC);
  2072. if (!KSUCCESS(Status)) {
  2073. goto HubEnablePortPowerEnd;
  2074. }
  2075. }
  2076. //
  2077. // Now that the port has been powered up, delay for the appropriate
  2078. // amount of time before accessing it again.
  2079. //
  2080. KeDelayExecution(FALSE,
  2081. FALSE,
  2082. Hub->PowerUpDelayIn2ms * 2 * MICROSECONDS_PER_MILLISECOND);
  2083. HubEnablePortPowerEnd:
  2084. return Status;
  2085. }