usbkbd.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. usbkbd.c
  5. Abstract:
  6. This module implements support for the USB Keyboard driver.
  7. Author:
  8. Evan Green 20-Mar-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "usbkbd.h"
  16. //
  17. // --------------------------------------------------------------------- Macros
  18. //
  19. //
  20. // ---------------------------------------------------------------- Definitions
  21. //
  22. //
  23. // Defines an error code reported to the system if the IN endpoint is halted
  24. // and cannot be cleared.
  25. //
  26. #define USB_KBD_ERROR_IN_ENDPOINT_HALTED 0x00000001
  27. //
  28. // Define the report ID for setting LED state.
  29. //
  30. #define USB_KBD_SET_LED_REPORT_ID 0
  31. //
  32. // ------------------------------------------------------ Data Type Definitions
  33. //
  34. /*++
  35. Structure Description:
  36. This structure stores context about a USB keyboard device.
  37. Members:
  38. UsbCoreHandle - Stores the handle to the device as identified by the USB
  39. core library.
  40. InterfaceNumber - Stores the USB keyboard interface number that this
  41. driver instance is attached to.
  42. InterfaceClaimed - Stores a boolean indicating whether or not the interface
  43. is claimed.
  44. IoBuffer - Stores a pointer to the I/O buffer used for transfers.
  45. InEndpoint - Stores the endpoint number for the interrupt IN endpoint.
  46. InMaxTransferSize - Stores the maximum transfer size on the interrupt IN
  47. endpoint, in bytes.
  48. InTransfer - Stores a pointer to the interrupt IN transfer used to receive
  49. HID reports.
  50. OutEndpoint - Stores the endpointer number for the optional interrupt OUT
  51. endpoint, or 0 to indicate that the default control endpoint should be
  52. used for out transfers.
  53. OutMaxTransferSize - Stores the maximum transfer size on the interrupt OUT
  54. endpoint, in bytes.
  55. UserInputHandle - Stores the handle given back by the user input library.
  56. PreviousReport - Stores a pointer to the previous keyboard report.
  57. --*/
  58. typedef struct _USB_KEYBOARD_DEVICE {
  59. HANDLE UsbCoreHandle;
  60. UCHAR InterfaceNumber;
  61. BOOL InterfaceClaimed;
  62. PIO_BUFFER IoBuffer;
  63. UCHAR InEndpoint;
  64. ULONG InMaxTransferSize;
  65. PUSB_TRANSFER InTransfer;
  66. UCHAR OutEndpoint;
  67. ULONG OutMaxTransferSize;
  68. HANDLE UserInputHandle;
  69. USB_KEYBOARD_REPORT PreviousReport;
  70. } USB_KEYBOARD_DEVICE, *PUSB_KEYBOARD_DEVICE;
  71. //
  72. // ----------------------------------------------- Internal Function Prototypes
  73. //
  74. KSTATUS
  75. UsbKbdAddDevice (
  76. PVOID Driver,
  77. PSTR DeviceId,
  78. PSTR ClassId,
  79. PSTR CompatibleIds,
  80. PVOID DeviceToken
  81. );
  82. VOID
  83. UsbKbdDispatchStateChange (
  84. PIRP Irp,
  85. PVOID DeviceContext,
  86. PVOID IrpContext
  87. );
  88. VOID
  89. UsbKbdDispatchOpen (
  90. PIRP Irp,
  91. PVOID DeviceContext,
  92. PVOID IrpContext
  93. );
  94. VOID
  95. UsbKbdDispatchClose (
  96. PIRP Irp,
  97. PVOID DeviceContext,
  98. PVOID IrpContext
  99. );
  100. VOID
  101. UsbKbdDispatchIo (
  102. PIRP Irp,
  103. PVOID DeviceContext,
  104. PVOID IrpContext
  105. );
  106. VOID
  107. UsbKbdDispatchSystemControl (
  108. PIRP Irp,
  109. PVOID DeviceContext,
  110. PVOID IrpContext
  111. );
  112. KSTATUS
  113. UsbKbdpStartDevice (
  114. PIRP Irp,
  115. PUSB_KEYBOARD_DEVICE Device
  116. );
  117. KSTATUS
  118. UsbKbdpSetUpUsbDevice (
  119. PIRP Irp,
  120. PUSB_KEYBOARD_DEVICE Device
  121. );
  122. VOID
  123. UsbKbdpRemoveDevice (
  124. PIRP Irp,
  125. PUSB_KEYBOARD_DEVICE Device
  126. );
  127. VOID
  128. UsbKbdpTransferCompletionCallback (
  129. PUSB_TRANSFER Transfer
  130. );
  131. VOID
  132. UsbKbdpProcessReport (
  133. PUSB_KEYBOARD_DEVICE Device,
  134. PUSB_KEYBOARD_REPORT Report
  135. );
  136. KSTATUS
  137. UsbKbdpSetLedState (
  138. PVOID Device,
  139. PVOID DeviceContext,
  140. ULONG LedState
  141. );
  142. //
  143. // -------------------------------------------------------------------- Globals
  144. //
  145. PDRIVER UsbKbdDriver = NULL;
  146. //
  147. // ------------------------------------------------------------------ Functions
  148. //
  149. KSTATUS
  150. DriverEntry (
  151. PDRIVER Driver
  152. )
  153. /*++
  154. Routine Description:
  155. This routine is the entry point for the USB keyboard driver. It registers
  156. the other dispatch functions, and performs driver-wide initialization.
  157. Arguments:
  158. Driver - Supplies a pointer to the driver object.
  159. Return Value:
  160. STATUS_SUCCESS on success.
  161. Failure code on error.
  162. --*/
  163. {
  164. DRIVER_FUNCTION_TABLE FunctionTable;
  165. KSTATUS Status;
  166. UsbKbdDriver = Driver;
  167. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  168. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  169. FunctionTable.AddDevice = UsbKbdAddDevice;
  170. FunctionTable.DispatchStateChange = UsbKbdDispatchStateChange;
  171. FunctionTable.DispatchOpen = UsbKbdDispatchOpen;
  172. FunctionTable.DispatchClose = UsbKbdDispatchClose;
  173. FunctionTable.DispatchIo = UsbKbdDispatchIo;
  174. FunctionTable.DispatchSystemControl = UsbKbdDispatchSystemControl;
  175. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  176. return Status;
  177. }
  178. //
  179. // --------------------------------------------------------- Internal Functions
  180. //
  181. KSTATUS
  182. UsbKbdAddDevice (
  183. PVOID Driver,
  184. PSTR DeviceId,
  185. PSTR ClassId,
  186. PSTR CompatibleIds,
  187. PVOID DeviceToken
  188. )
  189. /*++
  190. Routine Description:
  191. This routine is called when a device is detected for which the USB keyboard
  192. driver acts as the function driver. The driver will attach itself to the
  193. stack.
  194. Arguments:
  195. Driver - Supplies a pointer to the driver being called.
  196. DeviceId - Supplies a pointer to a string with the device ID.
  197. ClassId - Supplies a pointer to a string containing the device's class ID.
  198. CompatibleIds - Supplies a pointer to a string containing device IDs
  199. that would be compatible with this device.
  200. DeviceToken - Supplies an opaque token that the driver can use to identify
  201. the device in the system. This token should be used when attaching to
  202. the stack.
  203. Return Value:
  204. STATUS_SUCCESS on success.
  205. Failure code if the driver was unsuccessful in attaching itself.
  206. --*/
  207. {
  208. PUSB_KEYBOARD_DEVICE NewDevice;
  209. KSTATUS Status;
  210. //
  211. // Create the device context and attach to the device.
  212. //
  213. NewDevice = MmAllocatePagedPool(sizeof(USB_KEYBOARD_DEVICE),
  214. USB_KEYBOARD_ALLOCATION_TAG);
  215. if (NewDevice == NULL) {
  216. return STATUS_INSUFFICIENT_RESOURCES;
  217. }
  218. RtlZeroMemory(NewDevice, sizeof(USB_KEYBOARD_DEVICE));
  219. NewDevice->UsbCoreHandle = INVALID_HANDLE;
  220. NewDevice->UserInputHandle = INVALID_HANDLE;
  221. //
  222. // Attempt to attach to the USB core.
  223. //
  224. Status = UsbDriverAttach(DeviceToken,
  225. UsbKbdDriver,
  226. &(NewDevice->UsbCoreHandle));
  227. if (!KSUCCESS(Status)) {
  228. goto AddDeviceEnd;
  229. }
  230. ASSERT(NewDevice->UsbCoreHandle != INVALID_HANDLE);
  231. Status = IoAttachDriverToDevice(Driver, DeviceToken, NewDevice);
  232. AddDeviceEnd:
  233. if (!KSUCCESS(Status)) {
  234. if (NewDevice != NULL) {
  235. if (NewDevice->UsbCoreHandle != INVALID_HANDLE) {
  236. UsbDeviceClose(NewDevice->UsbCoreHandle);
  237. }
  238. MmFreePagedPool(NewDevice);
  239. }
  240. }
  241. return Status;
  242. }
  243. VOID
  244. UsbKbdDispatchStateChange (
  245. PIRP Irp,
  246. PVOID DeviceContext,
  247. PVOID IrpContext
  248. )
  249. /*++
  250. Routine Description:
  251. This routine handles State Change IRPs.
  252. Arguments:
  253. Irp - Supplies a pointer to the I/O request packet.
  254. DeviceContext - Supplies the context pointer supplied by the driver when it
  255. attached itself to the driver stack. Presumably this pointer contains
  256. driver-specific device context.
  257. IrpContext - Supplies the context pointer supplied by the driver when
  258. the IRP was created.
  259. Return Value:
  260. None.
  261. --*/
  262. {
  263. PUSB_KEYBOARD_DEVICE Device;
  264. KSTATUS Status;
  265. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  266. Device = (PUSB_KEYBOARD_DEVICE)DeviceContext;
  267. switch (Irp->MinorCode) {
  268. case IrpMinorQueryResources:
  269. if (Irp->Direction == IrpUp) {
  270. IoCompleteIrp(UsbKbdDriver, Irp, STATUS_SUCCESS);
  271. }
  272. break;
  273. case IrpMinorStartDevice:
  274. //
  275. // Attempt to fire the thing up if the bus has already started it.
  276. //
  277. if (Irp->Direction == IrpUp) {
  278. Status = UsbKbdpStartDevice(Irp, Device);
  279. if (!KSUCCESS(Status)) {
  280. IoCompleteIrp(UsbKbdDriver, Irp, Status);
  281. }
  282. }
  283. break;
  284. case IrpMinorQueryChildren:
  285. IoCompleteIrp(UsbKbdDriver, Irp, STATUS_SUCCESS);
  286. break;
  287. case IrpMinorRemoveDevice:
  288. if (Irp->Direction == IrpUp) {
  289. UsbKbdpRemoveDevice(Irp, Device);
  290. }
  291. break;
  292. //
  293. // For all other IRPs, do nothing.
  294. //
  295. default:
  296. break;
  297. }
  298. return;
  299. }
  300. VOID
  301. UsbKbdDispatchOpen (
  302. PIRP Irp,
  303. PVOID DeviceContext,
  304. PVOID IrpContext
  305. )
  306. /*++
  307. Routine Description:
  308. This routine handles Open IRPs.
  309. Arguments:
  310. Irp - Supplies a pointer to the I/O request packet.
  311. DeviceContext - Supplies the context pointer supplied by the driver when it
  312. attached itself to the driver stack. Presumably this pointer contains
  313. driver-specific device context.
  314. IrpContext - Supplies the context pointer supplied by the driver when
  315. the IRP was created.
  316. Return Value:
  317. None.
  318. --*/
  319. {
  320. return;
  321. }
  322. VOID
  323. UsbKbdDispatchClose (
  324. PIRP Irp,
  325. PVOID DeviceContext,
  326. PVOID IrpContext
  327. )
  328. /*++
  329. Routine Description:
  330. This routine handles Close IRPs.
  331. Arguments:
  332. Irp - Supplies a pointer to the I/O request packet.
  333. DeviceContext - Supplies the context pointer supplied by the driver when it
  334. attached itself to the driver stack. Presumably this pointer contains
  335. driver-specific device context.
  336. IrpContext - Supplies the context pointer supplied by the driver when
  337. the IRP was created.
  338. Return Value:
  339. None.
  340. --*/
  341. {
  342. return;
  343. }
  344. VOID
  345. UsbKbdDispatchIo (
  346. PIRP Irp,
  347. PVOID DeviceContext,
  348. PVOID IrpContext
  349. )
  350. /*++
  351. Routine Description:
  352. This routine handles I/O IRPs.
  353. Arguments:
  354. Irp - Supplies a pointer to the I/O request packet.
  355. DeviceContext - Supplies the context pointer supplied by the driver when it
  356. attached itself to the driver stack. Presumably this pointer contains
  357. driver-specific device context.
  358. IrpContext - Supplies the context pointer supplied by the driver when
  359. the IRP was created.
  360. Return Value:
  361. None.
  362. --*/
  363. {
  364. return;
  365. }
  366. VOID
  367. UsbKbdDispatchSystemControl (
  368. PIRP Irp,
  369. PVOID DeviceContext,
  370. PVOID IrpContext
  371. )
  372. /*++
  373. Routine Description:
  374. This routine handles System Control IRPs.
  375. Arguments:
  376. Irp - Supplies a pointer to the I/O request packet.
  377. DeviceContext - Supplies the context pointer supplied by the driver when it
  378. attached itself to the driver stack. Presumably this pointer contains
  379. driver-specific device context.
  380. IrpContext - Supplies the context pointer supplied by the driver when
  381. the IRP was created.
  382. Return Value:
  383. None.
  384. --*/
  385. {
  386. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  387. //
  388. // Do no processing on any IRPs. Let them flow.
  389. //
  390. return;
  391. }
  392. KSTATUS
  393. UsbKbdpStartDevice (
  394. PIRP Irp,
  395. PUSB_KEYBOARD_DEVICE Device
  396. )
  397. /*++
  398. Routine Description:
  399. This routine starts up the USB keyboard device.
  400. Arguments:
  401. Irp - Supplies a pointer to the I/O request packet.
  402. Device - Supplies a pointer to this USB keyboard device.
  403. Return Value:
  404. Status code.
  405. --*/
  406. {
  407. ULONG AlignedMaxTransferSize;
  408. ULONG Alignment;
  409. USER_INPUT_DEVICE_DESCRIPTION Description;
  410. PIO_BUFFER_FRAGMENT Fragment;
  411. PIO_BUFFER IoBuffer;
  412. ULONG IoBufferFlags;
  413. USB_SETUP_PACKET Setup;
  414. KSTATUS Status;
  415. HANDLE UserInputHandle;
  416. //
  417. // Claim the interface.
  418. //
  419. Status = UsbKbdpSetUpUsbDevice(Irp, Device);
  420. if (!KSUCCESS(Status)) {
  421. goto StartDeviceEnd;
  422. }
  423. //
  424. // Make sure that the device is in boot protocol mode. This driver does not
  425. // parse the report descriptor.
  426. //
  427. Setup.RequestType = USB_SETUP_REQUEST_TO_DEVICE |
  428. USB_SETUP_REQUEST_CLASS |
  429. USB_SETUP_REQUEST_INTERFACE_RECIPIENT;
  430. Setup.Request = USB_HID_SET_PROTOCOL;
  431. Setup.Value = USB_HID_PROTOCOL_VALUE_BOOT;
  432. Setup.Index = Device->InterfaceNumber;
  433. Setup.Length = 0;
  434. Status = UsbSendControlTransfer(Device->UsbCoreHandle,
  435. UsbTransferDirectionOut,
  436. &Setup,
  437. NULL,
  438. 0,
  439. NULL);
  440. if (!KSUCCESS(Status)) {
  441. goto StartDeviceEnd;
  442. }
  443. //
  444. // Send a Set Idle request so the device only completes the interrupt
  445. // transfers when something's changed.
  446. //
  447. Setup.RequestType = USB_SETUP_REQUEST_TO_DEVICE |
  448. USB_SETUP_REQUEST_CLASS |
  449. USB_SETUP_REQUEST_INTERFACE_RECIPIENT;
  450. Setup.Request = USB_HID_SET_IDLE;
  451. Setup.Value = 0;
  452. Setup.Index = Device->InterfaceNumber;
  453. Setup.Length = 0;
  454. Status = UsbSendControlTransfer(Device->UsbCoreHandle,
  455. UsbTransferDirectionOut,
  456. &Setup,
  457. NULL,
  458. 0,
  459. NULL);
  460. if (!KSUCCESS(Status)) {
  461. goto StartDeviceEnd;
  462. }
  463. //
  464. // Allocate an IN transfer if needed.
  465. //
  466. ASSERT(Device->InMaxTransferSize != 0);
  467. if (Device->InTransfer == NULL) {
  468. Alignment = MmGetIoBufferAlignment();
  469. AlignedMaxTransferSize = ALIGN_RANGE_UP(Device->InMaxTransferSize,
  470. Alignment);
  471. Device->InTransfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  472. Device->InEndpoint,
  473. Device->InMaxTransferSize,
  474. 0);
  475. if (Device->InTransfer == NULL) {
  476. Status = STATUS_INSUFFICIENT_RESOURCES;
  477. goto StartDeviceEnd;
  478. }
  479. ASSERT(Device->IoBuffer == NULL);
  480. //
  481. // Allocate an I/O buffer.
  482. //
  483. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  484. IoBuffer = MmAllocateNonPagedIoBuffer(0,
  485. MAX_ULONG,
  486. Alignment,
  487. AlignedMaxTransferSize,
  488. IoBufferFlags);
  489. if (IoBuffer == NULL) {
  490. Status = STATUS_INSUFFICIENT_RESOURCES;
  491. goto StartDeviceEnd;
  492. }
  493. ASSERT(IoBuffer->FragmentCount == 1);
  494. //
  495. // Wire up the USB transfer to use the I/O buffer.
  496. //
  497. Fragment = &(IoBuffer->Fragment[0]);
  498. Device->InTransfer->Buffer = Fragment->VirtualAddress;
  499. Device->InTransfer->BufferPhysicalAddress = Fragment->PhysicalAddress;
  500. Device->InTransfer->BufferActualLength = Fragment->Size;
  501. Device->IoBuffer = IoBuffer;
  502. }
  503. //
  504. // Create the user input device if needed.
  505. //
  506. if (Device->UserInputHandle == INVALID_HANDLE) {
  507. Description.Device = Irp->Device;
  508. Description.DeviceContext = Device;
  509. Description.Type = UserInputDeviceKeyboard;
  510. Description.InterfaceVersion =
  511. USER_INPUT_KEYBOARD_DEVICE_INTERFACE_VERSION;
  512. Description.U.KeyboardInterface.SetLedState = UsbKbdpSetLedState;
  513. UserInputHandle = InRegisterInputDevice(&Description);
  514. if (UserInputHandle == INVALID_HANDLE) {
  515. Status = STATUS_INVALID_HANDLE;
  516. goto StartDeviceEnd;
  517. }
  518. Device->UserInputHandle = UserInputHandle;
  519. }
  520. //
  521. // Submit the interrupt in transfer to start polling for reports.
  522. //
  523. Device->InTransfer->Direction = UsbTransferDirectionIn;
  524. Device->InTransfer->Length = Device->InMaxTransferSize;
  525. Device->InTransfer->UserData = Device;
  526. Device->InTransfer->CallbackRoutine = UsbKbdpTransferCompletionCallback;
  527. Status = UsbSubmitTransfer(Device->InTransfer);
  528. if (!KSUCCESS(Status)) {
  529. goto StartDeviceEnd;
  530. }
  531. Status = STATUS_SUCCESS;
  532. StartDeviceEnd:
  533. if (!KSUCCESS(Status)) {
  534. if (Device->InTransfer != NULL) {
  535. UsbDestroyTransfer(Device->InTransfer);
  536. Device->InTransfer = NULL;
  537. if (Device->IoBuffer != NULL) {
  538. MmFreeIoBuffer(Device->IoBuffer);
  539. Device->IoBuffer = NULL;
  540. }
  541. }
  542. if (Device->UserInputHandle != INVALID_HANDLE) {
  543. InDestroyInputDevice(Device->UserInputHandle);
  544. Device->UserInputHandle = INVALID_HANDLE;
  545. }
  546. ASSERT(Device->IoBuffer == NULL);
  547. }
  548. return Status;
  549. }
  550. KSTATUS
  551. UsbKbdpSetUpUsbDevice (
  552. PIRP Irp,
  553. PUSB_KEYBOARD_DEVICE Device
  554. )
  555. /*++
  556. Routine Description:
  557. This routine claims the keyboard interface for the given device.
  558. Arguments:
  559. Irp - Supplies a pointer to the I/O request packet.
  560. Device - Supplies a pointer to this keyboard device.
  561. Return Value:
  562. Status code.
  563. --*/
  564. {
  565. PUSB_CONFIGURATION_DESCRIPTION Configuration;
  566. PLIST_ENTRY CurrentEntry;
  567. USB_TRANSFER_DIRECTION Direction;
  568. PUSB_ENDPOINT_DESCRIPTION Endpoint;
  569. UCHAR EndpointType;
  570. BOOL InEndpointFound;
  571. PUSB_INTERFACE_DESCRIPTION Interface;
  572. BOOL OutEndpointFound;
  573. KSTATUS Status;
  574. //
  575. // Sanity check that the interface has not already been claimed.
  576. //
  577. if (Device->InterfaceClaimed != FALSE) {
  578. Status = STATUS_SUCCESS;
  579. goto SetUpUsbDeviceEnd;
  580. }
  581. //
  582. // If the configuration isn't yet set, set the first one.
  583. //
  584. Configuration = UsbGetActiveConfiguration(Device->UsbCoreHandle);
  585. if (Configuration == NULL) {
  586. Status = UsbSetConfiguration(Device->UsbCoreHandle, 0, TRUE);
  587. if (!KSUCCESS(Status)) {
  588. goto SetUpUsbDeviceEnd;
  589. }
  590. Configuration = UsbGetActiveConfiguration(Device->UsbCoreHandle);
  591. ASSERT(Configuration != NULL);
  592. }
  593. //
  594. // Get and verify the interface.
  595. //
  596. Interface = UsbGetDesignatedInterface(Irp->Device, Device->UsbCoreHandle);
  597. if (Interface == NULL) {
  598. Status = STATUS_NO_INTERFACE;
  599. goto SetUpUsbDeviceEnd;
  600. }
  601. if (Interface->Descriptor.Class != UsbInterfaceClassHid) {
  602. Status = STATUS_NO_INTERFACE;
  603. goto SetUpUsbDeviceEnd;
  604. }
  605. //
  606. // Also ensure that the keyboard supports the boot protocol, as that's what
  607. // this driver assumes (as opposed to actually parsing out HID reports).
  608. //
  609. if ((Interface->Descriptor.Subclass != USB_HID_BOOT_INTERFACE_SUBCLASS) ||
  610. (Interface->Descriptor.Protocol != USB_HID_BOOT_KEYBOARD_PROTOCOL)) {
  611. RtlDebugPrint("The attached USB keyboard does not follow the boot "
  612. "protocol, and as such is not currently supported.\n");
  613. Status = STATUS_NOT_SUPPORTED;
  614. goto SetUpUsbDeviceEnd;
  615. }
  616. //
  617. // Locate the IN and OUT endpoints.
  618. //
  619. InEndpointFound = FALSE;
  620. OutEndpointFound = FALSE;
  621. CurrentEntry = Interface->EndpointListHead.Next;
  622. while (CurrentEntry != &(Interface->EndpointListHead)) {
  623. Endpoint = LIST_VALUE(CurrentEntry,
  624. USB_ENDPOINT_DESCRIPTION,
  625. ListEntry);
  626. CurrentEntry = CurrentEntry->Next;
  627. //
  628. // Deconstruct the components of the endpoint descriptor.
  629. //
  630. EndpointType = Endpoint->Descriptor.Attributes &
  631. USB_ENDPOINT_ATTRIBUTES_TYPE_MASK;
  632. if ((Endpoint->Descriptor.EndpointAddress &
  633. USB_ENDPOINT_ADDRESS_DIRECTION_IN) != 0) {
  634. Direction = UsbTransferDirectionIn;
  635. } else {
  636. Direction = UsbTransferDirectionOut;
  637. }
  638. //
  639. // Look to match the endpoint up to one of the required ones.
  640. //
  641. if (EndpointType == USB_ENDPOINT_ATTRIBUTES_TYPE_INTERRUPT) {
  642. if ((InEndpointFound == FALSE) &&
  643. (Direction == UsbTransferDirectionIn)) {
  644. InEndpointFound = TRUE;
  645. Device->InEndpoint = Endpoint->Descriptor.EndpointAddress;
  646. Device->InMaxTransferSize = Endpoint->Descriptor.MaxPacketSize;
  647. } else if ((OutEndpointFound == FALSE) &&
  648. (Direction == UsbTransferDirectionOut)) {
  649. OutEndpointFound = TRUE;
  650. Device->OutEndpoint = Endpoint->Descriptor.EndpointAddress;
  651. Device->OutMaxTransferSize = Endpoint->Descriptor.MaxPacketSize;
  652. }
  653. }
  654. if ((InEndpointFound != FALSE) && (OutEndpointFound != FALSE)) {
  655. break;
  656. }
  657. }
  658. //
  659. // The IN endpoint is required, the OUT is not.
  660. //
  661. if (InEndpointFound == FALSE) {
  662. Status = STATUS_INVALID_CONFIGURATION;
  663. goto SetUpUsbDeviceEnd;
  664. }
  665. //
  666. // Everything's all ready, claim the interface.
  667. //
  668. Status = UsbClaimInterface(Device->UsbCoreHandle,
  669. Interface->Descriptor.InterfaceNumber);
  670. if (!KSUCCESS(Status)) {
  671. goto SetUpUsbDeviceEnd;
  672. }
  673. Device->InterfaceNumber = Interface->Descriptor.InterfaceNumber;
  674. Device->InterfaceClaimed = TRUE;
  675. Status = STATUS_SUCCESS;
  676. SetUpUsbDeviceEnd:
  677. return Status;
  678. }
  679. VOID
  680. UsbKbdpRemoveDevice (
  681. PIRP Irp,
  682. PUSB_KEYBOARD_DEVICE Device
  683. )
  684. /*++
  685. Routine Description:
  686. This routine removes the USB keyboard device.
  687. Arguments:
  688. Irp - Supplies a pointer to the I/O request packet.
  689. Device - Supplies a pointer to this USB keyboard device.
  690. Return Value:
  691. None.
  692. --*/
  693. {
  694. ASSERT(Irp->MinorCode == IrpMinorRemoveDevice);
  695. //
  696. // Detach the device from the USB core. This call marks the device as
  697. // disconnected and cancels all transfers.
  698. //
  699. UsbDetachDevice(Device->UsbCoreHandle);
  700. //
  701. // Now destroy the device. Since the above call waits for all transfers to
  702. // become inactive, the USB keyboard's IN transfer can no longer be
  703. // running. It was either properly cancelled or failed to resubmit while
  704. // in the callback.
  705. //
  706. if (Device->InterfaceClaimed != FALSE) {
  707. UsbReleaseInterface(Device->UsbCoreHandle, Device->InterfaceNumber);
  708. Device->InterfaceClaimed = FALSE;
  709. }
  710. //
  711. // Destroy the IO buffer created during USB keyboard initialization. It was
  712. // used by the transfer as well.
  713. //
  714. if (Device->IoBuffer != NULL) {
  715. MmFreeIoBuffer(Device->IoBuffer);
  716. }
  717. //
  718. // Destroy the USB keyboard device's IN transfer.
  719. //
  720. if (Device->InTransfer != NULL) {
  721. UsbDestroyTransfer(Device->InTransfer);
  722. }
  723. //
  724. // Destroy the USB keyboard input device.
  725. //
  726. if (Device->UserInputHandle != INVALID_HANDLE) {
  727. InDestroyInputDevice(Device->UserInputHandle);
  728. }
  729. //
  730. // Close the USB core handle, matching the open from when the driver
  731. // attached to the device.
  732. //
  733. ASSERT(Device->UsbCoreHandle != INVALID_HANDLE);
  734. UsbDeviceClose(Device->UsbCoreHandle);
  735. MmFreePagedPool(Device);
  736. return;
  737. }
  738. VOID
  739. UsbKbdpTransferCompletionCallback (
  740. PUSB_TRANSFER Transfer
  741. )
  742. /*++
  743. Routine Description:
  744. This routine is called when a USB transfer completes for the keyboard.
  745. Arguments:
  746. Transfer - Supplies a pointer to the transfer that completed.
  747. Return Value:
  748. None.
  749. --*/
  750. {
  751. PUSB_KEYBOARD_DEVICE Device;
  752. PVOID DeviceToken;
  753. PUSB_KEYBOARD_REPORT Report;
  754. KSTATUS Status;
  755. Device = (PUSB_KEYBOARD_DEVICE)Transfer->UserData;
  756. ASSERT(Device != NULL);
  757. ASSERT(Transfer == Device->InTransfer);
  758. ASSERT(Transfer->Direction == UsbTransferDirectionIn);
  759. //
  760. // Handle transfer errors to determine whether or not to resubmit.
  761. //
  762. if (!KSUCCESS(Transfer->Status)) {
  763. //
  764. // Do not resubmit the transfer if it was cancelled.
  765. //
  766. if (Transfer->Status == STATUS_OPERATION_CANCELLED) {
  767. ASSERT(Transfer->Error == UsbErrorTransferCancelled);
  768. goto TransferCompletionCallbackEnd;
  769. //
  770. // If there was an I/O error, perform any steps to clear the error.
  771. //
  772. } else if (Transfer->Status == STATUS_DEVICE_IO_ERROR) {
  773. if (Transfer->Error == UsbErrorTransferStalled) {
  774. Status = UsbClearFeature(Device->UsbCoreHandle,
  775. USB_SETUP_REQUEST_ENDPOINT_RECIPIENT,
  776. USB_FEATURE_ENDPOINT_HALT,
  777. Device->InEndpoint);
  778. if (!KSUCCESS(Status)) {
  779. DeviceToken = UsbGetDeviceToken(Device->UsbCoreHandle);
  780. IoSetDeviceDriverError(DeviceToken,
  781. UsbKbdDriver,
  782. Status,
  783. USB_KBD_ERROR_IN_ENDPOINT_HALTED);
  784. goto TransferCompletionCallbackEnd;
  785. }
  786. }
  787. //
  788. // Otherwise just send out a debug print and carry on.
  789. //
  790. } else {
  791. RtlDebugPrint("USB KBD: Unexpected error for IN transfer (0x%08x) "
  792. "on device 0x%08x: Status %d, Error %d.\n",
  793. Transfer,
  794. Device,
  795. Transfer->Status,
  796. Transfer->Error);
  797. }
  798. }
  799. //
  800. // Otherwise, process the data and re-submit the IN transfer for the USB
  801. // keyboard.
  802. //
  803. if (Transfer->LengthTransferred >= sizeof(USB_KEYBOARD_REPORT)) {
  804. Report = (PUSB_KEYBOARD_REPORT)Transfer->Buffer;
  805. UsbKbdpProcessReport(Device, Report);
  806. }
  807. //
  808. // If submission fails, exit.
  809. //
  810. Status = UsbSubmitTransfer(Device->InTransfer);
  811. if (!KSUCCESS(Status)) {
  812. goto TransferCompletionCallbackEnd;
  813. }
  814. TransferCompletionCallbackEnd:
  815. return;
  816. }
  817. VOID
  818. UsbKbdpProcessReport (
  819. PUSB_KEYBOARD_DEVICE Device,
  820. PUSB_KEYBOARD_REPORT Report
  821. )
  822. /*++
  823. Routine Description:
  824. This routine processes a new USB keyboard input report.
  825. Arguments:
  826. Device - Supplies a pointer to the keyboard device.
  827. Report - Supplies a pointer to the latest keyboard report.
  828. Return Value:
  829. None.
  830. --*/
  831. {
  832. ULONG BitIndex;
  833. UCHAR ChangedModifiers;
  834. USER_INPUT_EVENT Event;
  835. UCHAR Key;
  836. ULONG KeyIndex;
  837. UCHAR Mask;
  838. PUSB_KEYBOARD_REPORT Previous;
  839. USB_KEYBOARD_REPORT PreviousCopy;
  840. ULONG SearchIndex;
  841. BOOL ValidData;
  842. ASSERT(KeGetRunLevel() == RunLevelLow);
  843. //
  844. // First look for the all ones combination, which indicates that too many
  845. // keys are pressed.
  846. //
  847. ValidData = FALSE;
  848. for (KeyIndex = 0;
  849. KeyIndex < USB_KEYBOARD_REPORT_KEY_COUNT;
  850. KeyIndex += 1) {
  851. if (Report->Keycode[KeyIndex] != USB_KEYBOARD_INVALID_KEY_CODE) {
  852. ValidData = TRUE;
  853. break;
  854. }
  855. }
  856. if (ValidData == FALSE) {
  857. return;
  858. }
  859. Previous = &(Device->PreviousReport);
  860. RtlCopyMemory(&PreviousCopy, Previous, sizeof(USB_KEYBOARD_REPORT));
  861. //
  862. // Handle changes in the modifier keys.
  863. //
  864. ChangedModifiers = Previous->ModifierKeys ^ Report->ModifierKeys;
  865. for (BitIndex = 0; BitIndex < BITS_PER_BYTE; BitIndex += 1) {
  866. Mask = 1 << BitIndex;
  867. //
  868. // Send the change report if the modifier key changed.
  869. //
  870. if ((ChangedModifiers & Mask) != 0) {
  871. if ((Report->ModifierKeys & Mask) != 0) {
  872. Event.EventType = UserInputEventKeyDown;
  873. } else {
  874. Event.EventType = UserInputEventKeyUp;
  875. }
  876. Event.U.Key = UsbKbdControlKeys[BitIndex];
  877. InReportInputEvent(Device->UserInputHandle, &Event);
  878. }
  879. }
  880. //
  881. // Loop over every key down in the new report, and send key down reports if
  882. // it's not down in the previous report.
  883. //
  884. Event.EventType = UserInputEventKeyDown;
  885. for (KeyIndex = 0;
  886. KeyIndex < USB_KEYBOARD_REPORT_KEY_COUNT;
  887. KeyIndex += 1) {
  888. Key = Report->Keycode[KeyIndex];
  889. if ((Key >= USB_KEYBOARD_FIRST_VALID_KEY_CODE) &&
  890. (Key < USB_KEYCOARD_KEY_CODE_COUNT)) {
  891. //
  892. // Do a quick check in the same slot in the previous report, as
  893. // it's probably where the corresponding key is.
  894. //
  895. if (Previous->Keycode[KeyIndex] == Key) {
  896. PreviousCopy.Keycode[KeyIndex] = 0;
  897. continue;
  898. }
  899. //
  900. // Search for the keycode in the previous array.
  901. //
  902. for (SearchIndex = 0;
  903. SearchIndex < USB_KEYBOARD_REPORT_KEY_COUNT;
  904. SearchIndex += 1) {
  905. if (Previous->Keycode[SearchIndex] == Key) {
  906. PreviousCopy.Keycode[SearchIndex] = 0;
  907. break;
  908. }
  909. }
  910. //
  911. // If the key was found, then nothing's changed, so don't send a
  912. // report.
  913. //
  914. if (SearchIndex != USB_KEYBOARD_REPORT_KEY_COUNT) {
  915. continue;
  916. }
  917. //
  918. // This key just went down, so send a key down message.
  919. //
  920. Event.U.Key = UsbKbdKeys[Key];
  921. if (Event.U.Key != KeyboardKeyInvalid) {
  922. InReportInputEvent(Device->UserInputHandle, &Event);
  923. }
  924. }
  925. }
  926. //
  927. // Now go through the remaining key in the previous copy. Any of those
  928. // keys that haven't been blanked out by the last loop are keys that must
  929. // not have existed in the most recent report, meaning they're key up
  930. // events.
  931. //
  932. Event.EventType = UserInputEventKeyUp;
  933. for (KeyIndex = 0;
  934. KeyIndex < USB_KEYBOARD_REPORT_KEY_COUNT;
  935. KeyIndex += 1) {
  936. Key = PreviousCopy.Keycode[KeyIndex];
  937. if ((Key >= USB_KEYBOARD_FIRST_VALID_KEY_CODE) &&
  938. (Key < USB_KEYCOARD_KEY_CODE_COUNT)) {
  939. Event.U.Key = UsbKbdKeys[Key];
  940. if (Event.U.Key != KeyboardKeyInvalid) {
  941. InReportInputEvent(Device->UserInputHandle, &Event);
  942. }
  943. }
  944. }
  945. //
  946. // Copy the current report over the previous one.
  947. //
  948. RtlCopyMemory(Previous, Report, sizeof(USB_KEYBOARD_REPORT));
  949. return;
  950. }
  951. KSTATUS
  952. UsbKbdpSetLedState (
  953. PVOID Device,
  954. PVOID DeviceContext,
  955. ULONG LedState
  956. )
  957. /*++
  958. Routine Description:
  959. This routine sets a keyboard's LED state (e.g. Number lock, Caps lock and
  960. scroll lock). The state is absolute; the desired state for each LED must be
  961. supplied.
  962. Arguments:
  963. Device - Supplies a pointer to the OS device representing the user input
  964. device.
  965. DeviceContext - Supplies the opaque device context supplied in the device
  966. description upon registration with the user input library.
  967. LedState - Supplies a bitmask of flags describing the desired LED state.
  968. See USER_INPUT_KEYBOARD_LED_* for definition.
  969. Return Value:
  970. Status code.
  971. --*/
  972. {
  973. ULONG AlignedMaxTransferSize;
  974. ULONG Alignment;
  975. PIO_BUFFER_FRAGMENT Fragment;
  976. PIO_BUFFER IoBuffer;
  977. ULONG IoBufferFlags;
  978. USB_SETUP_PACKET Setup;
  979. KSTATUS Status;
  980. PUSB_TRANSFER Transfer;
  981. PUSB_KEYBOARD_DEVICE UsbDevice;
  982. UCHAR UsbLedState;
  983. UsbDevice = (PUSB_KEYBOARD_DEVICE)DeviceContext;
  984. //
  985. // Convert from the user input library LED state to the USB keyboard LED
  986. // state.
  987. //
  988. UsbLedState = 0;
  989. if ((LedState & USER_INPUT_KEYBOARD_LED_SCROLL_LOCK) != 0) {
  990. UsbLedState |= USB_KEYBOARD_LED_SCROLL_LOCK;
  991. }
  992. if ((LedState & USER_INPUT_KEYBOARD_LED_NUM_LOCK) != 0) {
  993. UsbLedState |= USB_KEYBOARD_LED_NUM_LOCK;
  994. }
  995. if ((LedState & USER_INPUT_KEYBOARD_LED_CAPS_LOCK) != 0) {
  996. UsbLedState |= USB_KEYBOARD_LED_CAPS_LOCK;
  997. }
  998. if ((LedState & USER_INPUT_KEYBOARD_LED_COMPOSE) != 0) {
  999. UsbLedState |= USB_KEYBOARD_LED_COMPOSE;
  1000. }
  1001. if ((LedState & USER_INPUT_KEYBOARD_LED_KANA) != 0) {
  1002. UsbLedState |= USB_KEYBOARD_LED_KANA;
  1003. }
  1004. //
  1005. // If an out endpoint exists, then just send the raw LED state. That's what
  1006. // it is expecting.
  1007. //
  1008. IoBuffer = NULL;
  1009. Transfer = NULL;
  1010. if (UsbDevice->OutEndpoint != 0) {
  1011. ASSERT(UsbDevice->OutMaxTransferSize >= sizeof(UCHAR));
  1012. Alignment = MmGetIoBufferAlignment();
  1013. AlignedMaxTransferSize = ALIGN_RANGE_UP(UsbDevice->OutMaxTransferSize,
  1014. Alignment);
  1015. Transfer = UsbAllocateTransfer(UsbDevice->UsbCoreHandle,
  1016. UsbDevice->OutEndpoint,
  1017. UsbDevice->OutMaxTransferSize,
  1018. 0);
  1019. if (Transfer == NULL) {
  1020. Status = STATUS_INSUFFICIENT_RESOURCES;
  1021. goto SetLedStateEnd;
  1022. }
  1023. ASSERT(UsbDevice->IoBuffer == NULL);
  1024. //
  1025. // Allocate an I/O buffer.
  1026. //
  1027. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  1028. IoBuffer = MmAllocateNonPagedIoBuffer(0,
  1029. MAX_ULONG,
  1030. Alignment,
  1031. AlignedMaxTransferSize,
  1032. IoBufferFlags);
  1033. if (IoBuffer == NULL) {
  1034. Status = STATUS_INSUFFICIENT_RESOURCES;
  1035. goto SetLedStateEnd;
  1036. }
  1037. ASSERT(IoBuffer->FragmentCount == 1);
  1038. //
  1039. // Wire up the USB transfer to use the I/O buffer.
  1040. //
  1041. Fragment = &(IoBuffer->Fragment[0]);
  1042. Transfer->Buffer = Fragment->VirtualAddress;
  1043. Transfer->BufferPhysicalAddress = Fragment->PhysicalAddress;
  1044. Transfer->BufferActualLength = Fragment->Size;
  1045. //
  1046. // Prepare the data and send it synchronously.
  1047. //
  1048. *((PUCHAR)Transfer->Buffer) = UsbLedState;
  1049. Transfer->Length = sizeof(UCHAR);
  1050. Transfer->Direction = UsbTransferDirectionOut;
  1051. Status = UsbSubmitSynchronousTransfer(Transfer);
  1052. if (!KSUCCESS(Status)) {
  1053. goto SetLedStateEnd;
  1054. }
  1055. //
  1056. // Otherwise the LED state can be set using a "set report" control transfer.
  1057. //
  1058. } else {
  1059. Setup.RequestType = USB_SETUP_REQUEST_TO_DEVICE |
  1060. USB_SETUP_REQUEST_CLASS |
  1061. USB_SETUP_REQUEST_INTERFACE_RECIPIENT;
  1062. Setup.Request = USB_HID_SET_REPORT;
  1063. Setup.Value = (USB_HID_REPORT_VALUE_TYPE_OUTPUT <<
  1064. USB_HID_REPORT_VALUE_TYPE_SHIFT) |
  1065. ((USB_KBD_SET_LED_REPORT_ID <<
  1066. USB_HID_REPORT_VALUE_ID_SHIFT) &
  1067. USB_HID_REPORT_VALUE_ID_MASK);
  1068. Setup.Index = UsbDevice->InterfaceNumber;
  1069. Setup.Length = sizeof(UCHAR);
  1070. Status = UsbSendControlTransfer(UsbDevice->UsbCoreHandle,
  1071. UsbTransferDirectionOut,
  1072. &Setup,
  1073. &UsbLedState,
  1074. sizeof(UCHAR),
  1075. NULL);
  1076. if (!KSUCCESS(Status)) {
  1077. goto SetLedStateEnd;
  1078. }
  1079. }
  1080. SetLedStateEnd:
  1081. if (Transfer != NULL) {
  1082. UsbDestroyTransfer(Transfer);
  1083. }
  1084. if (IoBuffer != NULL) {
  1085. MmFreeIoBuffer(IoBuffer);
  1086. }
  1087. return Status;
  1088. }