usbhub.c 13 KB

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