usbcore.c 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823
  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. usbcore.c
  9. Abstract:
  10. This module implements the USB core library.
  11. Author:
  12. Evan Green 15-Jan-2013
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/driver.h>
  20. #include <minoca/fw/acpitabs.h>
  21. #include "usbcore.h"
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // Define the initial allocation size for a configuration descriptor.
  27. //
  28. #define USB_INITIAL_CONFIGURATION_LENGTH 0xFF
  29. //
  30. // ------------------------------------------------------ Data Type Definitions
  31. //
  32. //
  33. // ----------------------------------------------- Internal Function Prototypes
  34. //
  35. KSTATUS
  36. UsbpCancelTransfer (
  37. PUSB_TRANSFER_PRIVATE Transfer
  38. );
  39. VOID
  40. UsbpDestroyTransfer (
  41. PUSB_TRANSFER Transfer
  42. );
  43. KSTATUS
  44. UsbpGetConfiguration (
  45. PUSB_DEVICE Device,
  46. UCHAR ConfigurationNumber,
  47. BOOL NumberIsIndex,
  48. PUSB_CONFIGURATION *Configuration
  49. );
  50. KSTATUS
  51. UsbpSubmitTransfer (
  52. PUSB_TRANSFER Transfer,
  53. ULONG PrivateFlags,
  54. BOOL PolledMode
  55. );
  56. KSTATUS
  57. UsbpCreateEndpointsForInterface (
  58. PUSB_DEVICE Device,
  59. PUSB_INTERFACE Interface
  60. );
  61. PUSB_ENDPOINT
  62. UsbpGetDeviceEndpoint (
  63. PUSB_DEVICE Device,
  64. UCHAR EndpointNumber
  65. );
  66. VOID
  67. UsbpCompletedTransferWorker (
  68. PVOID Parameter
  69. );
  70. RUNLEVEL
  71. UsbpAcquireCompletedTransfersLock (
  72. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue
  73. );
  74. VOID
  75. UsbpReleaseCompletedTransfersLock (
  76. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue,
  77. RUNLEVEL OldRunLevel
  78. );
  79. //
  80. // -------------------------------------------------------------------- Globals
  81. //
  82. PDRIVER UsbCoreDriver;
  83. //
  84. // Store a pointer to the USB core work queue.
  85. //
  86. PWORK_QUEUE UsbCoreWorkQueue = NULL;
  87. //
  88. // Store a pointer to the special USB paging transfer completion queue.
  89. //
  90. PUSB_TRANSFER_COMPLETION_QUEUE UsbCorePagingCompletionQueue = NULL;
  91. //
  92. // Store a list of all active host controllers and a lock that protects this
  93. // list.
  94. //
  95. LIST_ENTRY UsbHostControllerList;
  96. PQUEUED_LOCK UsbHostControllerListLock = NULL;
  97. //
  98. // Store a list of all active USB devices in the system.
  99. //
  100. LIST_ENTRY UsbDeviceList;
  101. PQUEUED_LOCK UsbDeviceListLock = NULL;
  102. //
  103. // Store a bitfield of enabled USB debug flags. See USB_DEBUG_* definitions.
  104. //
  105. ULONG UsbDebugFlags = 0x0;
  106. //
  107. // Set this to enable debugging only a single device address. If this is zero,
  108. // it's enabled on all addresses.
  109. //
  110. UCHAR UsbDebugDeviceAddress = 0x0;
  111. //
  112. // Store a pointer to the USB debugger handoff data.
  113. //
  114. PDEBUG_HANDOFF_DATA UsbDebugHandoffData = NULL;
  115. //
  116. // Define transfer direction and endpoint type strings.
  117. //
  118. PSTR UsbTransferDirectionStrings[UsbTransferDirectionCount] = {
  119. "INVALID",
  120. "from",
  121. "to",
  122. "from/to"
  123. };
  124. PSTR UsbTransferTypeStrings[UsbTransferTypeCount] = {
  125. "INVALID",
  126. "control",
  127. "interrupt",
  128. "bulk",
  129. "isochronous",
  130. };
  131. PSTR UsbErrorStrings[UsbErrorCount] = {
  132. "No error",
  133. "Not started",
  134. "Cancelled",
  135. "Allocated incorrectly",
  136. "Double submitted",
  137. "Incorrectly filled out",
  138. "Failed to submit",
  139. "Stalled",
  140. "Data buffer",
  141. "Babble",
  142. "Nak",
  143. "CrcOrTimeout",
  144. "Bitstuff",
  145. "Missed microframe",
  146. "Misaligned buffer",
  147. "Device not connected",
  148. "Short packet",
  149. };
  150. //
  151. // ------------------------------------------------------------------ Functions
  152. //
  153. __USED
  154. KSTATUS
  155. DriverEntry (
  156. PDRIVER Driver
  157. )
  158. /*++
  159. Routine Description:
  160. This routine implements the initial entry point of the USB core library,
  161. called when the library is first loaded.
  162. Arguments:
  163. Driver - Supplies a pointer to the driver object.
  164. Return Value:
  165. Status code.
  166. --*/
  167. {
  168. ULONG PathIndex;
  169. KSTATUS Status;
  170. Status = STATUS_INSUFFICIENT_RESOURCES;
  171. UsbCoreDriver = Driver;
  172. //
  173. // Initialize USB structures.
  174. //
  175. INITIALIZE_LIST_HEAD(&UsbHostControllerList);
  176. INITIALIZE_LIST_HEAD(&UsbDeviceList);
  177. ASSERT((UsbHostControllerListLock == NULL) &&
  178. (UsbDeviceListLock == NULL) &&
  179. (UsbCorePagingCompletionQueue == NULL) &&
  180. (UsbCoreWorkQueue == NULL));
  181. UsbHostControllerListLock = KeCreateQueuedLock();
  182. if (UsbHostControllerListLock == NULL) {
  183. goto DriverEntryEnd;
  184. }
  185. UsbDeviceListLock = KeCreateQueuedLock();
  186. if (UsbDeviceListLock == NULL) {
  187. goto DriverEntryEnd;
  188. }
  189. UsbCoreWorkQueue = KeCreateWorkQueue(WORK_QUEUE_FLAG_SUPPORT_DISPATCH_LEVEL,
  190. "UsbCoreWorker");
  191. if (UsbCoreWorkQueue== NULL) {
  192. goto DriverEntryEnd;
  193. }
  194. Status = KdGetDeviceInformation(&UsbDebugHandoffData);
  195. if ((!KSUCCESS(Status)) || (UsbDebugHandoffData == NULL) ||
  196. (UsbDebugHandoffData->PortType != DEBUG_PORT_TYPE_USB)) {
  197. UsbDebugHandoffData = NULL;
  198. }
  199. if ((UsbDebugFlags & USB_DEBUG_DEBUGGER_HANDOFF) != 0) {
  200. RtlDebugPrint("USB: Debug handoff data: 0x%x\n", UsbDebugHandoffData);
  201. if (UsbDebugHandoffData != NULL) {
  202. RtlDebugPrint("USB: Debug device %04X:%04X is at path ",
  203. UsbDebugHandoffData->U.Usb.VendorId,
  204. UsbDebugHandoffData->U.Usb.ProductId);
  205. for (PathIndex = 0;
  206. PathIndex < UsbDebugHandoffData->U.Usb.DevicePathSize;
  207. PathIndex += 1) {
  208. if (PathIndex != 0) {
  209. RtlDebugPrint(", ");
  210. }
  211. RtlDebugPrint(
  212. "%d",
  213. UsbDebugHandoffData->U.Usb.DevicePath[PathIndex]);
  214. }
  215. RtlDebugPrint("\n");
  216. }
  217. }
  218. Status = STATUS_SUCCESS;
  219. DriverEntryEnd:
  220. return Status;
  221. }
  222. USB_API
  223. HANDLE
  224. UsbDeviceOpen (
  225. PUSB_DEVICE Device
  226. )
  227. /*++
  228. Routine Description:
  229. This routine attempts to open a USB device for I/O.
  230. Arguments:
  231. Device - Supplies a pointer to the device to open.
  232. Return Value:
  233. Returns a handle to the device upon success.
  234. INVALID_HANDLE if the device could not be opened.
  235. --*/
  236. {
  237. if (Device->Connected != FALSE) {
  238. UsbpDeviceAddReference(Device);
  239. return (HANDLE)Device;
  240. }
  241. return INVALID_HANDLE;
  242. }
  243. USB_API
  244. VOID
  245. UsbDeviceClose (
  246. HANDLE UsbDeviceHandle
  247. )
  248. /*++
  249. Routine Description:
  250. This routine closes an open USB handle.
  251. Arguments:
  252. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  253. Return Value:
  254. None.
  255. --*/
  256. {
  257. PUSB_DEVICE Device;
  258. if (UsbDeviceHandle == INVALID_HANDLE) {
  259. return;
  260. }
  261. Device = (PUSB_DEVICE)UsbDeviceHandle;
  262. UsbpDeviceReleaseReference(Device);
  263. return;
  264. }
  265. USB_API
  266. PUSB_TRANSFER
  267. UsbAllocateTransfer (
  268. HANDLE UsbDeviceHandle,
  269. UCHAR EndpointNumber,
  270. ULONG MaxTransferSize,
  271. ULONG Flags
  272. )
  273. /*++
  274. Routine Description:
  275. This routine allocates a new USB transfer structure. This routine must be
  276. used to allocate transfers.
  277. Arguments:
  278. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  279. EndpointNumber - Supplies the endpoint number that the transfer will go to.
  280. MaxTransferSize - Supplies the maximum length, in bytes, of the transfer.
  281. Attempts to submit a transfer with lengths longer than this initialized
  282. length will fail. Longer transfer sizes do require more resources as
  283. they are split into subpackets, so try to be reasonable.
  284. Flags - Supplies a bitfield of flags regarding the transaction. See
  285. USB_TRANSFER_FLAG_* definitions.
  286. Return Value:
  287. Returns a pointer to the new USB transfer on success.
  288. NULL when there are insufficient resources to complete the request.
  289. --*/
  290. {
  291. PUSB_TRANSFER Transfer;
  292. Transfer = UsbpAllocateTransfer((PUSB_DEVICE)UsbDeviceHandle,
  293. EndpointNumber,
  294. MaxTransferSize,
  295. Flags);
  296. return Transfer;
  297. }
  298. USB_API
  299. VOID
  300. UsbDestroyTransfer (
  301. PUSB_TRANSFER Transfer
  302. )
  303. /*++
  304. Routine Description:
  305. This routine destroys an allocated transfer. This transfer must not be
  306. actively transferring.
  307. Arguments:
  308. Transfer - Supplies a pointer to the transfer to destroy.
  309. Return Value:
  310. None.
  311. --*/
  312. {
  313. UsbTransferReleaseReference(Transfer);
  314. return;
  315. }
  316. USB_API
  317. KSTATUS
  318. UsbSubmitTransfer (
  319. PUSB_TRANSFER Transfer
  320. )
  321. /*++
  322. Routine Description:
  323. This routine submits a USB transfer. The routine returns immediately,
  324. indicating only whether the transfer was submitted successfully. When the
  325. transfer actually completes, the callback routine will be called.
  326. Arguments:
  327. Transfer - Supplies a pointer to the transfer to submit.
  328. Return Value:
  329. STATUS_SUCCESS if the transfer was submitted to the USB host controller's
  330. queue.
  331. STATUS_INVALID_PARAMETER if one or more of the transfer fields is not
  332. properly filled out.
  333. Failing status codes if the request could not be submitted.
  334. --*/
  335. {
  336. return UsbpSubmitTransfer(Transfer, 0, FALSE);
  337. }
  338. USB_API
  339. KSTATUS
  340. UsbSubmitSynchronousTransfer (
  341. PUSB_TRANSFER Transfer
  342. )
  343. /*++
  344. Routine Description:
  345. This routine submits a USB transfer, and does not return until the transfer
  346. is completed successfully or with an error. This routine must be called at
  347. low level.
  348. Arguments:
  349. Transfer - Supplies a pointer to the transfer to submit.
  350. Return Value:
  351. STATUS_SUCCESS if the transfer was submitted to the USB host controller's
  352. queue.
  353. STATUS_INVALID_PARAMETER if one or more of the transfer fields is not
  354. properly filled out.
  355. Failing status codes if the request could not be submitted.
  356. --*/
  357. {
  358. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  359. KSTATUS Status;
  360. ASSERT(KeGetRunLevel() == RunLevelLow);
  361. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  362. KeSignalEvent(CompleteTransfer->Event, SignalOptionUnsignal);
  363. Status = UsbpSubmitTransfer(Transfer,
  364. USB_TRANSFER_PRIVATE_SYNCHRONOUS,
  365. FALSE);
  366. if (!KSUCCESS(Status)) {
  367. return Status;
  368. }
  369. //
  370. // Wait for the transfer to complete.
  371. //
  372. KeWaitForEvent(CompleteTransfer->Event, FALSE, WAIT_TIME_INDEFINITE);
  373. //
  374. // Assert that the transfer is now inactive. The caller should coordinate
  375. // not re-submitting this transfer before this call returns the status.
  376. //
  377. ASSERT(CompleteTransfer->State == TransferInactive);
  378. return Transfer->Status;
  379. }
  380. USB_API
  381. KSTATUS
  382. UsbSubmitPolledTransfer (
  383. PUSB_TRANSFER Transfer
  384. )
  385. /*++
  386. Routine Description:
  387. This routine submits a USB transfer, and does not return until the transfer
  388. is completed successfully or with an error. This routine is meant to be
  389. called in critical code paths at high level.
  390. Arguments:
  391. Transfer - Supplies a pointer to the transfer to submit.
  392. Return Value:
  393. Status code.
  394. --*/
  395. {
  396. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  397. ULONG OriginalState;
  398. KSTATUS Status;
  399. ASSERT(KeGetRunLevel() == RunLevelHigh);
  400. ASSERT(Transfer->CallbackRoutine == NULL);
  401. Transfer->Flags |= USB_TRANSFER_FLAG_NO_INTERRUPT_ON_COMPLETION;
  402. Status = UsbpSubmitTransfer(Transfer,
  403. USB_TRANSFER_PRIVATE_SYNCHRONOUS,
  404. TRUE);
  405. if (!KSUCCESS(Status)) {
  406. return Status;
  407. }
  408. //
  409. // If the transfer was successful, then it should be in the active state.
  410. // Flip it back to inactive.
  411. //
  412. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  413. OriginalState = RtlAtomicCompareExchange32(&(CompleteTransfer->State),
  414. TransferInactive,
  415. TransferActive);
  416. ASSERT(OriginalState == TransferActive);
  417. return Status;
  418. }
  419. USB_API
  420. KSTATUS
  421. UsbCancelTransfer (
  422. PUSB_TRANSFER Transfer,
  423. BOOL Wait
  424. )
  425. /*++
  426. Routine Description:
  427. This routine cancels a USB transfer, waiting for the transfer to enter the
  428. inactive state before returning. Must be called at low level.
  429. Arguments:
  430. Transfer - Supplies a pointer to the transfer to cancel.
  431. Wait - Supplies a boolean indicating that the caller wants to wait for the
  432. transfer the reach the inactive state. Specify TRUE if unsure.
  433. Return Value:
  434. Returns STATUS_SUCCESS if the transfer was successfully cancelled.
  435. Returns STATUS_TOO_LATE if the transfer was not cancelled, but moved to the
  436. inactive state.
  437. --*/
  438. {
  439. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  440. KSTATUS Status;
  441. ASSERT(KeGetRunLevel() == RunLevelLow);
  442. //
  443. // Attempt to cancel the transfer.
  444. //
  445. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  446. Status = UsbpCancelTransfer(CompleteTransfer);
  447. //
  448. // If desired, wait until the transfer has entered the inactive state.
  449. //
  450. if (Wait != FALSE) {
  451. while (CompleteTransfer->State != TransferInactive) {
  452. KeYield();
  453. }
  454. //
  455. // If the transfer was successfully pulled off the hardware queue, then
  456. // it really shouldn't be active. If it was too late to cancel, then it
  457. // may be active again. Tough luck.
  458. //
  459. ASSERT(!KSUCCESS(Status) ||
  460. (CompleteTransfer->State == TransferInactive));
  461. }
  462. return Status;
  463. }
  464. USB_API
  465. KSTATUS
  466. UsbInitializePagingDeviceTransfers (
  467. VOID
  468. )
  469. /*++
  470. Routine Description:
  471. This routine initializes the USB core to handle special paging device
  472. transfers that are serviced on their own work queue.
  473. Arguments:
  474. None.
  475. Return Value:
  476. Status code.
  477. --*/
  478. {
  479. ULONG AllocationSize;
  480. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue;
  481. PVOID OriginalQueue;
  482. KSTATUS Status;
  483. //
  484. // If the paging device transfer completion queue is already initialized,
  485. // then all is ready to go.
  486. //
  487. if (UsbCorePagingCompletionQueue != NULL) {
  488. return STATUS_SUCCESS;
  489. }
  490. //
  491. // Otherwise initialize a transfer completion queue.
  492. //
  493. AllocationSize = sizeof(USB_TRANSFER_COMPLETION_QUEUE);
  494. CompletionQueue = MmAllocateNonPagedPool(AllocationSize,
  495. USB_CORE_ALLOCATION_TAG);
  496. if (CompletionQueue == NULL) {
  497. Status = STATUS_INSUFFICIENT_RESOURCES;
  498. goto InitializePagingDeviceTransfersEnd;
  499. }
  500. Status = UsbpInitializeTransferCompletionQueue(CompletionQueue, TRUE);
  501. if (!KSUCCESS(Status)) {
  502. goto InitializePagingDeviceTransfersEnd;
  503. }
  504. //
  505. // Now try make this new transfer completion queue the global queue.
  506. //
  507. OriginalQueue = (PVOID)RtlAtomicCompareExchange(
  508. (volatile UINTN *)&UsbCorePagingCompletionQueue,
  509. (UINTN)CompletionQueue,
  510. (UINTN)NULL);
  511. //
  512. // If the original queue value was still NULL, then this completion queue
  513. // won the race, do not destroy it below.
  514. //
  515. if (OriginalQueue == NULL) {
  516. CompletionQueue = NULL;
  517. }
  518. Status = STATUS_SUCCESS;
  519. InitializePagingDeviceTransfersEnd:
  520. if (CompletionQueue != NULL) {
  521. UsbpDestroyTransferCompletionQueue(CompletionQueue);
  522. MmFreeNonPagedPool(CompletionQueue);
  523. }
  524. return Status;
  525. }
  526. USB_API
  527. ULONG
  528. UsbTransferAddReference (
  529. PUSB_TRANSFER Transfer
  530. )
  531. /*++
  532. Routine Description:
  533. This routine adds a reference to a USB transfer.
  534. Arguments:
  535. Transfer - Supplies a pointer to the transfer that is to be referenced.
  536. Return Value:
  537. Returns the old reference count.
  538. --*/
  539. {
  540. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  541. ULONG OldReferenceCount;
  542. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  543. OldReferenceCount = RtlAtomicAdd32(&(CompleteTransfer->ReferenceCount), 1);
  544. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  545. return OldReferenceCount;
  546. }
  547. USB_API
  548. ULONG
  549. UsbTransferReleaseReference (
  550. PUSB_TRANSFER Transfer
  551. )
  552. /*++
  553. Routine Description:
  554. This routine releases a reference on a USB transfer.
  555. Arguments:
  556. Transfer - Supplies a pointer to the transfer that is to be reference.
  557. Return Value:
  558. Returns the old reference count.
  559. --*/
  560. {
  561. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  562. ULONG OldReferenceCount;
  563. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  564. OldReferenceCount = RtlAtomicAdd32(&(CompleteTransfer->ReferenceCount),
  565. (ULONG)-1);
  566. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  567. if (OldReferenceCount == 1) {
  568. UsbpDestroyTransfer(Transfer);
  569. }
  570. return OldReferenceCount;
  571. }
  572. USB_API
  573. KSTATUS
  574. UsbGetStatus (
  575. HANDLE UsbDeviceHandle,
  576. UCHAR RequestRecipient,
  577. USHORT Index,
  578. PUSHORT Data
  579. )
  580. /*++
  581. Routine Description:
  582. This routine gets the status from the given device, interface, or endpoint,
  583. as determined based on the request type and index. This routine must be
  584. called at low level.
  585. Arguments:
  586. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  587. RequestRecipient - Supplies the recipient of this get status request.
  588. Index - Supplies the index of this get status request. This can be
  589. zero for devices, an interface number, or an endpoint number.
  590. Data - Supplies a pointer that receives the status from the request.
  591. Return Value:
  592. Status code.
  593. --*/
  594. {
  595. PUSB_DEVICE Device;
  596. ULONG LengthTransferred;
  597. USB_SETUP_PACKET SetupPacket;
  598. KSTATUS Status;
  599. ASSERT(KeGetRunLevel() == RunLevelLow);
  600. //
  601. // Validate the arguments.
  602. //
  603. if ((UsbDeviceHandle == INVALID_HANDLE) ||
  604. ((RequestRecipient != USB_SETUP_REQUEST_DEVICE_RECIPIENT) &&
  605. (RequestRecipient != USB_SETUP_REQUEST_INTERFACE_RECIPIENT) &&
  606. (RequestRecipient != USB_SETUP_REQUEST_ENDPOINT_RECIPIENT))) {
  607. Status = STATUS_INVALID_PARAMETER;
  608. goto GetStatusEnd;
  609. }
  610. //
  611. // Initialize the setup packet to send the device.
  612. //
  613. RtlZeroMemory(&SetupPacket, sizeof(USB_SETUP_PACKET));
  614. SetupPacket.RequestType = RequestRecipient | USB_SETUP_REQUEST_TO_HOST;
  615. SetupPacket.Request = USB_REQUEST_GET_STATUS;
  616. SetupPacket.Value = 0;
  617. SetupPacket.Index = Index;
  618. SetupPacket.Length = sizeof(USHORT);
  619. //
  620. // Send the transfer.
  621. //
  622. Device = (PUSB_DEVICE)UsbDeviceHandle;
  623. Status = UsbSendControlTransfer(Device,
  624. UsbTransferDirectionIn,
  625. &SetupPacket,
  626. Data,
  627. sizeof(USHORT),
  628. &LengthTransferred);
  629. //
  630. // Return failure if the transfer succeeded, but not enough bytes were
  631. // returned.
  632. //
  633. if (KSUCCESS(Status) && (LengthTransferred < sizeof(USHORT))) {
  634. Status = STATUS_DEVICE_IO_ERROR;
  635. goto GetStatusEnd;
  636. }
  637. GetStatusEnd:
  638. return Status;
  639. }
  640. USB_API
  641. KSTATUS
  642. UsbSetFeature (
  643. HANDLE UsbDeviceHandle,
  644. UCHAR RequestRecipient,
  645. USHORT Feature,
  646. USHORT Index
  647. )
  648. /*++
  649. Routine Description:
  650. This routine sets the given feature for a device, interface or endpoint,
  651. as specified by the request type and index. This routine must be called at
  652. low level.
  653. Arguments:
  654. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  655. RequestRecipient - Supplies the recipient of this clear feature request.
  656. Feature - Supplies the value of this clear feature request.
  657. Index - Supplies the index of this clear feature request. This can be
  658. zero for devices, an interface number, or an endpoint number.
  659. Return Value:
  660. Status code.
  661. --*/
  662. {
  663. PUSB_DEVICE Device;
  664. USB_SETUP_PACKET SetupPacket;
  665. KSTATUS Status;
  666. ASSERT(KeGetRunLevel() == RunLevelLow);
  667. //
  668. // Validate the arguments.
  669. //
  670. if ((UsbDeviceHandle == INVALID_HANDLE) ||
  671. ((RequestRecipient != USB_SETUP_REQUEST_DEVICE_RECIPIENT) &&
  672. (RequestRecipient != USB_SETUP_REQUEST_INTERFACE_RECIPIENT) &&
  673. (RequestRecipient != USB_SETUP_REQUEST_ENDPOINT_RECIPIENT)) ||
  674. ((RequestRecipient == USB_SETUP_REQUEST_ENDPOINT_RECIPIENT) &&
  675. (Feature != USB_FEATURE_ENDPOINT_HALT)) ||
  676. ((RequestRecipient == USB_SETUP_REQUEST_DEVICE_RECIPIENT) &&
  677. (Feature != USB_FEATURE_DEVICE_REMOTE_WAKEUP))) {
  678. Status = STATUS_INVALID_PARAMETER;
  679. goto SetFeatureEnd;
  680. }
  681. //
  682. // There are no interface features defined in the USB specification.
  683. //
  684. ASSERT(RequestRecipient != USB_SETUP_REQUEST_INTERFACE_RECIPIENT);
  685. //
  686. // The test mode feature is not allowed to be cleared.
  687. //
  688. ASSERT(Feature != USB_FEATURE_DEVICE_TEST_MODE);
  689. //
  690. // Initialize the setup packet to send the device.
  691. //
  692. RtlZeroMemory(&SetupPacket, sizeof(USB_SETUP_PACKET));
  693. SetupPacket.RequestType = RequestRecipient | USB_SETUP_REQUEST_TO_DEVICE;
  694. SetupPacket.Request = USB_REQUEST_SET_FEATURE;
  695. SetupPacket.Value = Feature;
  696. SetupPacket.Index = Index;
  697. SetupPacket.Length = 0;
  698. //
  699. // Send the transfer.
  700. //
  701. Device = (PUSB_DEVICE)UsbDeviceHandle;
  702. Status = UsbSendControlTransfer(Device,
  703. UsbTransferDirectionOut,
  704. &SetupPacket,
  705. NULL,
  706. 0,
  707. NULL);
  708. if (!KSUCCESS(Status)) {
  709. goto SetFeatureEnd;
  710. }
  711. SetFeatureEnd:
  712. return Status;
  713. }
  714. USB_API
  715. KSTATUS
  716. UsbClearFeature (
  717. HANDLE UsbDeviceHandle,
  718. UCHAR RequestRecipient,
  719. USHORT Feature,
  720. USHORT Index
  721. )
  722. /*++
  723. Routine Description:
  724. This routine clears the given feature from a device, interface or endpoint,
  725. as specified by the request type and index. This routine must be called at
  726. low level.
  727. Arguments:
  728. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  729. RequestRecipient - Supplies the recipient of this clear feature request.
  730. Feature - Supplies the value of this clear feature request.
  731. Index - Supplies the index of this clear feature request. This can be
  732. zero for devices, an interface number, or an endpoint number.
  733. Return Value:
  734. Status code.
  735. --*/
  736. {
  737. PUSB_DEVICE Device;
  738. PUSB_ENDPOINT Endpoint;
  739. USB_SETUP_PACKET SetupPacket;
  740. KSTATUS Status;
  741. ASSERT(KeGetRunLevel() == RunLevelLow);
  742. //
  743. // Validate the arguments.
  744. //
  745. if ((UsbDeviceHandle == INVALID_HANDLE) ||
  746. ((RequestRecipient != USB_SETUP_REQUEST_DEVICE_RECIPIENT) &&
  747. (RequestRecipient != USB_SETUP_REQUEST_INTERFACE_RECIPIENT) &&
  748. (RequestRecipient != USB_SETUP_REQUEST_ENDPOINT_RECIPIENT)) ||
  749. ((RequestRecipient == USB_SETUP_REQUEST_ENDPOINT_RECIPIENT) &&
  750. (Feature != USB_FEATURE_ENDPOINT_HALT)) ||
  751. ((RequestRecipient == USB_SETUP_REQUEST_DEVICE_RECIPIENT) &&
  752. (Feature != USB_FEATURE_DEVICE_REMOTE_WAKEUP))) {
  753. Status = STATUS_INVALID_PARAMETER;
  754. goto ClearFeatureEnd;
  755. }
  756. //
  757. // There are no interface features defined in the USB specification.
  758. //
  759. ASSERT(RequestRecipient != USB_SETUP_REQUEST_INTERFACE_RECIPIENT);
  760. //
  761. // The test mode feature is not allowed to be cleared.
  762. //
  763. ASSERT(Feature != USB_FEATURE_DEVICE_TEST_MODE);
  764. //
  765. // Initialize the setup packet to send the device.
  766. //
  767. RtlZeroMemory(&SetupPacket, sizeof(USB_SETUP_PACKET));
  768. SetupPacket.RequestType = RequestRecipient | USB_SETUP_REQUEST_TO_DEVICE;
  769. SetupPacket.Request = USB_REQUEST_CLEAR_FEATURE;
  770. SetupPacket.Value = Feature;
  771. SetupPacket.Index = Index;
  772. SetupPacket.Length = 0;
  773. //
  774. // Send the transfer.
  775. //
  776. Device = (PUSB_DEVICE)UsbDeviceHandle;
  777. Status = UsbSendControlTransfer(Device,
  778. UsbTransferDirectionOut,
  779. &SetupPacket,
  780. NULL,
  781. 0,
  782. NULL);
  783. if (!KSUCCESS(Status)) {
  784. goto ClearFeatureEnd;
  785. }
  786. //
  787. // If this was a successful attempt to clear an endpoint's HALT feature,
  788. // then the endpoint's data toggle needs to be unset, ensuring that the
  789. // next transfer on the endpoint will use DATA0.
  790. //
  791. if ((RequestRecipient == USB_SETUP_REQUEST_ENDPOINT_RECIPIENT) &&
  792. (Feature == USB_FEATURE_ENDPOINT_HALT)) {
  793. Endpoint = UsbpGetDeviceEndpoint(Device, Index);
  794. if (Endpoint == NULL) {
  795. ASSERT(Endpoint != NULL);
  796. Status = STATUS_NOT_FOUND;
  797. goto ClearFeatureEnd;
  798. }
  799. UsbpResetEndpoint(Device, Endpoint);
  800. }
  801. ClearFeatureEnd:
  802. return Status;
  803. }
  804. USB_API
  805. ULONG
  806. UsbGetConfigurationCount (
  807. HANDLE UsbDeviceHandle
  808. )
  809. /*++
  810. Routine Description:
  811. This routine gets the number of possible configurations in a given device.
  812. Arguments:
  813. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  814. Return Value:
  815. Returns the number of configurations in the device.
  816. --*/
  817. {
  818. PUSB_DEVICE Device;
  819. if (UsbDeviceHandle == INVALID_HANDLE) {
  820. return 0;
  821. }
  822. Device = (PUSB_DEVICE)UsbDeviceHandle;
  823. return Device->ConfigurationCount;
  824. }
  825. USB_API
  826. KSTATUS
  827. UsbGetConfiguration (
  828. HANDLE UsbDeviceHandle,
  829. UCHAR ConfigurationNumber,
  830. BOOL NumberIsIndex,
  831. PUSB_CONFIGURATION_DESCRIPTION *Configuration
  832. )
  833. /*++
  834. Routine Description:
  835. This routine gets a configuration out of the given device. This routine will
  836. send a blocking request to the device. This routine must be called at low
  837. level.
  838. Arguments:
  839. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  840. ConfigurationNumber - Supplies the index or configuration value of the
  841. configuration to get.
  842. NumberIsIndex - Supplies a boolean indicating whether the configuration
  843. number is an index (TRUE) or a specific configuration value (FALSE).
  844. Configuration - Supplies a pointer where a pointer to the desired
  845. configuration will be returned.
  846. Return Value:
  847. Status code.
  848. --*/
  849. {
  850. PUSB_DEVICE Device;
  851. PUSB_CONFIGURATION InternalConfiguration;
  852. KSTATUS Status;
  853. Device = (PUSB_DEVICE)UsbDeviceHandle;
  854. Status = UsbpGetConfiguration(Device,
  855. ConfigurationNumber,
  856. NumberIsIndex,
  857. &InternalConfiguration);
  858. *Configuration = &(InternalConfiguration->Description);
  859. return Status;
  860. }
  861. USB_API
  862. PUSB_CONFIGURATION_DESCRIPTION
  863. UsbGetActiveConfiguration (
  864. HANDLE UsbDeviceHandle
  865. )
  866. /*++
  867. Routine Description:
  868. This routine gets the currently active configuration set in the device.
  869. Arguments:
  870. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  871. Return Value:
  872. Returns a pointer to the current configuration.
  873. NULL if the device is not currently configured.
  874. --*/
  875. {
  876. PUSB_DEVICE Device;
  877. if (UsbDeviceHandle == INVALID_HANDLE) {
  878. return NULL;
  879. }
  880. Device = (PUSB_DEVICE)UsbDeviceHandle;
  881. if (Device->ActiveConfiguration == NULL) {
  882. return NULL;
  883. }
  884. return &(Device->ActiveConfiguration->Description);
  885. }
  886. USB_API
  887. KSTATUS
  888. UsbSetConfiguration (
  889. HANDLE UsbDeviceHandle,
  890. UCHAR ConfigurationNumber,
  891. BOOL NumberIsIndex
  892. )
  893. /*++
  894. Routine Description:
  895. This routine sets the configuration to the given configuration value. This
  896. routine must be called at low level.
  897. Arguments:
  898. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  899. ConfigurationNumber - Supplies the configuration index or value to set.
  900. NumberIsIndex - Supplies a boolean indicating whether the configuration
  901. number is an index (TRUE) or a specific configuration value (FALSE).
  902. Return Value:
  903. Status code.
  904. --*/
  905. {
  906. PUSB_CONFIGURATION Configuration;
  907. PLIST_ENTRY CurrentEndpointEntry;
  908. PLIST_ENTRY CurrentInterfaceEntry;
  909. PUSB_DEVICE Device;
  910. PUSB_ENDPOINT Endpoint;
  911. PUSB_INTERFACE Interface;
  912. PLIST_ENTRY InterfaceListHead;
  913. ULONG LengthTransferred;
  914. USB_SETUP_PACKET SetupPacket;
  915. KSTATUS Status;
  916. Device = (PUSB_DEVICE)UsbDeviceHandle;
  917. ASSERT(KeGetRunLevel() == RunLevelLow);
  918. //
  919. // First, get the configuration being described.
  920. //
  921. Status = UsbpGetConfiguration(Device,
  922. ConfigurationNumber,
  923. NumberIsIndex,
  924. &Configuration);
  925. if (!KSUCCESS(Status)) {
  926. goto SetConfigurationEnd;
  927. }
  928. //
  929. // Initialize the setup packet to send the device.
  930. //
  931. RtlZeroMemory(&SetupPacket, sizeof(USB_SETUP_PACKET));
  932. SetupPacket.RequestType = USB_SETUP_REQUEST_TO_DEVICE |
  933. USB_SETUP_REQUEST_STANDARD |
  934. USB_SETUP_REQUEST_DEVICE_RECIPIENT;
  935. SetupPacket.Request = USB_DEVICE_REQUEST_SET_CONFIGURATION;
  936. SetupPacket.Value =
  937. Configuration->Description.Descriptor.ConfigurationValue;
  938. SetupPacket.Index = 0;
  939. SetupPacket.Length = 0;
  940. //
  941. // Lock the device and send the set request. The device is locked to avoid
  942. // getting the active configuration variable out of sync with what the
  943. // device actually has set.
  944. //
  945. KeAcquireQueuedLock(Device->ConfigurationLock);
  946. Status = UsbSendControlTransfer(Device,
  947. UsbTransferDirectionOut,
  948. &SetupPacket,
  949. NULL,
  950. 0,
  951. &LengthTransferred);
  952. if (KSUCCESS(Status)) {
  953. Device->ActiveConfiguration = Configuration;
  954. }
  955. KeReleaseQueuedLock(Device->ConfigurationLock);
  956. //
  957. // Setting the configuration resets the DATA toggle for every endpoint on
  958. // the device. See Section 9.1.1.5 of the USB 2.0 Specification.
  959. //
  960. if (KSUCCESS(Status)) {
  961. UsbpResetEndpoint(Device, Device->EndpointZero);
  962. InterfaceListHead = &(Configuration->Description.InterfaceListHead);
  963. CurrentInterfaceEntry = InterfaceListHead->Next;
  964. while (CurrentInterfaceEntry != InterfaceListHead) {
  965. Interface = LIST_VALUE(CurrentInterfaceEntry,
  966. USB_INTERFACE,
  967. Description.ListEntry);
  968. CurrentEndpointEntry = Interface->EndpointList.Next;
  969. CurrentInterfaceEntry = CurrentInterfaceEntry->Next;
  970. while (CurrentEndpointEntry != &(Interface->EndpointList)) {
  971. Endpoint = LIST_VALUE(CurrentEndpointEntry,
  972. USB_ENDPOINT,
  973. ListEntry);
  974. UsbpResetEndpoint(Device, Endpoint);
  975. CurrentEndpointEntry = CurrentEndpointEntry->Next;
  976. }
  977. }
  978. }
  979. SetConfigurationEnd:
  980. return Status;
  981. }
  982. USB_API
  983. KSTATUS
  984. UsbClaimInterface (
  985. HANDLE UsbDeviceHandle,
  986. UCHAR InterfaceNumber
  987. )
  988. /*++
  989. Routine Description:
  990. This routine claims an interface, preparing it for I/O use. An interface
  991. can be claimed more than once. This routine must be called at low level.
  992. Arguments:
  993. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  994. InterfaceNumber - Supplies the number of the interface to claim.
  995. Return Value:
  996. Status code.
  997. --*/
  998. {
  999. PUSB_CONFIGURATION Configuration;
  1000. PLIST_ENTRY CurrentEntry;
  1001. PUSB_DEVICE Device;
  1002. PUSB_ENDPOINT Endpoint;
  1003. PUSB_INTERFACE Interface;
  1004. KSTATUS Status;
  1005. Device = (PUSB_DEVICE)UsbDeviceHandle;
  1006. Interface = NULL;
  1007. ASSERT(KeGetRunLevel() == RunLevelLow);
  1008. //
  1009. // Lock the device.
  1010. //
  1011. KeAcquireQueuedLock(Device->ConfigurationLock);
  1012. //
  1013. // If no interface has been set on the device yet, then an interface
  1014. // cannot be claimed.
  1015. //
  1016. Configuration = Device->ActiveConfiguration;
  1017. if (Configuration == NULL) {
  1018. Status = STATUS_INVALID_CONFIGURATION;
  1019. goto ClaimInterfaceEnd;
  1020. }
  1021. //
  1022. // Loop through looking for the requested interface.
  1023. //
  1024. CurrentEntry = Configuration->Description.InterfaceListHead.Next;
  1025. while (CurrentEntry != &(Configuration->Description.InterfaceListHead)) {
  1026. Interface = LIST_VALUE(CurrentEntry,
  1027. USB_INTERFACE,
  1028. Description.ListEntry);
  1029. if (Interface->Description.Descriptor.InterfaceNumber ==
  1030. InterfaceNumber) {
  1031. break;
  1032. }
  1033. CurrentEntry = CurrentEntry->Next;
  1034. }
  1035. if (CurrentEntry == &(Configuration->Description.InterfaceListHead)) {
  1036. Status = STATUS_NOT_FOUND;
  1037. goto ClaimInterfaceEnd;
  1038. }
  1039. //
  1040. // If the interface isn't supposed to have any endpoints, then finish.
  1041. //
  1042. if (LIST_EMPTY(&(Interface->Description.EndpointListHead)) != FALSE) {
  1043. Status = STATUS_SUCCESS;
  1044. goto ClaimInterfaceEnd;
  1045. }
  1046. //
  1047. // If there are no endpoints yet, they'll have to be created now.
  1048. //
  1049. if (LIST_EMPTY(&(Interface->EndpointList)) != FALSE) {
  1050. Status = UsbpCreateEndpointsForInterface(Device, Interface);
  1051. if (!KSUCCESS(Status)) {
  1052. goto ClaimInterfaceEnd;
  1053. }
  1054. //
  1055. // The endpoints are there, up the reference counts on them.
  1056. //
  1057. } else {
  1058. CurrentEntry = Interface->EndpointList.Next;
  1059. while (CurrentEntry != &(Interface->EndpointList)) {
  1060. Endpoint = LIST_VALUE(CurrentEntry, USB_ENDPOINT, ListEntry);
  1061. CurrentEntry = CurrentEntry->Next;
  1062. UsbpEndpointAddReference(Endpoint);
  1063. }
  1064. }
  1065. Status = STATUS_SUCCESS;
  1066. ClaimInterfaceEnd:
  1067. KeReleaseQueuedLock(Device->ConfigurationLock);
  1068. return Status;
  1069. }
  1070. USB_API
  1071. VOID
  1072. UsbReleaseInterface (
  1073. HANDLE UsbDeviceHandle,
  1074. UCHAR InterfaceNumber
  1075. )
  1076. /*++
  1077. Routine Description:
  1078. This routine releases an interface that was previously claimed for I/O.
  1079. After this call, the caller that had claimed the interface should not use
  1080. it again without reclaiming it.
  1081. Arguments:
  1082. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  1083. InterfaceNumber - Supplies the number of the interface to release.
  1084. Return Value:
  1085. Status code.
  1086. --*/
  1087. {
  1088. PUSB_CONFIGURATION Configuration;
  1089. PLIST_ENTRY CurrentEntry;
  1090. PUSB_DEVICE Device;
  1091. PUSB_ENDPOINT Endpoint;
  1092. PUSB_INTERFACE Interface;
  1093. Device = (PUSB_DEVICE)UsbDeviceHandle;
  1094. Interface = NULL;
  1095. ASSERT(KeGetRunLevel() == RunLevelLow);
  1096. //
  1097. // Lock the device.
  1098. //
  1099. KeAcquireQueuedLock(Device->ConfigurationLock);
  1100. //
  1101. // If no interface has been set on the device yet, then an interface
  1102. // cannot be claimed.
  1103. //
  1104. Configuration = Device->ActiveConfiguration;
  1105. if (Configuration == NULL) {
  1106. goto ClaimInterfaceEnd;
  1107. }
  1108. //
  1109. // Loop through looking for the requested interface.
  1110. //
  1111. CurrentEntry = Configuration->Description.InterfaceListHead.Next;
  1112. while (CurrentEntry != &(Configuration->Description.InterfaceListHead)) {
  1113. Interface = LIST_VALUE(CurrentEntry,
  1114. USB_INTERFACE,
  1115. Description.ListEntry);
  1116. if (Interface->Description.Descriptor.InterfaceNumber ==
  1117. InterfaceNumber) {
  1118. break;
  1119. }
  1120. CurrentEntry = CurrentEntry->Next;
  1121. }
  1122. if (CurrentEntry == &(Configuration->Description.InterfaceListHead)) {
  1123. goto ClaimInterfaceEnd;
  1124. }
  1125. //
  1126. // If the interface isn't supposed to have any endpoints, then finish.
  1127. //
  1128. if (LIST_EMPTY(&(Interface->Description.EndpointListHead)) != FALSE) {
  1129. goto ClaimInterfaceEnd;
  1130. }
  1131. //
  1132. // Decrement the reference count on each endpoint. It's important to move
  1133. // to the next list entry before releasing the reference, as doing so may
  1134. // cause the endpoint to get unlinked and released.
  1135. //
  1136. CurrentEntry = Interface->EndpointList.Next;
  1137. while (CurrentEntry != &(Interface->EndpointList)) {
  1138. Endpoint = LIST_VALUE(CurrentEntry, USB_ENDPOINT, ListEntry);
  1139. CurrentEntry = CurrentEntry->Next;
  1140. UsbpEndpointReleaseReference(Device, Endpoint);
  1141. }
  1142. ClaimInterfaceEnd:
  1143. KeReleaseQueuedLock(Device->ConfigurationLock);
  1144. return;
  1145. }
  1146. USB_API
  1147. KSTATUS
  1148. UsbSendControlTransfer (
  1149. HANDLE UsbDeviceHandle,
  1150. USB_TRANSFER_DIRECTION TransferDirection,
  1151. PUSB_SETUP_PACKET SetupPacket,
  1152. PVOID Buffer,
  1153. ULONG BufferLength,
  1154. PULONG LengthTransferred
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. This routine sends a syncrhonous control transfer to or from the given USB
  1159. device.
  1160. Arguments:
  1161. UsbDeviceHandle - Supplies a pointer to the device to talk to.
  1162. TransferDirection - Supplies whether or not the transfer is to the device
  1163. or to the host.
  1164. SetupPacket - Supplies a pointer to the setup packet.
  1165. Buffer - Supplies a pointer to the buffer to be sent or received. This does
  1166. not include the setup packet, this is the optional data portion only.
  1167. BufferLength - Supplies the length of the buffer, not including the setup
  1168. packet.
  1169. LengthTransferred - Supplies a pointer where the number of bytes that were
  1170. actually transfered (not including the setup packet) will be returned.
  1171. Return Value:
  1172. Status code.
  1173. --*/
  1174. {
  1175. UINTN AllocationSize;
  1176. UINTN BufferAlignment;
  1177. PUSB_DEVICE Device;
  1178. PIO_BUFFER IoBuffer;
  1179. ULONG IoBufferFlags;
  1180. KSTATUS Status;
  1181. PUSB_TRANSFER Transfer;
  1182. PVOID TransferBuffer;
  1183. ULONG TransferLength;
  1184. Device = (PUSB_DEVICE)UsbDeviceHandle;
  1185. Transfer = NULL;
  1186. if (LengthTransferred != NULL) {
  1187. *LengthTransferred = 0;
  1188. }
  1189. ASSERT(TransferDirection != UsbTransferDirectionInvalid);
  1190. //
  1191. // Create the I/O buffer that will be used for the transfer.
  1192. //
  1193. TransferLength = BufferLength + sizeof(USB_SETUP_PACKET);
  1194. BufferAlignment = MmGetIoBufferAlignment();
  1195. AllocationSize = ALIGN_RANGE_UP(TransferLength, BufferAlignment);
  1196. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  1197. IoBuffer = MmAllocateNonPagedIoBuffer(0,
  1198. MAX_ULONG,
  1199. BufferAlignment,
  1200. AllocationSize,
  1201. IoBufferFlags);
  1202. if (IoBuffer == NULL) {
  1203. Status = STATUS_INSUFFICIENT_RESOURCES;
  1204. goto SendControlTransferEnd;
  1205. }
  1206. ASSERT(IoBuffer->FragmentCount == 1);
  1207. TransferBuffer = IoBuffer->Fragment[0].VirtualAddress;
  1208. RtlCopyMemory(TransferBuffer, SetupPacket, sizeof(USB_SETUP_PACKET));
  1209. if ((TransferDirection == UsbTransferDirectionOut) &&
  1210. (BufferLength != 0)) {
  1211. RtlCopyMemory(TransferBuffer + sizeof(USB_SETUP_PACKET),
  1212. Buffer,
  1213. BufferLength);
  1214. }
  1215. //
  1216. // Create a USB transfer.
  1217. //
  1218. Transfer = UsbpAllocateTransfer(Device, 0, AllocationSize, 0);
  1219. if (Transfer == NULL) {
  1220. Status = STATUS_INSUFFICIENT_RESOURCES;
  1221. goto SendControlTransferEnd;
  1222. }
  1223. Transfer->Direction = TransferDirection;
  1224. Transfer->Length = TransferLength;
  1225. Transfer->Buffer = IoBuffer->Fragment[0].VirtualAddress;
  1226. Transfer->BufferPhysicalAddress = IoBuffer->Fragment[0].PhysicalAddress;
  1227. Transfer->BufferActualLength = IoBuffer->Fragment[0].Size;
  1228. //
  1229. // Submit the transfer and wait for it to complete.
  1230. //
  1231. Status = UsbSubmitSynchronousTransfer(Transfer);
  1232. if (!KSUCCESS(Status)) {
  1233. goto SendControlTransferEnd;
  1234. }
  1235. ASSERT(KSUCCESS(Transfer->Status));
  1236. //
  1237. // Copy the results into the caller's buffer.
  1238. //
  1239. ASSERT(Transfer->LengthTransferred >= sizeof(USB_SETUP_PACKET));
  1240. ASSERT(Transfer->LengthTransferred - sizeof(USB_SETUP_PACKET) <=
  1241. BufferLength);
  1242. if ((TransferDirection == UsbTransferDirectionIn) &&
  1243. (Transfer->LengthTransferred > sizeof(USB_SETUP_PACKET))) {
  1244. if (LengthTransferred != NULL) {
  1245. *LengthTransferred = Transfer->LengthTransferred -
  1246. sizeof(USB_SETUP_PACKET);
  1247. }
  1248. RtlCopyMemory(Buffer,
  1249. Transfer->Buffer + sizeof(USB_SETUP_PACKET),
  1250. Transfer->LengthTransferred - sizeof(USB_SETUP_PACKET));
  1251. }
  1252. Status = STATUS_SUCCESS;
  1253. SendControlTransferEnd:
  1254. if (Transfer != NULL) {
  1255. UsbDestroyTransfer(Transfer);
  1256. }
  1257. if (IoBuffer != NULL) {
  1258. MmFreeIoBuffer(IoBuffer);
  1259. }
  1260. return Status;
  1261. }
  1262. PUSB_TRANSFER
  1263. UsbpAllocateTransfer (
  1264. PUSB_DEVICE Device,
  1265. UCHAR EndpointNumber,
  1266. ULONG MaxTransferSize,
  1267. ULONG Flags
  1268. )
  1269. /*++
  1270. Routine Description:
  1271. This routine allocates a new USB transfer structure. This routine must be
  1272. used to allocate transfers.
  1273. Arguments:
  1274. Device - Supplies a pointer to the device the transfer will eventually be
  1275. submitted to. This must not be changed by the caller in the transfer
  1276. structure once set.
  1277. EndpointNumber - Supplies the endpoint number that the transfer will go to.
  1278. MaxTransferSize - Supplies the maximum length, in bytes, of the transfer.
  1279. Attempts to submit a transfer with lengths longer than this initialized
  1280. length will fail. Longer transfer sizes do require more resources as
  1281. they are split into subpackets, so try to be reasonable.
  1282. Flags - Supplies a bitfield of flags regarding the transaction. See
  1283. USB_TRANSFER_FLAG_* definitions.
  1284. Return Value:
  1285. Returns a pointer to the new USB transfer on success.
  1286. NULL when there are insufficient resources to complete the request.
  1287. --*/
  1288. {
  1289. ULONG AllocationSize;
  1290. PUSB_HOST_CREATE_TRANSFER CreateTransfer;
  1291. PUSB_HOST_DESTROY_TRANSFER DestroyTransfer;
  1292. PUSB_ENDPOINT Endpoint;
  1293. PVOID HostControllerContext;
  1294. BOOL ReleaseLock;
  1295. KSTATUS Status;
  1296. PUSB_TRANSFER_PRIVATE Transfer;
  1297. BOOL TransferCreated;
  1298. CreateTransfer = Device->Controller->Device.CreateTransfer;
  1299. DestroyTransfer = Device->Controller->Device.DestroyTransfer;
  1300. Endpoint = NULL;
  1301. HostControllerContext = Device->Controller->Device.HostControllerContext;
  1302. ReleaseLock = FALSE;
  1303. Transfer = NULL;
  1304. TransferCreated = FALSE;
  1305. //
  1306. // Add a reference to the device to account for the transfer. This is to
  1307. // potentially allow a driver to roll through the removal IRP destroying
  1308. // everything except for some pending transfer which depends on the USB
  1309. // core. The USB core device will get cleaned up when said transfer get
  1310. // destroyed, releasing this reference.
  1311. //
  1312. UsbpDeviceAddReference(Device);
  1313. //
  1314. // Find the endpoint associated with this transfer.
  1315. //
  1316. Endpoint = UsbpGetDeviceEndpoint(Device, EndpointNumber);
  1317. if (Endpoint == NULL) {
  1318. Status = STATUS_INVALID_PARAMETER;
  1319. goto AllocateTransferEnd;
  1320. }
  1321. //
  1322. // Allocate the transfer.
  1323. //
  1324. AllocationSize = sizeof(USB_TRANSFER_PRIVATE);
  1325. Transfer = MmAllocateNonPagedPool(AllocationSize, USB_CORE_ALLOCATION_TAG);
  1326. if (Transfer == NULL) {
  1327. Status = STATUS_INSUFFICIENT_RESOURCES;
  1328. goto AllocateTransferEnd;
  1329. }
  1330. RtlZeroMemory(Transfer, AllocationSize);
  1331. Transfer->Magic = USB_TRANSFER_INTERNAL_MAGIC;
  1332. Transfer->ReferenceCount = 1;
  1333. Transfer->Device = Device;
  1334. Transfer->Protected.DeviceAddress = Device->BusAddress;
  1335. Transfer->Protected.EndpointNumber = EndpointNumber;
  1336. Transfer->Protected.Type = Endpoint->Type;
  1337. Transfer->MaxTransferSize = MaxTransferSize;
  1338. Transfer->Endpoint = Endpoint;
  1339. Transfer->Protected.Public.Flags = Flags;
  1340. Transfer->Event = KeCreateEvent(NULL);
  1341. if (Transfer->Event == NULL) {
  1342. Status = STATUS_INSUFFICIENT_RESOURCES;
  1343. goto AllocateTransferEnd;
  1344. }
  1345. ASSERT(Transfer->State == TransferInvalid);
  1346. ASSERT(Transfer->CompletionListEntry.Next == NULL);
  1347. //
  1348. // Don't let a new transfer be created for a disconnected device.
  1349. //
  1350. KeAcquireQueuedLock(Device->Lock);
  1351. ReleaseLock = TRUE;
  1352. if (Device->Connected == FALSE) {
  1353. Status = STATUS_DEVICE_NOT_CONNECTED;
  1354. goto AllocateTransferEnd;
  1355. }
  1356. //
  1357. // Call into the host controller to allocate any of its needed structures.
  1358. //
  1359. Status = CreateTransfer(HostControllerContext,
  1360. Endpoint->HostControllerContext,
  1361. MaxTransferSize,
  1362. Flags,
  1363. &(Transfer->HostControllerContext));
  1364. if (!KSUCCESS(Status)) {
  1365. goto AllocateTransferEnd;
  1366. }
  1367. //
  1368. // Now that the transfer is successfully created, mark it as inactive and
  1369. // add it to the USB device's list of transfers.
  1370. //
  1371. Transfer->State = TransferInactive;
  1372. INSERT_BEFORE(&(Transfer->DeviceListEntry), &(Device->TransferList));
  1373. KeReleaseQueuedLock(Device->Lock);
  1374. ReleaseLock = FALSE;
  1375. TransferCreated = TRUE;
  1376. Status = STATUS_SUCCESS;
  1377. AllocateTransferEnd:
  1378. if (!KSUCCESS(Status)) {
  1379. if (Transfer != NULL) {
  1380. if (TransferCreated != FALSE) {
  1381. DestroyTransfer(HostControllerContext,
  1382. Endpoint->HostControllerContext,
  1383. Transfer->HostControllerContext);
  1384. }
  1385. if (Transfer->Event != NULL) {
  1386. KeDestroyEvent(Transfer->Event);
  1387. }
  1388. MmFreeNonPagedPool(Transfer);
  1389. Transfer = NULL;
  1390. }
  1391. if (ReleaseLock != FALSE) {
  1392. KeReleaseQueuedLock(Device->Lock);
  1393. }
  1394. UsbpDeviceReleaseReference(Device);
  1395. }
  1396. return (PUSB_TRANSFER)Transfer;
  1397. }
  1398. VOID
  1399. UsbpCancelAllTransfers (
  1400. PUSB_DEVICE Device
  1401. )
  1402. /*++
  1403. Routine Description:
  1404. This routine cancels all transfers for the given USB core device. The
  1405. device must be disconnected before calling into this routine.
  1406. Arguments:
  1407. Device - Supplies the core handle to the device whose transfers are
  1408. to be cancelled.
  1409. Return Value:
  1410. None.
  1411. --*/
  1412. {
  1413. PLIST_ENTRY CurrentEntry;
  1414. PUSB_TRANSFER_PRIVATE Transfer;
  1415. ASSERT(Device != NULL);
  1416. ASSERT(Device->Connected == FALSE);
  1417. ASSERT(KeGetRunLevel() == RunLevelLow);
  1418. //
  1419. // Loop through the transfers and add a reference to each. This way the
  1420. // device lock does not need to be held while going through the cancel
  1421. // process, potentially impeding a transfer's ability to fail resubmission.
  1422. //
  1423. KeAcquireQueuedLock(Device->Lock);
  1424. CurrentEntry = Device->TransferList.Next;
  1425. while (CurrentEntry != &(Device->TransferList)) {
  1426. Transfer = (PUSB_TRANSFER_PRIVATE)LIST_VALUE(CurrentEntry,
  1427. USB_TRANSFER_PRIVATE,
  1428. DeviceListEntry);
  1429. UsbTransferAddReference((PUSB_TRANSFER)Transfer);
  1430. CurrentEntry = CurrentEntry->Next;
  1431. }
  1432. //
  1433. // Release the lock. It is safe to proceed outside the lock because a
  1434. // reference has been added to each transfer to prevent deletion and
  1435. // because the device has been disconnected, preventing insertion.
  1436. //
  1437. KeReleaseQueuedLock(Device->Lock);
  1438. //
  1439. // Loop through the transfers again and cancel them all.
  1440. //
  1441. CurrentEntry = Device->TransferList.Next;
  1442. while (CurrentEntry != &(Device->TransferList)) {
  1443. Transfer = (PUSB_TRANSFER_PRIVATE)LIST_VALUE(CurrentEntry,
  1444. USB_TRANSFER_PRIVATE,
  1445. DeviceListEntry);
  1446. UsbpCancelTransfer(Transfer);
  1447. CurrentEntry = CurrentEntry->Next;
  1448. }
  1449. //
  1450. // Now wait on all transfers to enter the inactive state.
  1451. //
  1452. CurrentEntry = Device->TransferList.Next;
  1453. while (CurrentEntry != &(Device->TransferList)) {
  1454. Transfer = (PUSB_TRANSFER_PRIVATE)LIST_VALUE(CurrentEntry,
  1455. USB_TRANSFER_PRIVATE,
  1456. DeviceListEntry);
  1457. while (Transfer->State != TransferInactive) {
  1458. KeYield();
  1459. }
  1460. CurrentEntry = CurrentEntry->Next;
  1461. }
  1462. //
  1463. // Loop one last time, releasing the references. Be aware that this could
  1464. // be the last reference on some transfers, meaning the lock cannot be
  1465. // held because the release could trigger deletion.
  1466. //
  1467. CurrentEntry = Device->TransferList.Next;
  1468. while (CurrentEntry != &(Device->TransferList)) {
  1469. Transfer = (PUSB_TRANSFER_PRIVATE)LIST_VALUE(CurrentEntry,
  1470. USB_TRANSFER_PRIVATE,
  1471. DeviceListEntry);
  1472. CurrentEntry = CurrentEntry->Next;
  1473. UsbTransferReleaseReference((PUSB_TRANSFER)Transfer);
  1474. }
  1475. return;
  1476. }
  1477. KSTATUS
  1478. UsbpReadConfigurationDescriptors (
  1479. PUSB_DEVICE Device,
  1480. PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
  1481. )
  1482. /*++
  1483. Routine Description:
  1484. This routine attempts to read all configuration descriptors from the device.
  1485. Arguments:
  1486. Device - Supplies a pointer to the device to query.
  1487. DeviceDescriptor - Supplies a pointer to the device descriptor.
  1488. Return Value:
  1489. Status code.
  1490. --*/
  1491. {
  1492. PUSB_CONFIGURATION Configuration;
  1493. UCHAR ConfigurationCount;
  1494. UCHAR ConfigurationIndex;
  1495. KSTATUS OverallStatus;
  1496. KSTATUS Status;
  1497. OverallStatus = STATUS_SUCCESS;
  1498. ConfigurationCount = DeviceDescriptor->ConfigurationCount;
  1499. for (ConfigurationIndex = 0;
  1500. ConfigurationIndex < ConfigurationCount;
  1501. ConfigurationIndex += 1) {
  1502. Status = UsbpGetConfiguration(Device,
  1503. ConfigurationIndex,
  1504. TRUE,
  1505. &Configuration);
  1506. if (!KSUCCESS(Status)) {
  1507. OverallStatus = Status;
  1508. }
  1509. }
  1510. return OverallStatus;
  1511. }
  1512. USB_API
  1513. PVOID
  1514. UsbGetDeviceToken (
  1515. PUSB_DEVICE Device
  1516. )
  1517. /*++
  1518. Routine Description:
  1519. This routine returns the system device token associated with the given USB
  1520. device.
  1521. Arguments:
  1522. Device - Supplies a pointer to a USB device.
  1523. Return Value:
  1524. Returns a system device token.
  1525. --*/
  1526. {
  1527. return Device->Device;
  1528. }
  1529. KSTATUS
  1530. UsbpInitializeTransferCompletionQueue (
  1531. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue,
  1532. BOOL PrivateWorkQueue
  1533. )
  1534. /*++
  1535. Routine Description:
  1536. This routine initializes the given transfer completion queue.
  1537. Arguments:
  1538. CompletionQueue - Supplies a pointer to a USB transfer completion queue
  1539. that is to be initialized.
  1540. PrivateWorkQueue - Supplies a boolean indicating whether or not the
  1541. completion queue requires a private work queue for queuing its work
  1542. item.
  1543. Return Value:
  1544. Status code.
  1545. --*/
  1546. {
  1547. KSTATUS Status;
  1548. ULONG WorkQueueFlags;
  1549. RtlZeroMemory(CompletionQueue, sizeof(USB_TRANSFER_COMPLETION_QUEUE));
  1550. INITIALIZE_LIST_HEAD(&(CompletionQueue->CompletedTransfersList));
  1551. KeInitializeSpinLock(&(CompletionQueue->CompletedTransfersListLock));
  1552. if (PrivateWorkQueue != FALSE) {
  1553. WorkQueueFlags = WORK_QUEUE_FLAG_SUPPORT_DISPATCH_LEVEL;
  1554. CompletionQueue->WorkQueue = KeCreateWorkQueue(WorkQueueFlags,
  1555. "UsbCorePrivateWorker");
  1556. if (CompletionQueue->WorkQueue == NULL) {
  1557. Status = STATUS_INSUFFICIENT_RESOURCES;
  1558. goto InitializeTransferCompletionQueueEnd;
  1559. }
  1560. } else {
  1561. CompletionQueue->WorkQueue = UsbCoreWorkQueue;
  1562. }
  1563. ASSERT(CompletionQueue->WorkQueue != NULL);
  1564. CompletionQueue->WorkItem = KeCreateWorkItem(CompletionQueue->WorkQueue,
  1565. WorkPriorityNormal,
  1566. UsbpCompletedTransferWorker,
  1567. CompletionQueue,
  1568. USB_CORE_ALLOCATION_TAG);
  1569. if (CompletionQueue->WorkItem == NULL) {
  1570. Status = STATUS_INSUFFICIENT_RESOURCES;
  1571. goto InitializeTransferCompletionQueueEnd;
  1572. }
  1573. Status = STATUS_SUCCESS;
  1574. InitializeTransferCompletionQueueEnd:
  1575. if (!KSUCCESS(Status)) {
  1576. UsbpDestroyTransferCompletionQueue(CompletionQueue);
  1577. }
  1578. return Status;
  1579. }
  1580. VOID
  1581. UsbpDestroyTransferCompletionQueue (
  1582. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue
  1583. )
  1584. /*++
  1585. Routine Description:
  1586. This routine destroys the given transfer completion queue. It does not
  1587. release the completion queue's memory.
  1588. Arguments:
  1589. CompletionQueue - Supplies a pointer to a USB transfer completion queue
  1590. that is to be destroyed.
  1591. Return Value:
  1592. Status code.
  1593. --*/
  1594. {
  1595. if (CompletionQueue->WorkItem != NULL) {
  1596. KeDestroyWorkItem(CompletionQueue->WorkItem);
  1597. }
  1598. if ((CompletionQueue->WorkQueue != NULL) &&
  1599. (CompletionQueue->WorkQueue != UsbCoreWorkQueue)) {
  1600. KeDestroyWorkQueue(CompletionQueue->WorkQueue);
  1601. }
  1602. return;
  1603. }
  1604. VOID
  1605. UsbpProcessCompletedTransfer (
  1606. PUSB_TRANSFER_INTERNAL Transfer
  1607. )
  1608. /*++
  1609. Routine Description:
  1610. This routine processes the completed transfer. It will either signal
  1611. synchronous transfers or queue asynchronous transfers on the correct
  1612. transfer completion queue so that its callback routine can be completed at
  1613. low level. This routine is called at dispatch.
  1614. Arguments:
  1615. Transfer - Supplies a pointer to a completed transfer.
  1616. Return Value:
  1617. None.
  1618. --*/
  1619. {
  1620. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  1621. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue;
  1622. PUSB_HOST_CONTROLLER Controller;
  1623. ULONG FlushAlignment;
  1624. ULONG FlushLength;
  1625. RUNLEVEL OldRunLevel;
  1626. USB_TRANSFER_STATE OldState;
  1627. ULONG PrivateFlags;
  1628. BOOL QueueWorkItem;
  1629. KSTATUS Status;
  1630. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  1631. ASSERT(KeGetRunLevel() == RunLevelDispatch);
  1632. ASSERT(CompleteTransfer->CompletionListEntry.Next == NULL);
  1633. //
  1634. // For any transfer that read data (i.e. all but the out transfers),
  1635. // invalidate the data cache again so that the consumer reads the correct
  1636. // data.
  1637. //
  1638. if (Transfer->Public.Direction != UsbTransferDirectionOut) {
  1639. ASSERT((Transfer->Public.Direction == UsbTransferDirectionIn) ||
  1640. (Transfer->Public.Direction == UsbTransferBidirectional));
  1641. FlushAlignment = MmGetIoBufferAlignment();
  1642. ASSERT(POWER_OF_2(FlushAlignment) != FALSE);
  1643. FlushLength = ALIGN_RANGE_UP(Transfer->Public.LengthTransferred,
  1644. FlushAlignment);
  1645. MmFlushBufferForDataIn(Transfer->Public.Buffer, FlushLength);
  1646. }
  1647. //
  1648. // For synchronous transfers, fire the event.
  1649. //
  1650. PrivateFlags = CompleteTransfer->PrivateFlags;
  1651. if ((PrivateFlags & USB_TRANSFER_PRIVATE_SYNCHRONOUS) != 0) {
  1652. //
  1653. // Mark that the transfer is no longer in flight.
  1654. //
  1655. OldState = RtlAtomicCompareExchange32(&(CompleteTransfer->State),
  1656. TransferInactive,
  1657. TransferActive);
  1658. ASSERT(OldState == TransferActive);
  1659. KeSignalEvent(CompleteTransfer->Event, SignalOptionSignalAll);
  1660. //
  1661. // USB core is done with this transfer, so release the reference taken
  1662. // on submit.
  1663. //
  1664. UsbTransferReleaseReference((PUSB_TRANSFER)Transfer);
  1665. //
  1666. // Queue all non-synchronous transfers to handle the callback at low-level.
  1667. //
  1668. } else {
  1669. //
  1670. // If this is a paging device transfer, then use the paging device
  1671. // completion queue.
  1672. //
  1673. if ((Transfer->Public.Flags & USB_TRANSFER_FLAG_PAGING_DEVICE) != 0) {
  1674. ASSERT(UsbCorePagingCompletionQueue != NULL);
  1675. CompletionQueue = UsbCorePagingCompletionQueue;
  1676. //
  1677. // Otherwise use the controller's completion queue.
  1678. //
  1679. } else {
  1680. Controller = CompleteTransfer->Device->Controller;
  1681. CompletionQueue = &(Controller->TransferCompletionQueue);
  1682. }
  1683. //
  1684. // Add the transfer to the completion list and potentially queue the
  1685. // work item to empty the list.
  1686. //
  1687. OldRunLevel = UsbpAcquireCompletedTransfersLock(CompletionQueue);
  1688. //
  1689. // If the list is currently empty, then the work item needs to be
  1690. // queued to process this new insertion.
  1691. //
  1692. if (LIST_EMPTY(&(CompletionQueue->CompletedTransfersList)) != FALSE) {
  1693. QueueWorkItem = TRUE;
  1694. //
  1695. // If it is not empty, then the work item is already queued and the
  1696. // insertion below will be picked up.
  1697. //
  1698. } else {
  1699. QueueWorkItem = FALSE;
  1700. }
  1701. INSERT_BEFORE(&(CompleteTransfer->CompletionListEntry),
  1702. &(CompletionQueue->CompletedTransfersList));
  1703. if (QueueWorkItem != FALSE) {
  1704. Status = KeQueueWorkItem(CompletionQueue->WorkItem);
  1705. ASSERT(KSUCCESS(Status));
  1706. }
  1707. UsbpReleaseCompletedTransfersLock(CompletionQueue, OldRunLevel);
  1708. }
  1709. return;
  1710. }
  1711. USB_API
  1712. BOOL
  1713. UsbIsPolledIoSupported (
  1714. HANDLE UsbDeviceHandle
  1715. )
  1716. /*++
  1717. Routine Description:
  1718. This routine returns a boolean indicating whether or not the given USB
  1719. device's controller supports polled I/O mode. Polled I/O should only be
  1720. used in dire circumstances. That is, during system failure when a crash
  1721. dump file needs to be written over USB Mass Storage at high run level with
  1722. interrupts disabled.
  1723. Arguments:
  1724. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  1725. Return Value:
  1726. Returns a boolean indicating if polled I/O is supported (TRUE) or not
  1727. (FALSE).
  1728. --*/
  1729. {
  1730. PUSB_DEVICE Device;
  1731. Device = (PUSB_DEVICE)UsbDeviceHandle;
  1732. if (Device->Controller->Device.SubmitPolledTransfer != NULL) {
  1733. return TRUE;
  1734. }
  1735. return FALSE;
  1736. }
  1737. USB_API
  1738. KSTATUS
  1739. UsbResetEndpoint (
  1740. HANDLE UsbDeviceHandle,
  1741. UCHAR EndpointNumber
  1742. )
  1743. /*++
  1744. Routine Description:
  1745. This routine resets the given endpoint for the given USB device. This
  1746. includes resetting the data toggle to DATA 0.
  1747. Arguments:
  1748. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  1749. EndpointNumber - Supplies the number of the endpoint to be reset.
  1750. Return Value:
  1751. Status code.
  1752. --*/
  1753. {
  1754. PUSB_DEVICE Device;
  1755. PUSB_ENDPOINT Endpoint;
  1756. KSTATUS Status;
  1757. Device = (PUSB_DEVICE)UsbDeviceHandle;
  1758. Endpoint = UsbpGetDeviceEndpoint(Device, EndpointNumber);
  1759. if (Endpoint == NULL) {
  1760. Status = STATUS_INVALID_PARAMETER;
  1761. goto ResetEndpointEnd;
  1762. }
  1763. UsbpResetEndpoint(Device, Endpoint);
  1764. Status = STATUS_SUCCESS;
  1765. ResetEndpointEnd:
  1766. return Status;
  1767. }
  1768. USB_API
  1769. KSTATUS
  1770. UsbFlushEndpoint (
  1771. HANDLE UsbDeviceHandle,
  1772. UCHAR EndpointNumber,
  1773. PULONG TransferCount
  1774. )
  1775. /*++
  1776. Routine Description:
  1777. This routine flushes the given endpoint for the given USB device. This
  1778. includes busily waiting for all active transfers to complete. This is only
  1779. meant to be used at high run level when preparing to write a crash dump
  1780. file using USB Mass Storage.
  1781. Arguments:
  1782. UsbDeviceHandle - Supplies the handle returned when the device was opened.
  1783. EndpointNumber - Supplies the number of the endpoint to be reset.
  1784. TransferCount - Supplies a pointer that receives the total number of
  1785. transfers that were flushed.
  1786. Return Value:
  1787. Status code.
  1788. --*/
  1789. {
  1790. PUSB_DEVICE Device;
  1791. PUSB_ENDPOINT Endpoint;
  1792. KSTATUS Status;
  1793. ASSERT(KeGetRunLevel() == RunLevelHigh);
  1794. Device = (PUSB_DEVICE)UsbDeviceHandle;
  1795. Endpoint = UsbpGetDeviceEndpoint(Device, EndpointNumber);
  1796. if (Endpoint == NULL) {
  1797. Status = STATUS_INVALID_PARAMETER;
  1798. goto FlushEndpointEnd;
  1799. }
  1800. Status = UsbpFlushEndpoint(Device, Endpoint, TransferCount);
  1801. if (!KSUCCESS(Status)) {
  1802. goto FlushEndpointEnd;
  1803. }
  1804. FlushEndpointEnd:
  1805. return Status;
  1806. }
  1807. //
  1808. // --------------------------------------------------------- Internal Functions
  1809. //
  1810. KSTATUS
  1811. UsbpCancelTransfer (
  1812. PUSB_TRANSFER_PRIVATE Transfer
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. This routine cancels a USB transfer.
  1817. Arguments:
  1818. Transfer - Supplies a pointer to the transfer to cancel.
  1819. Return Value:
  1820. Status code.
  1821. --*/
  1822. {
  1823. PUSB_HOST_CANCEL_TRANSFER CancelTransfer;
  1824. PUSB_HOST_CONTROLLER Controller;
  1825. PUSB_ENDPOINT Endpoint;
  1826. KSTATUS Status;
  1827. Endpoint = Transfer->Endpoint;
  1828. Controller = Transfer->Device->Controller;
  1829. CancelTransfer = Controller->Device.CancelTransfer;
  1830. //
  1831. // Try to cancel the transfer. This only makes an attempt at cancelling
  1832. // the transfer and does not guarantee success or that the transfer is
  1833. // out of USB core's domain. The caller needs to handle the various failure
  1834. // cases. If the transfer is currently inactive, just return that the
  1835. // cancel is too early.
  1836. //
  1837. if (Transfer->State == TransferInactive) {
  1838. Status = STATUS_TOO_EARLY;
  1839. } else {
  1840. Status = CancelTransfer(Controller->Device.HostControllerContext,
  1841. Endpoint->HostControllerContext,
  1842. (PUSB_TRANSFER_INTERNAL)Transfer,
  1843. Transfer->HostControllerContext);
  1844. if (!KSUCCESS(Status)) {
  1845. ASSERT(Status == STATUS_TOO_LATE);
  1846. }
  1847. }
  1848. return Status;
  1849. }
  1850. VOID
  1851. UsbpDestroyTransfer (
  1852. PUSB_TRANSFER Transfer
  1853. )
  1854. /*++
  1855. Routine Description:
  1856. This routine destroys an allocated transfer. This transfer must not be
  1857. actively transferring.
  1858. Arguments:
  1859. Transfer - Supplies a pointer to the transfer to destroy.
  1860. Return Value:
  1861. None.
  1862. --*/
  1863. {
  1864. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  1865. PUSB_HOST_DESTROY_TRANSFER DestroyTransfer;
  1866. PUSB_HOST_CONTROLLER HostController;
  1867. PVOID HostControllerContext;
  1868. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  1869. ASSERT(CompleteTransfer->CompletionListEntry.Next == NULL);
  1870. ASSERT(CompleteTransfer->Magic == USB_TRANSFER_INTERNAL_MAGIC);
  1871. ASSERT(CompleteTransfer->State == TransferInactive);
  1872. //
  1873. // Remove the transfer from its USB device's list of transfers.
  1874. //
  1875. KeAcquireQueuedLock(CompleteTransfer->Device->Lock);
  1876. LIST_REMOVE(&(CompleteTransfer->DeviceListEntry));
  1877. KeReleaseQueuedLock(CompleteTransfer->Device->Lock);
  1878. //
  1879. // Call the host controller to destroy the transfer.
  1880. //
  1881. HostController = CompleteTransfer->Device->Controller;
  1882. DestroyTransfer = HostController->Device.DestroyTransfer;
  1883. HostControllerContext = HostController->Device.HostControllerContext;
  1884. DestroyTransfer(HostControllerContext,
  1885. CompleteTransfer->Endpoint->HostControllerContext,
  1886. CompleteTransfer->HostControllerContext);
  1887. KeDestroyEvent(CompleteTransfer->Event);
  1888. //
  1889. // Releae the reference the transfer took on the device.
  1890. //
  1891. UsbpDeviceReleaseReference(CompleteTransfer->Device);
  1892. //
  1893. // Destroy the transfer itself.
  1894. //
  1895. MmFreeNonPagedPool(CompleteTransfer);
  1896. return;
  1897. }
  1898. KSTATUS
  1899. UsbpGetConfiguration (
  1900. PUSB_DEVICE Device,
  1901. UCHAR ConfigurationNumber,
  1902. BOOL NumberIsIndex,
  1903. PUSB_CONFIGURATION *Configuration
  1904. )
  1905. /*++
  1906. Routine Description:
  1907. This routine gets a configuration out of the given device. This routine
  1908. will send a blocking request to the device. This routine must be called at
  1909. low level.
  1910. Arguments:
  1911. Device - Supplies a pointer to the device.
  1912. ConfigurationNumber - Supplies the index or configuration value of the
  1913. configuration to get.
  1914. NumberIsIndex - Supplies a boolean indicating whether the configuration
  1915. number is an index (TRUE) or a specific configuration value (FALSE).
  1916. Configuration - Supplies a pointer where a pointer to the created
  1917. configuration will be returned.
  1918. Return Value:
  1919. Status code.
  1920. --*/
  1921. {
  1922. ULONG AllocationSize;
  1923. PUCHAR BufferPointer;
  1924. PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
  1925. UCHAR ConfigurationValue;
  1926. PUSB_CONFIGURATION CurrentConfiguration;
  1927. PLIST_ENTRY CurrentEntry;
  1928. PUSB_INTERFACE CurrentInterface;
  1929. PUSB_CONFIGURATION_DESCRIPTION Description;
  1930. UCHAR DescriptorLength;
  1931. UCHAR DescriptorType;
  1932. PUSB_ENDPOINT_DESCRIPTION Endpoint;
  1933. ULONG EndpointCount;
  1934. ULONG InterfaceCount;
  1935. ULONG Length;
  1936. ULONG LengthTransferred;
  1937. PUCHAR NewBufferPointer;
  1938. USB_SETUP_PACKET SetupPacket;
  1939. KSTATUS Status;
  1940. USHORT TotalLength;
  1941. PUSB_UNKNOWN_DESCRIPTION Unknown;
  1942. ULONG UnknownCount;
  1943. ULONG UnknownSize;
  1944. *Configuration = NULL;
  1945. ConfigurationDescriptor = NULL;
  1946. CurrentConfiguration = NULL;
  1947. ASSERT(KeGetRunLevel() == RunLevelLow);
  1948. KeAcquireQueuedLock(Device->ConfigurationLock);
  1949. //
  1950. // First look to see if the configuration already exists.
  1951. //
  1952. CurrentEntry = Device->ConfigurationList.Next;
  1953. while (CurrentEntry != &(Device->ConfigurationList)) {
  1954. CurrentConfiguration = LIST_VALUE(CurrentEntry,
  1955. USB_CONFIGURATION,
  1956. ListEntry);
  1957. //
  1958. // Match on either the index or the value.
  1959. //
  1960. Description = &(CurrentConfiguration->Description);
  1961. if (NumberIsIndex != FALSE) {
  1962. if (ConfigurationNumber == Description->Index) {
  1963. break;
  1964. }
  1965. } else {
  1966. ConfigurationValue = Description->Descriptor.ConfigurationValue;
  1967. if (ConfigurationNumber == ConfigurationValue) {
  1968. break;
  1969. }
  1970. }
  1971. CurrentEntry = CurrentEntry->Next;
  1972. }
  1973. if (CurrentEntry != &(Device->ConfigurationList)) {
  1974. Status = STATUS_SUCCESS;
  1975. goto GetConfigurationEnd;
  1976. }
  1977. CurrentConfiguration = NULL;
  1978. //
  1979. // The USB spec does not support requesting descriptors by value, so this
  1980. // had better be a "by-index" request.
  1981. //
  1982. ASSERT(NumberIsIndex != FALSE);
  1983. //
  1984. // Allocate space for the entire descriptor, which includes all of the
  1985. // interface and endpoint descriptors (hopefully).
  1986. //
  1987. ConfigurationDescriptor = MmAllocatePagedPool(
  1988. USB_INITIAL_CONFIGURATION_LENGTH,
  1989. USB_CORE_ALLOCATION_TAG);
  1990. if (ConfigurationDescriptor == NULL) {
  1991. Status = STATUS_INSUFFICIENT_RESOURCES;
  1992. goto GetConfigurationEnd;
  1993. }
  1994. //
  1995. // Read in the configuration descriptor.
  1996. //
  1997. RtlZeroMemory(&SetupPacket, sizeof(USB_SETUP_PACKET));
  1998. SetupPacket.RequestType = USB_SETUP_REQUEST_TO_HOST |
  1999. USB_SETUP_REQUEST_STANDARD |
  2000. USB_SETUP_REQUEST_DEVICE_RECIPIENT;
  2001. SetupPacket.Request = USB_DEVICE_REQUEST_GET_DESCRIPTOR;
  2002. SetupPacket.Value = (UsbDescriptorTypeConfiguration << 8) |
  2003. ConfigurationNumber;
  2004. SetupPacket.Index = 0;
  2005. SetupPacket.Length = USB_INITIAL_CONFIGURATION_LENGTH;
  2006. Status = UsbSendControlTransfer(Device,
  2007. UsbTransferDirectionIn,
  2008. &SetupPacket,
  2009. ConfigurationDescriptor,
  2010. USB_INITIAL_CONFIGURATION_LENGTH,
  2011. &LengthTransferred);
  2012. if (!KSUCCESS(Status)) {
  2013. goto GetConfigurationEnd;
  2014. }
  2015. if (LengthTransferred < sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
  2016. Status = STATUS_INVALID_CONFIGURATION;
  2017. goto GetConfigurationEnd;
  2018. }
  2019. //
  2020. // If the buffer was too small, allocate a bigger one and read it in again.
  2021. //
  2022. TotalLength = ConfigurationDescriptor->TotalLength;
  2023. if (TotalLength > USB_INITIAL_CONFIGURATION_LENGTH) {
  2024. MmFreePagedPool(ConfigurationDescriptor);
  2025. ConfigurationDescriptor = MmAllocatePagedPool(TotalLength,
  2026. USB_CORE_ALLOCATION_TAG);
  2027. if (ConfigurationDescriptor == NULL) {
  2028. Status = STATUS_INSUFFICIENT_RESOURCES;
  2029. goto GetConfigurationEnd;
  2030. }
  2031. SetupPacket.Length = TotalLength;
  2032. Status = UsbSendControlTransfer(Device,
  2033. UsbTransferDirectionIn,
  2034. &SetupPacket,
  2035. ConfigurationDescriptor,
  2036. TotalLength,
  2037. &LengthTransferred);
  2038. if (!KSUCCESS(Status)) {
  2039. goto GetConfigurationEnd;
  2040. }
  2041. if (LengthTransferred != TotalLength) {
  2042. Status = STATUS_INVALID_CONFIGURATION;
  2043. goto GetConfigurationEnd;
  2044. }
  2045. }
  2046. //
  2047. // Count the number of interfaces and endpoints to determine the allocation
  2048. // size for the description.
  2049. //
  2050. InterfaceCount = 0;
  2051. EndpointCount = 0;
  2052. UnknownCount = 0;
  2053. UnknownSize = 0;
  2054. Length = ConfigurationDescriptor->Length;
  2055. BufferPointer = (PUCHAR)ConfigurationDescriptor +
  2056. ConfigurationDescriptor->Length;
  2057. while (Length + 1 < LengthTransferred) {
  2058. //
  2059. // Get this descriptor and count it.
  2060. //
  2061. DescriptorLength = *BufferPointer;
  2062. DescriptorType = *(BufferPointer + 1);
  2063. if (DescriptorType == UsbDescriptorTypeInterface) {
  2064. InterfaceCount += 1;
  2065. } else if (DescriptorType == UsbDescriptorTypeEndpoint) {
  2066. EndpointCount += 1;
  2067. } else {
  2068. UnknownCount += 1;
  2069. UnknownSize += DescriptorLength + sizeof(ULONGLONG) - 1;
  2070. }
  2071. //
  2072. // Move on to the next descriptor.
  2073. //
  2074. BufferPointer += DescriptorLength;
  2075. Length += DescriptorLength;
  2076. }
  2077. //
  2078. // Now allocate space for the configuration description.
  2079. //
  2080. AllocationSize = sizeof(USB_CONFIGURATION) +
  2081. (InterfaceCount * sizeof(USB_INTERFACE)) +
  2082. (EndpointCount * sizeof(USB_ENDPOINT_DESCRIPTION)) +
  2083. (UnknownCount * sizeof(USB_UNKNOWN_DESCRIPTION)) +
  2084. UnknownSize;
  2085. CurrentConfiguration = MmAllocatePagedPool(AllocationSize,
  2086. USB_CORE_ALLOCATION_TAG);
  2087. if (CurrentConfiguration == NULL) {
  2088. Status = STATUS_INSUFFICIENT_RESOURCES;
  2089. goto GetConfigurationEnd;
  2090. }
  2091. RtlZeroMemory(CurrentConfiguration, AllocationSize);
  2092. CurrentConfiguration->Description.Index = ConfigurationNumber;
  2093. RtlCopyMemory(&(CurrentConfiguration->Description.Descriptor),
  2094. ConfigurationDescriptor,
  2095. sizeof(USB_CONFIGURATION_DESCRIPTOR));
  2096. INITIALIZE_LIST_HEAD(
  2097. &(CurrentConfiguration->Description.InterfaceListHead));
  2098. //
  2099. // Go through the descriptor again and create analogous structures for them.
  2100. //
  2101. CurrentInterface = NULL;
  2102. Length = ConfigurationDescriptor->Length;
  2103. BufferPointer = (PUCHAR)ConfigurationDescriptor +
  2104. ConfigurationDescriptor->Length;
  2105. NewBufferPointer = (PUCHAR)(CurrentConfiguration + 1);
  2106. while (Length + 1 < LengthTransferred) {
  2107. //
  2108. // Get this descriptor and create the analogous structure.
  2109. //
  2110. DescriptorLength = *BufferPointer;
  2111. DescriptorType = *(BufferPointer + 1);
  2112. if (Length + DescriptorLength > LengthTransferred) {
  2113. Status = STATUS_INVALID_CONFIGURATION;
  2114. goto GetConfigurationEnd;
  2115. }
  2116. if (DescriptorType == UsbDescriptorTypeInterface) {
  2117. CurrentInterface = (PUSB_INTERFACE)NewBufferPointer;
  2118. if (DescriptorLength < sizeof(USB_INTERFACE_DESCRIPTOR)) {
  2119. Status = STATUS_INVALID_CONFIGURATION;
  2120. goto GetConfigurationEnd;
  2121. }
  2122. RtlCopyMemory(&(CurrentInterface->Description.Descriptor),
  2123. BufferPointer,
  2124. sizeof(USB_INTERFACE_DESCRIPTOR));
  2125. INITIALIZE_LIST_HEAD(
  2126. &(CurrentInterface->Description.EndpointListHead));
  2127. INITIALIZE_LIST_HEAD(
  2128. &(CurrentInterface->Description.UnknownListHead));
  2129. INITIALIZE_LIST_HEAD(&(CurrentInterface->EndpointList));
  2130. INSERT_BEFORE(
  2131. &(CurrentInterface->Description.ListEntry),
  2132. &(CurrentConfiguration->Description.InterfaceListHead));
  2133. NewBufferPointer = (PUCHAR)(CurrentInterface + 1);
  2134. } else if (DescriptorType == UsbDescriptorTypeEndpoint) {
  2135. //
  2136. // If an endpoint came with no interface, that's illegal.
  2137. //
  2138. if (CurrentInterface == NULL) {
  2139. Status = STATUS_INVALID_CONFIGURATION;
  2140. goto GetConfigurationEnd;
  2141. }
  2142. Endpoint = (PUSB_ENDPOINT_DESCRIPTION)NewBufferPointer;
  2143. if (DescriptorLength < sizeof(USB_ENDPOINT_DESCRIPTOR)) {
  2144. Status = STATUS_INVALID_CONFIGURATION;
  2145. goto GetConfigurationEnd;
  2146. }
  2147. RtlCopyMemory(&(Endpoint->Descriptor),
  2148. BufferPointer,
  2149. sizeof(USB_ENDPOINT_DESCRIPTOR));
  2150. INSERT_BEFORE(&(Endpoint->ListEntry),
  2151. &(CurrentInterface->Description.EndpointListHead));
  2152. NewBufferPointer = (PUCHAR)(Endpoint + 1);
  2153. //
  2154. // Add an unknown descriptor to the interface if there is one. HID
  2155. // descriptors are nestled in this way.
  2156. //
  2157. } else {
  2158. if (CurrentInterface != NULL) {
  2159. Unknown = (PUSB_UNKNOWN_DESCRIPTION)NewBufferPointer;
  2160. Unknown->Descriptor = (PUCHAR)(Unknown + 1);
  2161. RtlCopyMemory(Unknown->Descriptor,
  2162. BufferPointer,
  2163. DescriptorLength);
  2164. INSERT_BEFORE(&(Unknown->ListEntry),
  2165. &(CurrentInterface->Description.UnknownListHead));
  2166. NewBufferPointer =
  2167. ALIGN_POINTER_UP(Unknown->Descriptor + DescriptorLength,
  2168. sizeof(ULONGLONG));
  2169. }
  2170. }
  2171. //
  2172. // Move on to the next descriptor.
  2173. //
  2174. BufferPointer += DescriptorLength;
  2175. Length += DescriptorLength;
  2176. }
  2177. ASSERT((UINTN)NewBufferPointer - (UINTN)CurrentConfiguration <=
  2178. AllocationSize);
  2179. //
  2180. // Insert the new configuration onto the global list to cache it for
  2181. // future calls.
  2182. //
  2183. INSERT_BEFORE(&(CurrentConfiguration->ListEntry),
  2184. &(Device->ConfigurationList));
  2185. GetConfigurationEnd:
  2186. KeReleaseQueuedLock(Device->ConfigurationLock);
  2187. if (!KSUCCESS(Status)) {
  2188. if (CurrentConfiguration != NULL) {
  2189. MmFreePagedPool(CurrentConfiguration);
  2190. CurrentConfiguration = NULL;
  2191. }
  2192. }
  2193. if (ConfigurationDescriptor != NULL) {
  2194. MmFreePagedPool(ConfigurationDescriptor);
  2195. }
  2196. *Configuration = CurrentConfiguration;
  2197. return Status;
  2198. }
  2199. KSTATUS
  2200. UsbpSubmitTransfer (
  2201. PUSB_TRANSFER Transfer,
  2202. ULONG PrivateFlags,
  2203. BOOL PolledMode
  2204. )
  2205. /*++
  2206. Routine Description:
  2207. This routine submits a USB transfer. The routine returns immediately,
  2208. indicating only whether the transfer was submitted successfully. When the
  2209. transfer actually completes, the callback routine will be called.
  2210. Arguments:
  2211. Transfer - Supplies a pointer to the transfer to destroy.
  2212. PrivateFlags - Supplies an optional bitfield of private flags regarding the
  2213. transfer. See USB_TRANSFER_PRIVATE_* definitions.
  2214. PolledMode - Supplies a boolean indicating whether the I/O should be done
  2215. in polled mode or not. This is reserved for I/O paths after a critical
  2216. system error.
  2217. Return Value:
  2218. STATUS_SUCCESS if the transfer was submitted to the USB host controller's
  2219. queue.
  2220. STATUS_INVALID_PARAMETER if one or more of the transfer fields is not
  2221. properly filled out.
  2222. Failing status codes if the request could not be submitted.
  2223. --*/
  2224. {
  2225. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  2226. PUSB_HOST_CONTROLLER Controller;
  2227. PUSB_DEVICE Device;
  2228. PUSB_ENDPOINT Endpoint;
  2229. ULONG FlushAlignment;
  2230. ULONG FlushLength;
  2231. USB_TRANSFER_STATE OriginalState;
  2232. BOOL PacketQueued;
  2233. BOOL ReleaseDeviceLock;
  2234. PUSB_SETUP_PACKET Setup;
  2235. KSTATUS Status;
  2236. PUSB_HOST_SUBMIT_TRANSFER SubmitTransfer;
  2237. ASSERT(Transfer != NULL);
  2238. CompleteTransfer = (PUSB_TRANSFER_PRIVATE)Transfer;
  2239. Endpoint = CompleteTransfer->Endpoint;
  2240. Controller = CompleteTransfer->Device->Controller;
  2241. Device = (PUSB_DEVICE)CompleteTransfer->Device;
  2242. PacketQueued = FALSE;
  2243. ReleaseDeviceLock = FALSE;
  2244. //
  2245. // Reference the transfer.
  2246. //
  2247. UsbTransferAddReference(Transfer);
  2248. //
  2249. // Callers are not allowed to allocate their own transfer structures, nor
  2250. // are they allowed to resubmit packets that have not completed.
  2251. //
  2252. if (CompleteTransfer->Magic != USB_TRANSFER_INTERNAL_MAGIC) {
  2253. ASSERT(FALSE);
  2254. Transfer->Error = UsbErrorTransferAllocatedIncorrectly;
  2255. Status = STATUS_INVALID_PARAMETER;
  2256. goto SubmitTransferEnd;
  2257. }
  2258. //
  2259. // Also fail if a transfer is submitted while it is still in-flight. It
  2260. // should either be inactive or in the middle of the callback.
  2261. //
  2262. if (CompleteTransfer->State == TransferActive) {
  2263. ASSERT(FALSE);
  2264. Transfer->Error = UsbErrorTransferSubmittedWhileStillActive;
  2265. Status = STATUS_RESOURCE_IN_USE;
  2266. goto SubmitTransferEnd;
  2267. }
  2268. ASSERT(CompleteTransfer->CompletionListEntry.Next == NULL);
  2269. //
  2270. // Validate the transfer.
  2271. //
  2272. if ((Transfer->Length == 0) ||
  2273. (Transfer->Length > CompleteTransfer->MaxTransferSize) ||
  2274. (Transfer->Buffer == NULL) ||
  2275. (Transfer->BufferPhysicalAddress == INVALID_PHYSICAL_ADDRESS) ||
  2276. (Transfer->BufferActualLength < Transfer->Length) ||
  2277. ((Transfer->Direction != UsbTransferDirectionIn) &&
  2278. (Transfer->Direction != UsbTransferDirectionOut))) {
  2279. ASSERT(FALSE);
  2280. Transfer->Error = UsbErrorTransferIncorrectlyFilledOut;
  2281. Status = STATUS_INVALID_PARAMETER;
  2282. goto SubmitTransferEnd;
  2283. }
  2284. if ((PrivateFlags & USB_TRANSFER_PRIVATE_SYNCHRONOUS) != 0) {
  2285. CompleteTransfer->PrivateFlags |= USB_TRANSFER_PRIVATE_SYNCHRONOUS;
  2286. } else {
  2287. CompleteTransfer->PrivateFlags &= ~USB_TRANSFER_PRIVATE_SYNCHRONOUS;
  2288. if (Transfer->CallbackRoutine == NULL) {
  2289. Transfer->Error = UsbErrorTransferIncorrectlyFilledOut;
  2290. Status = STATUS_INVALID_PARAMETER;
  2291. goto SubmitTransferEnd;
  2292. }
  2293. }
  2294. Transfer->Status = STATUS_NOT_STARTED;
  2295. Transfer->Error = UsbErrorTransferNotStarted;
  2296. Transfer->LengthTransferred = 0;
  2297. if (PolledMode == FALSE) {
  2298. SubmitTransfer = Controller->Device.SubmitTransfer;
  2299. ASSERT(SubmitTransfer != NULL);
  2300. } else {
  2301. SubmitTransfer = Controller->Device.SubmitPolledTransfer;
  2302. if (SubmitTransfer == NULL) {
  2303. Status = STATUS_NOT_SUPPORTED;
  2304. goto SubmitTransferEnd;
  2305. }
  2306. }
  2307. //
  2308. // Clean the data buffer in preparation for the USB controller doing DMA
  2309. // to/from it. Control transfers always have an outgoing portion.
  2310. //
  2311. FlushAlignment = MmGetIoBufferAlignment();
  2312. ASSERT(POWER_OF_2(FlushAlignment) != FALSE);
  2313. FlushLength = ALIGN_RANGE_UP(Transfer->Length, FlushAlignment);
  2314. if ((ALIGN_RANGE_DOWN((UINTN)Transfer->Buffer, FlushAlignment) !=
  2315. (UINTN)Transfer->Buffer) ||
  2316. (FlushLength > Transfer->BufferActualLength)) {
  2317. ASSERT(FALSE);
  2318. Transfer->Error = UsbErrorTransferBufferNotAligned;
  2319. Status = STATUS_INVALID_PARAMETER;
  2320. Transfer->Status = Status;
  2321. goto SubmitTransferEnd;
  2322. }
  2323. //
  2324. // Print out any debug information. The transfer isn't guaranteed to be
  2325. // submitted after this point, but this touches the transfer buffer, which
  2326. // needs to be flushed and then not touched.
  2327. //
  2328. if ((UsbDebugFlags & USB_DEBUG_TRANSFERS) != 0) {
  2329. if ((UsbDebugDeviceAddress == 0) ||
  2330. (UsbDebugDeviceAddress ==
  2331. CompleteTransfer->Protected.DeviceAddress)) {
  2332. ASSERT(Transfer->Direction < UsbTransferDirectionCount);
  2333. ASSERT(CompleteTransfer->Protected.Type < UsbTransferTypeCount);
  2334. RtlDebugPrint(
  2335. "USB: Transfer (0x%08x) %s dev %d, EP%x, %s, "
  2336. "Buffer 0x%x, Length 0x%x\n",
  2337. Transfer,
  2338. UsbTransferDirectionStrings[Transfer->Direction],
  2339. CompleteTransfer->Protected.DeviceAddress,
  2340. CompleteTransfer->Protected.EndpointNumber,
  2341. UsbTransferTypeStrings[CompleteTransfer->Protected.Type],
  2342. Transfer->Buffer,
  2343. Transfer->Length);
  2344. if (CompleteTransfer->Protected.Type == UsbTransferTypeControl) {
  2345. ASSERT(Transfer->Length >= sizeof(USB_SETUP_PACKET));
  2346. Setup = Transfer->Buffer;
  2347. RtlDebugPrint("USB: RequestType 0x%x, Request 0x%x, "
  2348. "Value 0x%x, Index 0x%x, Length 0x%x\n",
  2349. Setup->RequestType,
  2350. Setup->Request,
  2351. Setup->Value,
  2352. Setup->Index,
  2353. Setup->Length);
  2354. }
  2355. }
  2356. }
  2357. //
  2358. // Flush the transfer buffer. Do not access the buffer beyond this point.
  2359. //
  2360. if (CompleteTransfer->Endpoint->Type == UsbTransferTypeControl) {
  2361. if (Transfer->Direction == UsbTransferDirectionOut) {
  2362. MmFlushBufferForDataOut(Transfer->Buffer, FlushLength);
  2363. } else {
  2364. MmFlushBufferForDataIo(Transfer->Buffer, FlushLength);
  2365. }
  2366. //
  2367. // Bulk, interrupt, and isochronous transfers really only go the direction
  2368. // they claim.
  2369. //
  2370. } else {
  2371. if (Transfer->Direction == UsbTransferDirectionOut) {
  2372. MmFlushBufferForDataOut(Transfer->Buffer, FlushLength);
  2373. } else {
  2374. ASSERT(Transfer->Direction == UsbTransferDirectionIn);
  2375. MmFlushBufferForDataIn(Transfer->Buffer, FlushLength);
  2376. }
  2377. }
  2378. //
  2379. // Acquire the USB device's lock to check the status. Transfers should not
  2380. // be submitted to disconnected devices.
  2381. //
  2382. if (PolledMode == FALSE) {
  2383. KeAcquireQueuedLock(Device->Lock);
  2384. ReleaseDeviceLock = TRUE;
  2385. }
  2386. if (Device->Connected == FALSE) {
  2387. Transfer->Error = UsbErrorTransferDeviceNotConnected;
  2388. Status = STATUS_DEVICE_NOT_CONNECTED;
  2389. goto SubmitTransferEnd;
  2390. }
  2391. //
  2392. // Update the transfer state to 'active' before submission to the host
  2393. // controller. This could be a transition from either the callback state
  2394. // or the inactive state.
  2395. //
  2396. OriginalState = RtlAtomicCompareExchange32(&(CompleteTransfer->State),
  2397. TransferActive,
  2398. TransferInCallback);
  2399. if (OriginalState != TransferInCallback) {
  2400. OriginalState = RtlAtomicCompareExchange32(&(CompleteTransfer->State),
  2401. TransferActive,
  2402. TransferInactive);
  2403. if (OriginalState != TransferInactive) {
  2404. KeCrashSystem(CRASH_USB_ERROR,
  2405. UsbErrorTransferSubmittedWhileStillActive,
  2406. (UINTN)Transfer,
  2407. CompleteTransfer->State,
  2408. 0);
  2409. }
  2410. }
  2411. //
  2412. // Submit the transfer to the host controller.
  2413. //
  2414. Status = SubmitTransfer(Controller->Device.HostControllerContext,
  2415. Endpoint->HostControllerContext,
  2416. &(CompleteTransfer->Protected),
  2417. CompleteTransfer->HostControllerContext);
  2418. if (!KSUCCESS(Status)) {
  2419. Transfer->Error = UsbErrorTransferFailedToSubmit;
  2420. //
  2421. // Flip the transfer state to inactive, always.
  2422. //
  2423. OriginalState = RtlAtomicCompareExchange32(&(CompleteTransfer->State),
  2424. TransferInactive,
  2425. TransferActive);
  2426. ASSERT(OriginalState == TransferActive);
  2427. goto SubmitTransferEnd;
  2428. }
  2429. if (PolledMode == FALSE) {
  2430. KeReleaseQueuedLock(Device->Lock);
  2431. ReleaseDeviceLock = FALSE;
  2432. }
  2433. PacketQueued = TRUE;
  2434. Status = STATUS_SUCCESS;
  2435. SubmitTransferEnd:
  2436. if (!KSUCCESS(Status)) {
  2437. //
  2438. // Release the device lock, if necessary.
  2439. //
  2440. if (ReleaseDeviceLock != FALSE) {
  2441. ASSERT(PolledMode == FALSE);
  2442. KeReleaseQueuedLock(Device->Lock);
  2443. }
  2444. //
  2445. // Report transfer failures.
  2446. //
  2447. if ((UsbDebugFlags & (USB_DEBUG_TRANSFERS | USB_DEBUG_ERRORS)) != 0) {
  2448. if ((UsbDebugDeviceAddress == 0) ||
  2449. (UsbDebugDeviceAddress ==
  2450. CompleteTransfer->Protected.DeviceAddress)) {
  2451. RtlDebugPrint(
  2452. "USB: Submit failed, transfer (0x%08x) %s "
  2453. "dev %d, EP%x, %s, Buffer 0x%x, Len 0x%x. Status %d\n",
  2454. Transfer,
  2455. UsbTransferDirectionStrings[Transfer->Direction],
  2456. CompleteTransfer->Protected.DeviceAddress,
  2457. CompleteTransfer->Protected.EndpointNumber,
  2458. UsbTransferTypeStrings[CompleteTransfer->Protected.Type],
  2459. Transfer->Buffer,
  2460. Transfer->Length,
  2461. Status);
  2462. }
  2463. }
  2464. //
  2465. // Upon failure, cancel the transfer if it was submitted. This will
  2466. // modify the transfer state. Also, it could fail if the transfer went
  2467. // through very quickly. This, however, is not currently a valid error
  2468. // path - just future proofing.
  2469. //
  2470. if (PacketQueued != FALSE) {
  2471. UsbCancelTransfer(Transfer, TRUE);
  2472. //
  2473. // Relese the reference on failure. If the cancel path was taken, then
  2474. // the reference will be released after the callback. Also set the
  2475. // transfer status here; the cancel path does that as well.
  2476. //
  2477. } else {
  2478. Transfer->Status = Status;
  2479. UsbTransferReleaseReference(Transfer);
  2480. }
  2481. }
  2482. return Status;
  2483. }
  2484. KSTATUS
  2485. UsbpCreateEndpointsForInterface (
  2486. PUSB_DEVICE Device,
  2487. PUSB_INTERFACE Interface
  2488. )
  2489. /*++
  2490. Routine Description:
  2491. This routine creates endpoints for the given interface.
  2492. Arguments:
  2493. Device - Supplies a pointer to the device owning the interface and
  2494. endpoints.
  2495. Interface - Supplies a pointer to the interface to create endpoints for.
  2496. Return Value:
  2497. Status code.
  2498. --*/
  2499. {
  2500. UCHAR Attributes;
  2501. PLIST_ENTRY CurrentEntry;
  2502. USB_TRANSFER_DIRECTION Direction;
  2503. PUSB_ENDPOINT Endpoint;
  2504. PUSB_ENDPOINT_DESCRIPTION EndpointDescription;
  2505. UCHAR EndpointNumber;
  2506. ULONG MaxPacketSize;
  2507. ULONG PollRate;
  2508. KSTATUS Status;
  2509. USB_TRANSFER_TYPE Type;
  2510. //
  2511. // Loop through all the endpoint descriptions.
  2512. //
  2513. CurrentEntry = Interface->Description.EndpointListHead.Next;
  2514. while (CurrentEntry != &(Interface->Description.EndpointListHead)) {
  2515. EndpointDescription = LIST_VALUE(CurrentEntry,
  2516. USB_ENDPOINT_DESCRIPTION,
  2517. ListEntry);
  2518. CurrentEntry = CurrentEntry->Next;
  2519. PollRate = 0;
  2520. //
  2521. // Get the endpoint number.
  2522. //
  2523. EndpointNumber = EndpointDescription->Descriptor.EndpointAddress;
  2524. //
  2525. // Get the endpoint type.
  2526. //
  2527. Attributes = EndpointDescription->Descriptor.Attributes;
  2528. switch (Attributes & USB_ENDPOINT_ATTRIBUTES_TYPE_MASK) {
  2529. case USB_ENDPOINT_ATTRIBUTES_TYPE_CONTROL:
  2530. Type = UsbTransferTypeControl;
  2531. break;
  2532. case USB_ENDPOINT_ATTRIBUTES_TYPE_ISOCHRONOUS:
  2533. Type = UsbTransferTypeIsochronous;
  2534. PollRate = EndpointDescription->Descriptor.Interval;
  2535. break;
  2536. case USB_ENDPOINT_ATTRIBUTES_TYPE_BULK:
  2537. Type = UsbTransferTypeBulk;
  2538. if ((EndpointNumber & USB_ENDPOINT_ADDRESS_DIRECTION_IN) == 0) {
  2539. PollRate = EndpointDescription->Descriptor.Interval;
  2540. }
  2541. break;
  2542. case USB_ENDPOINT_ATTRIBUTES_TYPE_INTERRUPT:
  2543. default:
  2544. Type = UsbTransferTypeInterrupt;
  2545. PollRate = EndpointDescription->Descriptor.Interval;
  2546. break;
  2547. }
  2548. //
  2549. // Get the direction.
  2550. //
  2551. if (Type == UsbTransferTypeControl) {
  2552. Direction = UsbTransferBidirectional;
  2553. } else {
  2554. Direction = UsbTransferDirectionOut;
  2555. if ((EndpointNumber & USB_ENDPOINT_ADDRESS_DIRECTION_IN) != 0) {
  2556. Direction = UsbTransferDirectionIn;
  2557. }
  2558. }
  2559. MaxPacketSize = EndpointDescription->Descriptor.MaxPacketSize;
  2560. Status = UsbpCreateEndpoint(Device,
  2561. EndpointNumber,
  2562. Direction,
  2563. Type,
  2564. MaxPacketSize,
  2565. PollRate,
  2566. &Endpoint);
  2567. if (!KSUCCESS(Status)) {
  2568. goto CreateEndpointsForInterfaceEnd;
  2569. }
  2570. INSERT_BEFORE(&(Endpoint->ListEntry), &(Interface->EndpointList));
  2571. }
  2572. Status = STATUS_SUCCESS;
  2573. CreateEndpointsForInterfaceEnd:
  2574. if (!KSUCCESS(Status)) {
  2575. //
  2576. // Loop through and free any endpoints that were created.
  2577. //
  2578. CurrentEntry = Interface->EndpointList.Next;
  2579. while (CurrentEntry != &(Interface->EndpointList)) {
  2580. Endpoint = LIST_VALUE(CurrentEntry, USB_ENDPOINT, ListEntry);
  2581. CurrentEntry = CurrentEntry->Next;
  2582. ASSERT(Endpoint->ReferenceCount == 1);
  2583. UsbpEndpointReleaseReference(Device, Endpoint);
  2584. }
  2585. }
  2586. return Status;
  2587. }
  2588. PUSB_ENDPOINT
  2589. UsbpGetDeviceEndpoint (
  2590. PUSB_DEVICE Device,
  2591. UCHAR EndpointNumber
  2592. )
  2593. /*++
  2594. Routine Description:
  2595. This routine looks up a USB endpoint for the given device.
  2596. Arguments:
  2597. Device - Supplies a pointer to a USB device.
  2598. EndpointNumber - Supplies the number of the desired endpoint.
  2599. Return Value:
  2600. Returns a pointer to a USB endpoint on success, or NULL if the given
  2601. endpoint does not exist for the given device.
  2602. --*/
  2603. {
  2604. PUSB_CONFIGURATION ActiveConfiguration;
  2605. PLIST_ENTRY CurrentEndpointEntry;
  2606. PLIST_ENTRY CurrentInterfaceEntry;
  2607. PUSB_ENDPOINT Endpoint;
  2608. PUSB_INTERFACE Interface;
  2609. PLIST_ENTRY InterfaceListHead;
  2610. //
  2611. // Endpoint zero is easy to retrieve.
  2612. //
  2613. if (EndpointNumber == 0) {
  2614. return Device->EndpointZero;
  2615. }
  2616. //
  2617. // Run through the list of interfaces and associated endpoints to find
  2618. // non-zero endpoints.
  2619. //
  2620. ASSERT(Device->ActiveConfiguration != NULL);
  2621. ActiveConfiguration = Device->ActiveConfiguration;
  2622. InterfaceListHead = &(ActiveConfiguration->Description.InterfaceListHead);
  2623. CurrentInterfaceEntry = InterfaceListHead->Next;
  2624. Endpoint = NULL;
  2625. while (CurrentInterfaceEntry != InterfaceListHead) {
  2626. Interface = LIST_VALUE(CurrentInterfaceEntry,
  2627. USB_INTERFACE,
  2628. Description.ListEntry);
  2629. CurrentEndpointEntry = Interface->EndpointList.Next;
  2630. CurrentInterfaceEntry = CurrentInterfaceEntry->Next;
  2631. while (CurrentEndpointEntry != &(Interface->EndpointList)) {
  2632. Endpoint = LIST_VALUE(CurrentEndpointEntry,
  2633. USB_ENDPOINT,
  2634. ListEntry);
  2635. CurrentEndpointEntry = CurrentEndpointEntry->Next;
  2636. if (Endpoint->Number == EndpointNumber) {
  2637. break;
  2638. }
  2639. }
  2640. if ((Endpoint != NULL) && (Endpoint->Number == EndpointNumber)) {
  2641. break;
  2642. }
  2643. }
  2644. return Endpoint;
  2645. }
  2646. VOID
  2647. UsbpCompletedTransferWorker (
  2648. PVOID Parameter
  2649. )
  2650. /*++
  2651. Routine Description:
  2652. This routine processes completed USB transfers.
  2653. Arguments:
  2654. Parameter - Supplies a pointer to the USB host controller.
  2655. Return Value:
  2656. None.
  2657. --*/
  2658. {
  2659. PUSB_TRANSFER_CALLBACK CallbackRoutine;
  2660. PUSB_TRANSFER_PRIVATE CompleteTransfer;
  2661. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue;
  2662. PLIST_ENTRY CurrentEntry;
  2663. RUNLEVEL OldRunLevel;
  2664. USB_TRANSFER_STATE OldState;
  2665. LIST_ENTRY TransferList;
  2666. ASSERT(KeGetRunLevel() == RunLevelLow);
  2667. CompletionQueue = (PUSB_TRANSFER_COMPLETION_QUEUE)Parameter;
  2668. //
  2669. // Acquire the lock and pull all transfers off of the list. Once the list
  2670. // is empty and the lock is released, other completed transfers will know
  2671. // that the work item needs to be queued.
  2672. //
  2673. ASSERT(LIST_EMPTY(&(CompletionQueue->CompletedTransfersList)) == FALSE);
  2674. OldRunLevel = UsbpAcquireCompletedTransfersLock(CompletionQueue);
  2675. MOVE_LIST(&(CompletionQueue->CompletedTransfersList), &TransferList);
  2676. INITIALIZE_LIST_HEAD(&(CompletionQueue->CompletedTransfersList));
  2677. UsbpReleaseCompletedTransfersLock(CompletionQueue, OldRunLevel);
  2678. //
  2679. // Now that the lock is released and execution is at low level, process the
  2680. // work items.
  2681. //
  2682. while (LIST_EMPTY(&TransferList) == FALSE) {
  2683. CurrentEntry = TransferList.Next;
  2684. LIST_REMOVE(CurrentEntry);
  2685. CompleteTransfer = LIST_VALUE(CurrentEntry,
  2686. USB_TRANSFER_PRIVATE,
  2687. CompletionListEntry);
  2688. ASSERT(CompleteTransfer->Magic == USB_TRANSFER_INTERNAL_MAGIC);
  2689. //
  2690. // Mark that the transfer is no longer in flight, but in the callback.
  2691. //
  2692. OldState = RtlAtomicCompareExchange32(&(CompleteTransfer->State),
  2693. TransferInCallback,
  2694. TransferActive);
  2695. ASSERT(OldState == TransferActive);
  2696. //
  2697. // Call the callback routine.
  2698. //
  2699. CompleteTransfer->CompletionListEntry.Next = NULL;
  2700. CallbackRoutine = CompleteTransfer->Protected.Public.CallbackRoutine;
  2701. CallbackRoutine(&(CompleteTransfer->Protected.Public));
  2702. //
  2703. // If the callback did not resubmit the transfer, then move it to the
  2704. // inactive state. See the submit routine for how this change
  2705. // synchronizes with re-submits that are outside the callback (e.g. in
  2706. // a work item).
  2707. //
  2708. RtlAtomicCompareExchange32(&(CompleteTransfer->State),
  2709. TransferInactive,
  2710. TransferInCallback);
  2711. //
  2712. // Once the callback is called, USB core is done with this transfer;
  2713. // release the reference taken during submit.
  2714. //
  2715. UsbTransferReleaseReference((PUSB_TRANSFER)CompleteTransfer);
  2716. }
  2717. return;
  2718. }
  2719. RUNLEVEL
  2720. UsbpAcquireCompletedTransfersLock (
  2721. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue
  2722. )
  2723. /*++
  2724. Routine Description:
  2725. This routine acquires the given completion queue's completed transfers lock
  2726. at dispatch level.
  2727. Arguments:
  2728. CompletionQueue - Supplies a pointer to the completion queue to lock.
  2729. Return Value:
  2730. Returns the previous run-level, which must be passed in when the completion
  2731. queue is unlocked.
  2732. --*/
  2733. {
  2734. RUNLEVEL OldRunLevel;
  2735. OldRunLevel = KeRaiseRunLevel(RunLevelDispatch);
  2736. KeAcquireSpinLock(&(CompletionQueue->CompletedTransfersListLock));
  2737. return OldRunLevel;
  2738. }
  2739. VOID
  2740. UsbpReleaseCompletedTransfersLock (
  2741. PUSB_TRANSFER_COMPLETION_QUEUE CompletionQueue,
  2742. RUNLEVEL OldRunLevel
  2743. )
  2744. /*++
  2745. Routine Description:
  2746. This routine releases the given completion queue's completed transfers
  2747. lock, and returns the run-level to its previous value.
  2748. Arguments:
  2749. CompletionQueue - Supplies a pointer to the completion queue to unlock.
  2750. OldRunLevel - Supplies the original run level returned when the lock was
  2751. acquired.
  2752. Return Value:
  2753. None.
  2754. --*/
  2755. {
  2756. KeReleaseSpinLock(&(CompletionQueue->CompletedTransfersListLock));
  2757. KeLowerRunLevel(OldRunLevel);
  2758. return;
  2759. }