usbhub.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. usbhub.c
  5. Abstract:
  6. This module implements support for the USB Hub driver.
  7. Author:
  8. Evan Green 16-Jan-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/driver.h>
  16. #include <minoca/usb/usbhost.h>
  17. #include "usbhub.h"
  18. //
  19. // --------------------------------------------------------------------- Macros
  20. //
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. /*++
  28. Structure Description:
  29. This structure stores context about a USB Hub.
  30. Members:
  31. UsbCoreHandle - Stores the handle to the hub as identified by the USB core
  32. library.
  33. UsbHub - Stores an opaque pointer to the USB hub-specific context.
  34. --*/
  35. typedef struct _USB_HUB_DRIVER_CONTEXT {
  36. HANDLE UsbCoreHandle;
  37. PUSB_HUB UsbHub;
  38. } USB_HUB_DRIVER_CONTEXT, *PUSB_HUB_DRIVER_CONTEXT;
  39. //
  40. // ----------------------------------------------- Internal Function Prototypes
  41. //
  42. KSTATUS
  43. UsbHubAddDevice (
  44. PVOID Driver,
  45. PSTR DeviceId,
  46. PSTR ClassId,
  47. PSTR CompatibleIds,
  48. PVOID DeviceToken
  49. );
  50. VOID
  51. UsbHubDispatchStateChange (
  52. PIRP Irp,
  53. PVOID DeviceContext,
  54. PVOID IrpContext
  55. );
  56. VOID
  57. UsbHubDispatchOpen (
  58. PIRP Irp,
  59. PVOID DeviceContext,
  60. PVOID IrpContext
  61. );
  62. VOID
  63. UsbHubDispatchClose (
  64. PIRP Irp,
  65. PVOID DeviceContext,
  66. PVOID IrpContext
  67. );
  68. VOID
  69. UsbHubDispatchIo (
  70. PIRP Irp,
  71. PVOID DeviceContext,
  72. PVOID IrpContext
  73. );
  74. VOID
  75. UsbHubDispatchSystemControl (
  76. PIRP Irp,
  77. PVOID DeviceContext,
  78. PVOID IrpContext
  79. );
  80. KSTATUS
  81. UsbHubpStartDevice (
  82. PIRP Irp,
  83. PUSB_HUB_DRIVER_CONTEXT Device
  84. );
  85. VOID
  86. UsbHubpEnumerateChildren (
  87. PIRP Irp,
  88. PUSB_HUB_DRIVER_CONTEXT Device
  89. );
  90. VOID
  91. UsbHubpRemoveDevice (
  92. PIRP Irp,
  93. PUSB_HUB_DRIVER_CONTEXT Device
  94. );
  95. //
  96. // -------------------------------------------------------------------- Globals
  97. //
  98. PDRIVER UsbHubDriver = NULL;
  99. //
  100. // ------------------------------------------------------------------ Functions
  101. //
  102. KSTATUS
  103. DriverEntry (
  104. PDRIVER Driver
  105. )
  106. /*++
  107. Routine Description:
  108. This routine is the entry point for the USB Hub driver. It registers its
  109. other dispatch functions, and performs driver-wide initialization.
  110. Arguments:
  111. Driver - Supplies a pointer to the driver object.
  112. Return Value:
  113. STATUS_SUCCESS on success.
  114. Failure code on error.
  115. --*/
  116. {
  117. DRIVER_FUNCTION_TABLE FunctionTable;
  118. KSTATUS Status;
  119. UsbHubDriver = Driver;
  120. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  121. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  122. FunctionTable.AddDevice = UsbHubAddDevice;
  123. FunctionTable.DispatchStateChange = UsbHubDispatchStateChange;
  124. FunctionTable.DispatchOpen = UsbHubDispatchOpen;
  125. FunctionTable.DispatchClose = UsbHubDispatchClose;
  126. FunctionTable.DispatchIo = UsbHubDispatchIo;
  127. FunctionTable.DispatchSystemControl = UsbHubDispatchSystemControl;
  128. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  129. return Status;
  130. }
  131. //
  132. // --------------------------------------------------------- Internal Functions
  133. //
  134. KSTATUS
  135. UsbHubAddDevice (
  136. PVOID Driver,
  137. PSTR DeviceId,
  138. PSTR ClassId,
  139. PSTR CompatibleIds,
  140. PVOID DeviceToken
  141. )
  142. /*++
  143. Routine Description:
  144. This routine is called when a device is detected for which the USB Hub
  145. driver acts as the function driver. The driver will attach itself to the
  146. stack.
  147. Arguments:
  148. Driver - Supplies a pointer to the driver being called.
  149. DeviceId - Supplies a pointer to a string with the device ID.
  150. ClassId - Supplies a pointer to a string containing the device's class ID.
  151. CompatibleIds - Supplies a pointer to a string containing device IDs
  152. that would be compatible with this device.
  153. DeviceToken - Supplies an opaque token that the driver can use to identify
  154. the device in the system. This token should be used when attaching to
  155. the stack.
  156. Return Value:
  157. STATUS_SUCCESS on success.
  158. Failure code if the driver was unsuccessful in attaching itself.
  159. --*/
  160. {
  161. PUSB_HUB_DRIVER_CONTEXT NewDevice;
  162. KSTATUS Status;
  163. //
  164. // Create the device context and attach to the device.
  165. //
  166. NewDevice = MmAllocateNonPagedPool(sizeof(USB_HUB_DRIVER_CONTEXT),
  167. USB_HUB_ALLOCATION_TAG);
  168. if (NewDevice == NULL) {
  169. return STATUS_INSUFFICIENT_RESOURCES;
  170. }
  171. RtlZeroMemory(NewDevice, sizeof(USB_HUB_DRIVER_CONTEXT));
  172. NewDevice->UsbCoreHandle = INVALID_HANDLE;
  173. //
  174. // Attempt to attach to the USB core.
  175. //
  176. Status = UsbDriverAttach(DeviceToken,
  177. UsbHubDriver,
  178. &(NewDevice->UsbCoreHandle));
  179. if (!KSUCCESS(Status)) {
  180. goto AddDeviceEnd;
  181. }
  182. ASSERT(NewDevice->UsbCoreHandle != INVALID_HANDLE);
  183. //
  184. // Allow the USB core to create some hub context with this device.
  185. //
  186. Status = UsbCreateHub(NewDevice->UsbCoreHandle, &(NewDevice->UsbHub));
  187. if (!KSUCCESS(Status)) {
  188. goto AddDeviceEnd;
  189. }
  190. Status = IoAttachDriverToDevice(Driver, DeviceToken, NewDevice);
  191. AddDeviceEnd:
  192. if (!KSUCCESS(Status)) {
  193. if (NewDevice != NULL) {
  194. if (NewDevice->UsbCoreHandle != INVALID_HANDLE) {
  195. UsbDeviceClose(NewDevice->UsbCoreHandle);
  196. }
  197. MmFreeNonPagedPool(NewDevice);
  198. }
  199. }
  200. return Status;
  201. }
  202. VOID
  203. UsbHubDispatchStateChange (
  204. PIRP Irp,
  205. PVOID DeviceContext,
  206. PVOID IrpContext
  207. )
  208. /*++
  209. Routine Description:
  210. This routine handles State Change IRPs.
  211. Arguments:
  212. Irp - Supplies a pointer to the I/O request packet.
  213. DeviceContext - Supplies the context pointer supplied by the driver when it
  214. attached itself to the driver stack. Presumably this pointer contains
  215. driver-specific device context.
  216. IrpContext - Supplies the context pointer supplied by the driver when
  217. the IRP was created.
  218. Return Value:
  219. None.
  220. --*/
  221. {
  222. PUSB_HUB_DRIVER_CONTEXT Device;
  223. KSTATUS Status;
  224. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  225. Device = (PUSB_HUB_DRIVER_CONTEXT)DeviceContext;
  226. //
  227. // If the device structure is NULL, then the USB hub driver is acting as a
  228. // bus driver. Complete some IRPs by default.
  229. //
  230. if (Device == NULL) {
  231. switch (Irp->MinorCode) {
  232. case IrpMinorRemoveDevice:
  233. case IrpMinorQueryResources:
  234. case IrpMinorStartDevice:
  235. case IrpMinorQueryChildren:
  236. if (Irp->Direction == IrpUp) {
  237. IoCompleteIrp(UsbHubDriver, Irp, STATUS_SUCCESS);
  238. }
  239. break;
  240. default:
  241. break;
  242. }
  243. //
  244. // If the device is non-NULL, the driver is acting as a function driver for
  245. // the USB hub.
  246. //
  247. } else {
  248. switch (Irp->MinorCode) {
  249. case IrpMinorQueryResources:
  250. if (Irp->Direction == IrpUp) {
  251. IoCompleteIrp(UsbHubDriver, Irp, STATUS_SUCCESS);
  252. }
  253. break;
  254. case IrpMinorStartDevice:
  255. //
  256. // Attempt to fire the thing up if the bus has already started it.
  257. //
  258. if (Irp->Direction == IrpUp) {
  259. Status = UsbHubpStartDevice(Irp, Device);
  260. if (!KSUCCESS(Status)) {
  261. IoCompleteIrp(UsbHubDriver, Irp, Status);
  262. }
  263. }
  264. break;
  265. case IrpMinorQueryChildren:
  266. if (Irp->Direction == IrpUp) {
  267. UsbHubpEnumerateChildren(Irp, Device);
  268. }
  269. break;
  270. case IrpMinorRemoveDevice:
  271. if (Irp->Direction == IrpUp) {
  272. UsbHubpRemoveDevice(Irp, Device);
  273. }
  274. break;
  275. //
  276. // For all other IRPs, do nothing.
  277. //
  278. default:
  279. break;
  280. }
  281. }
  282. return;
  283. }
  284. VOID
  285. UsbHubDispatchOpen (
  286. PIRP Irp,
  287. PVOID DeviceContext,
  288. PVOID IrpContext
  289. )
  290. /*++
  291. Routine Description:
  292. This routine handles Open IRPs.
  293. Arguments:
  294. Irp - Supplies a pointer to the I/O request packet.
  295. DeviceContext - Supplies the context pointer supplied by the driver when it
  296. attached itself to the driver stack. Presumably this pointer contains
  297. driver-specific device context.
  298. IrpContext - Supplies the context pointer supplied by the driver when
  299. the IRP was created.
  300. Return Value:
  301. None.
  302. --*/
  303. {
  304. return;
  305. }
  306. VOID
  307. UsbHubDispatchClose (
  308. PIRP Irp,
  309. PVOID DeviceContext,
  310. PVOID IrpContext
  311. )
  312. /*++
  313. Routine Description:
  314. This routine handles Close IRPs.
  315. Arguments:
  316. Irp - Supplies a pointer to the I/O request packet.
  317. DeviceContext - Supplies the context pointer supplied by the driver when it
  318. attached itself to the driver stack. Presumably this pointer contains
  319. driver-specific device context.
  320. IrpContext - Supplies the context pointer supplied by the driver when
  321. the IRP was created.
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. return;
  327. }
  328. VOID
  329. UsbHubDispatchIo (
  330. PIRP Irp,
  331. PVOID DeviceContext,
  332. PVOID IrpContext
  333. )
  334. /*++
  335. Routine Description:
  336. This routine handles I/O IRPs.
  337. Arguments:
  338. Irp - Supplies a pointer to the I/O request packet.
  339. DeviceContext - Supplies the context pointer supplied by the driver when it
  340. attached itself to the driver stack. Presumably this pointer contains
  341. driver-specific device context.
  342. IrpContext - Supplies the context pointer supplied by the driver when
  343. the IRP was created.
  344. Return Value:
  345. None.
  346. --*/
  347. {
  348. return;
  349. }
  350. VOID
  351. UsbHubDispatchSystemControl (
  352. PIRP Irp,
  353. PVOID DeviceContext,
  354. PVOID IrpContext
  355. )
  356. /*++
  357. Routine Description:
  358. This routine handles System Control IRPs.
  359. Arguments:
  360. Irp - Supplies a pointer to the I/O request packet.
  361. DeviceContext - Supplies the context pointer supplied by the driver when it
  362. attached itself to the driver stack. Presumably this pointer contains
  363. driver-specific device context.
  364. IrpContext - Supplies the context pointer supplied by the driver when
  365. the IRP was created.
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  371. //
  372. // Do no processing on any IRPs. Let them flow.
  373. //
  374. return;
  375. }
  376. KSTATUS
  377. UsbHubpStartDevice (
  378. PIRP Irp,
  379. PUSB_HUB_DRIVER_CONTEXT Device
  380. )
  381. /*++
  382. Routine Description:
  383. This routine starts up the USB Hub.
  384. Arguments:
  385. Irp - Supplies a pointer to the I/O request packet.
  386. Device - Supplies a pointer to this hub device.
  387. Return Value:
  388. Status code.
  389. --*/
  390. {
  391. KSTATUS Status;
  392. Status = UsbStartHub(Device->UsbHub);
  393. if (!KSUCCESS(Status)) {
  394. goto StartDeviceEnd;
  395. }
  396. StartDeviceEnd:
  397. return Status;
  398. }
  399. VOID
  400. UsbHubpEnumerateChildren (
  401. PIRP Irp,
  402. PUSB_HUB_DRIVER_CONTEXT Device
  403. )
  404. /*++
  405. Routine Description:
  406. This routine enumerates the USB Hub's children.
  407. Arguments:
  408. Irp - Supplies a pointer to the I/O request packet.
  409. Device - Supplies a pointer to this hub device.
  410. Return Value:
  411. None.
  412. --*/
  413. {
  414. KSTATUS Status;
  415. //
  416. // Forward this on to the USB core to figure out.
  417. //
  418. Status = UsbHubQueryChildren(Irp, Device->UsbHub);
  419. IoCompleteIrp(UsbHubDriver, Irp, Status);
  420. return;
  421. }
  422. VOID
  423. UsbHubpRemoveDevice (
  424. PIRP Irp,
  425. PUSB_HUB_DRIVER_CONTEXT Device
  426. )
  427. /*++
  428. Routine Description:
  429. This routine removes the USB hub device.
  430. Arguments:
  431. Irp - Supplies a pointer to the I/O request packet.
  432. Device - Supplies a pointer to this hub device.
  433. Return Value:
  434. None.
  435. --*/
  436. {
  437. //
  438. // Set the device for removal in USB core. This will mark the device as
  439. // disconnected and cancel all of its transfers.
  440. //
  441. UsbDetachDevice(Device->UsbCoreHandle);
  442. //
  443. // Destroy the hub. This will remove all of the device's children and
  444. // destroy any hub-specific state.
  445. //
  446. UsbDestroyHub(Device->UsbHub);
  447. //
  448. // Release the reference on the USB core handle that was taken when the hub
  449. // device was added.
  450. //
  451. UsbDeviceClose(Device->UsbCoreHandle);
  452. //
  453. // Free the hub context.
  454. //
  455. MmFreeNonPagedPool(Device);
  456. return;
  457. }