hub.c 71 KB

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