Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1220 lines
38 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. usb.c
  5. Abstract: Human Input Device (HID) minidriver for Universal Serial Bus (USB) devices
  6. The HID USB Minidriver (HUM, Hum) provides an abstraction layer for the
  7. HID Class so that future HID devices whic are not USB devices can be supported.
  8. Author:
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #include <USBDLIB.H>
  15. NTSTATUS
  16. HumGetHidInfo(
  17. IN PDEVICE_OBJECT DeviceObject,
  18. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc,
  19. IN ULONG DescriptorLength
  20. )
  21. /*++
  22. Routine Description:
  23. Given a config descriptor for a device, finds whether the device has a valid
  24. HID interface and a valid HID descriptor in that interface. Saves this to
  25. our device extension for later.
  26. Arguments:
  27. DeviceObject - pointer to a device object.
  28. ConfigDesc - pointer to USB configuration descriptor
  29. DescriptorLength - length of valid data in config descriptor
  30. Return Value:
  31. NT status code.
  32. --*/
  33. {
  34. NTSTATUS ntStatus = STATUS_SUCCESS;
  35. PDEVICE_EXTENSION DeviceExtension;
  36. PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
  37. DBGPRINT(1,("HumGetHidInfo Entry"));
  38. /*
  39. * Get a pointer to the device extension
  40. */
  41. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  42. /*
  43. * Init our HID descriptor
  44. */
  45. RtlZeroMemory((PUCHAR) &DeviceExtension->HidDescriptor, sizeof(USB_HID_DESCRIPTOR));
  46. /*
  47. * Walk the interfaces
  48. */
  49. InterfaceDesc = USBD_ParseConfigurationDescriptorEx(
  50. ConfigDesc,
  51. ConfigDesc,
  52. -1,
  53. -1,
  54. USB_INTERFACE_CLASS_HID,
  55. -1,
  56. -1);
  57. if (InterfaceDesc){
  58. PUSB_HID_DESCRIPTOR pHidDescriptor = NULL;
  59. ASSERT(InterfaceDesc->bLength >= sizeof(USB_INTERFACE_DESCRIPTOR));
  60. /*
  61. * If this is a HID interface, look for a HID descriptor.
  62. */
  63. if (InterfaceDesc->bInterfaceClass == USB_INTERFACE_CLASS_HID) {
  64. HumParseHidInterface(DeviceExtension, InterfaceDesc, 0, &pHidDescriptor);
  65. }
  66. else {
  67. ASSERT(!(PVOID)"USBD_ParseConfigurationDescriptorEx returned non-HID iface descriptor!");
  68. }
  69. //
  70. // Did we find a HID descriptor?
  71. //
  72. if (pHidDescriptor) {
  73. //
  74. // Yes, copy HID descriptor to our private storage
  75. //
  76. DBGPRINT(1,("Copying device descriptor to DeviceExtension->HidDescriptor"));
  77. RtlCopyMemory((PUCHAR) &DeviceExtension->HidDescriptor, (PUCHAR) pHidDescriptor, sizeof(USB_HID_DESCRIPTOR));
  78. }
  79. else {
  80. DBGWARN(("Failed to find a HID Descriptor!"));
  81. ntStatus = STATUS_UNSUCCESSFUL;
  82. }
  83. }
  84. else {
  85. DBGWARN(("USBD_ParseConfigurationDescriptorEx() failed!"));
  86. ntStatus = STATUS_UNSUCCESSFUL;
  87. }
  88. DBGPRINT(1,("HumGetHidInfo Exit = 0x%x", ntStatus));
  89. return ntStatus;
  90. }
  91. NTSTATUS
  92. HumGetDeviceDescriptor(
  93. IN PDEVICE_OBJECT DeviceObject,
  94. IN PDEVICE_EXTENSION DeviceData
  95. )
  96. /*++
  97. Routine Description:
  98. Returns a configuration descriptor for the device
  99. Arguments:
  100. DeviceObject - pointer to a device object.
  101. Return Value:
  102. NT status code.
  103. --*/
  104. {
  105. NTSTATUS ntStatus = STATUS_SUCCESS;
  106. ULONG DescriptorLength = sizeof (USB_DEVICE_DESCRIPTOR);
  107. DBGPRINT(1,("HumGetDeviceDescriptor Entry"));
  108. //
  109. // Get config descriptor
  110. //
  111. ntStatus = HumGetDescriptorRequest(
  112. DeviceObject,
  113. URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
  114. USB_DEVICE_DESCRIPTOR_TYPE,
  115. (PVOID *) &DeviceData->DeviceDescriptor,
  116. &DescriptorLength,
  117. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  118. 0,
  119. 0);
  120. if (NT_SUCCESS(ntStatus)){
  121. //
  122. // Dump device descriptor
  123. //
  124. ASSERT (sizeof(USB_DEVICE_DESCRIPTOR) == DescriptorLength);
  125. DBGPRINT(2,("Device->bLength = 0x%x", DeviceData->DeviceDescriptor->bLength));
  126. DBGPRINT(2,("Device->bDescriptorType = 0x%x", DeviceData->DeviceDescriptor->bDescriptorType));
  127. DBGPRINT(2,("Device->bDeviceClass = 0x%x", DeviceData->DeviceDescriptor->bDeviceClass));
  128. DBGPRINT(2,("Device->bDeviceSubClass = 0x%x", DeviceData->DeviceDescriptor->bDeviceSubClass));
  129. DBGPRINT(2,("Device->bDeviceProtocol = 0x%x", DeviceData->DeviceDescriptor->bDeviceProtocol));
  130. DBGPRINT(2,("Device->idVendor = 0x%x", DeviceData->DeviceDescriptor->idVendor));
  131. DBGPRINT(2,("Device->idProduct = 0x%x", DeviceData->DeviceDescriptor->idProduct));
  132. DBGPRINT(2,("Device->bcdDevice = 0x%x", DeviceData->DeviceDescriptor->bcdDevice));
  133. }
  134. else {
  135. DBGWARN(("HumGetDescriptorRequest failed w/ %xh in HumGetDeviceDescriptor", (ULONG)ntStatus));
  136. }
  137. DBGPRINT(1,("HumGetDeviceDescriptor Exit = 0x%x", ntStatus));
  138. return ntStatus;
  139. }
  140. NTSTATUS
  141. HumGetConfigDescriptor(
  142. IN PDEVICE_OBJECT DeviceObject,
  143. OUT PUSB_CONFIGURATION_DESCRIPTOR *ConfigurationDesc,
  144. OUT PULONG ConfigurationDescLength
  145. )
  146. /*++
  147. Routine Description:
  148. Returns a configuration descriptor for the device
  149. Arguments:
  150. DeviceObject - pointer to a device object.
  151. Return Value:
  152. NT status code.
  153. --*/
  154. {
  155. NTSTATUS ntStatus = STATUS_SUCCESS;
  156. ULONG DescriptorLength;
  157. PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc = NULL;
  158. DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
  159. //
  160. // Just get the base config descriptor, so that we can figure out the size,
  161. // then allocate enough space for the entire descriptor.
  162. //
  163. ntStatus = HumGetDescriptorRequest(DeviceObject,
  164. URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
  165. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  166. (PVOID *) &ConfigDesc,
  167. &DescriptorLength,
  168. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  169. 0,
  170. 0);
  171. if (NT_SUCCESS(ntStatus)){
  172. ASSERT(DescriptorLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
  173. DescriptorLength = ConfigDesc->wTotalLength;
  174. ExFreePool(ConfigDesc);
  175. if (!DescriptorLength) {
  176. //
  177. // The config descriptor is bad. Outta here.
  178. //
  179. return STATUS_DEVICE_DATA_ERROR;
  180. }
  181. //
  182. // Set this to NULL so we know to allocate a new buffer
  183. //
  184. ConfigDesc = NULL;
  185. ntStatus = HumGetDescriptorRequest(DeviceObject,
  186. URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
  187. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  188. (PVOID *) &ConfigDesc,
  189. &DescriptorLength,
  190. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  191. 0,
  192. 0);
  193. if (NT_SUCCESS(ntStatus)) {
  194. //
  195. // Dump config descriptor
  196. //
  197. DBGPRINT(1,("Config = 0x%x", ConfigDesc));
  198. DBGPRINT(2,("Config->bLength = 0x%x", ConfigDesc->bLength));
  199. DBGPRINT(2,("Config->bDescriptorType = 0x%x", ConfigDesc->bDescriptorType));
  200. DBGPRINT(2,("Config->wTotalLength = 0x%x", ConfigDesc->wTotalLength));
  201. DBGPRINT(2,("Config->bNumInterfaces = 0x%x", ConfigDesc->bNumInterfaces));
  202. DBGPRINT(2,("Config->bConfigurationValue = 0x%x", ConfigDesc->bConfigurationValue));
  203. DBGPRINT(2,("Config->iConfiguration = 0x%x", ConfigDesc->iConfiguration));
  204. DBGPRINT(2,("Config->bmAttributes = 0x%x", ConfigDesc->bmAttributes));
  205. DBGPRINT(2,("Config->MaxPower = 0x%x", ConfigDesc->MaxPower));
  206. ASSERT (ConfigDesc->bLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
  207. #ifndef STRICT_COMPLIANCE
  208. if (ConfigDesc->bLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
  209. DBGPRINT(1,("WARINING -- Correcting bad Config->bLength"));
  210. ConfigDesc->bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
  211. }
  212. #endif
  213. }
  214. else {
  215. DBGWARN(("HumGetDescriptorRequest failed in HumGetConfigDescriptor (#1)"));
  216. }
  217. }
  218. else {
  219. DBGWARN(("HumGetDescriptorRequest failed in HumGetConfigDescriptor (#2)"));
  220. }
  221. *ConfigurationDesc = ConfigDesc;
  222. *ConfigurationDescLength = DescriptorLength;
  223. return ntStatus;
  224. }
  225. NTSTATUS
  226. HumParseHidInterface(
  227. IN PDEVICE_EXTENSION DeviceExtension,
  228. IN PUSB_INTERFACE_DESCRIPTOR InterfaceDesc,
  229. IN ULONG InterfaceLength,
  230. OUT PUSB_HID_DESCRIPTOR *HidDescriptor
  231. )
  232. /*++
  233. Routine Description:
  234. Find a valid HID descriptor in a HID Interface
  235. Arguments:
  236. DeviceObject - pointer to a device object.
  237. Return Value:
  238. NT status code.
  239. --*/
  240. {
  241. NTSTATUS ntStatus = STATUS_SUCCESS;
  242. ULONG iEndpoint;
  243. PUSB_ENDPOINT_DESCRIPTOR EndpointDesc;
  244. PUSB_COMMON_DESCRIPTOR CommonDesc;
  245. DBGPRINT(1,("HumParseHidInterface Entry"));
  246. //
  247. // Set to null until we find the HidDescriptor
  248. //
  249. *HidDescriptor = NULL;
  250. //
  251. // This routine should only be called on HID interface class interfaces.
  252. //
  253. ASSERT (InterfaceDesc->bInterfaceClass == USB_INTERFACE_CLASS_HID);
  254. //
  255. // Check for valid length
  256. //
  257. if (InterfaceDesc->bLength < sizeof(USB_INTERFACE_DESCRIPTOR)) {
  258. DBGWARN(("Interface->bLength (%d) is invalid", InterfaceDesc->bLength));
  259. goto Bail;
  260. }
  261. //
  262. // For HID 1.0 draft 4 compliance, the next descriptor is HID. However, for earlier
  263. // drafts, endpoints come first and then HID. We're trying to support both.
  264. //
  265. DeviceExtension->DeviceFlags &= ~DEVICE_FLAGS_HID_1_0_D3_COMPAT_DEVICE;
  266. //
  267. // What draft of HID 1.0 are we looking at?
  268. //
  269. CommonDesc = (PUSB_COMMON_DESCRIPTOR) ((ULONG_PTR)InterfaceDesc + InterfaceDesc->bLength);
  270. if (CommonDesc->bLength < sizeof (USB_COMMON_DESCRIPTOR)) {
  271. DBGWARN(("Descriptor->bLength (%d) is invalid", CommonDesc->bLength));
  272. goto Bail;
  273. }
  274. if (CommonDesc->bDescriptorType != USB_DESCRIPTOR_TYPE_HID) {
  275. DeviceExtension->DeviceFlags |= DEVICE_FLAGS_HID_1_0_D3_COMPAT_DEVICE;
  276. }
  277. else {
  278. //
  279. // Validate the length
  280. //
  281. if (CommonDesc->bLength == sizeof(USB_HID_DESCRIPTOR)) {
  282. *HidDescriptor = (PUSB_HID_DESCRIPTOR) CommonDesc;
  283. CommonDesc = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)*HidDescriptor +
  284. (*HidDescriptor)->bLength);
  285. }
  286. else {
  287. DBGWARN(("HID descriptor length (%d) is invalid!", CommonDesc->bLength));
  288. goto Bail;
  289. }
  290. }
  291. //
  292. // Walk endpoints
  293. //
  294. EndpointDesc = (PUSB_ENDPOINT_DESCRIPTOR) CommonDesc;
  295. for (iEndpoint = 0; iEndpoint < InterfaceDesc->bNumEndpoints; iEndpoint++) {
  296. if (EndpointDesc->bLength < sizeof(USB_ENDPOINT_DESCRIPTOR)) {
  297. DBGWARN(("Endpoint->bLength (%d) is invalid", EndpointDesc->bLength));
  298. goto Bail;
  299. }
  300. EndpointDesc = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDesc + EndpointDesc->bLength);
  301. }
  302. if (DeviceExtension->DeviceFlags & DEVICE_FLAGS_HID_1_0_D3_COMPAT_DEVICE) {
  303. CommonDesc = (PUSB_COMMON_DESCRIPTOR) EndpointDesc;
  304. if (CommonDesc->bDescriptorType == USB_DESCRIPTOR_TYPE_HID) {
  305. *HidDescriptor = (PUSB_HID_DESCRIPTOR) CommonDesc;
  306. }
  307. else {
  308. //
  309. // This is either an unknown type of descriptor or the device is
  310. // reporting back a bad descriptor type.
  311. //
  312. DBGWARN(("Unknown descriptor in HID interface"));
  313. #ifndef STRICT_COMPLIANCE
  314. if (CommonDesc->bLength == sizeof(USB_HID_DESCRIPTOR)) {
  315. DBGWARN(("WARINING -- Guessing descriptor of length %d is actually HID!", sizeof(USB_HID_DESCRIPTOR)));
  316. *HidDescriptor = (PUSB_HID_DESCRIPTOR) CommonDesc;
  317. }
  318. #endif
  319. }
  320. }
  321. //
  322. // End of endpoint/hid descriptor parsing.
  323. //
  324. if (*HidDescriptor) {
  325. DBGPRINT(1,("HidDescriptor = 0x%x", *HidDescriptor));
  326. DBGPRINT(2,("HidDescriptor->bLength = 0x%x", (*HidDescriptor)->bLength));
  327. DBGPRINT(2,("HidDescriptor->bDescriptorType = 0x%x", (*HidDescriptor)->bDescriptorType));
  328. DBGPRINT(2,("HidDescriptor->bcdHID = 0x%x", (*HidDescriptor)->bcdHID));
  329. DBGPRINT(2,("HidDescriptor->bCountryCode = 0x%x", (*HidDescriptor)->bCountry));
  330. DBGPRINT(2,("HidDescriptor->bNumDescriptors = 0x%x", (*HidDescriptor)->bNumDescriptors));
  331. DBGPRINT(2,("HidDescriptor->bReportType = 0x%x", (*HidDescriptor)->bReportType));
  332. DBGPRINT(2,("HidDescriptor->wReportLength = 0x%x", (*HidDescriptor)->wReportLength));
  333. }
  334. Bail:
  335. if (*HidDescriptor == NULL) {
  336. //
  337. // We did not find a HID descriptor in this interface!
  338. //
  339. DBGWARN(("Failed to find a valid HID descriptor in interface!"));
  340. DBGBREAK;
  341. ntStatus = STATUS_UNSUCCESSFUL;
  342. }
  343. DBGPRINT(1,("HumParseHidInterface Exit = 0x%x", ntStatus));
  344. return ntStatus;
  345. }
  346. NTSTATUS
  347. HumSelectConfiguration(
  348. IN PDEVICE_OBJECT DeviceObject,
  349. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
  350. )
  351. /*++
  352. Routine Description:
  353. Initializes an USB device which may have multiple interfaces
  354. Arguments:
  355. DeviceObject - pointer to the device object
  356. ConfigurationDescriptor - pointer to the USB configuration
  357. descriptor containing the interface and endpoint
  358. descriptors.
  359. Return Value:
  360. NT status code
  361. --*/
  362. {
  363. PDEVICE_EXTENSION DeviceExtension;
  364. NTSTATUS ntStatus;
  365. PURB urb = NULL;
  366. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
  367. USBD_INTERFACE_LIST_ENTRY interfaceList[2];
  368. PUSBD_INTERFACE_INFORMATION usbInterface;
  369. DBGPRINT(1,("HumSelectConfiguration Entry"));
  370. //
  371. // Get a pointer to the device extension
  372. //
  373. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  374. interfaceList[0].InterfaceDescriptor =
  375. USBD_ParseConfigurationDescriptorEx(
  376. ConfigurationDescriptor,
  377. ConfigurationDescriptor,
  378. -1,
  379. -1,
  380. USB_INTERFACE_CLASS_HID,
  381. -1,
  382. -1);
  383. // terminate the list
  384. interfaceList[1].InterfaceDescriptor =
  385. NULL;
  386. if (interfaceList[0].InterfaceDescriptor) {
  387. urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,
  388. &interfaceList[0]);
  389. if (urb) {
  390. ntStatus = HumCallUSB(DeviceObject, urb);
  391. //
  392. // If the device is configured, save the configuration handle
  393. //
  394. if (NT_SUCCESS(ntStatus)) {
  395. DeviceExtension->ConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle;
  396. //
  397. // Now we need to find the HID interface and save the pointer to it
  398. //
  399. usbInterface = &urb->UrbSelectConfiguration.Interface;
  400. ASSERT(usbInterface->Class == USB_INTERFACE_CLASS_HID);
  401. DBGPRINT(1,("USBD Interface = 0x%x", usbInterface));
  402. }
  403. else {
  404. DBGWARN(("HumCallUSB failed in HumSelectConfiguration"));
  405. DeviceExtension->ConfigurationHandle = NULL;
  406. }
  407. }
  408. else {
  409. DBGWARN(("USBD_CreateConfigurationRequestEx failed in HumSelectConfiguration"));
  410. ntStatus = STATUS_NO_MEMORY;
  411. }
  412. }
  413. else {
  414. DBGWARN(("Bad interface descriptor in HumSelectConfiguration"));
  415. ntStatus = STATUS_INVALID_PARAMETER;
  416. }
  417. if (NT_SUCCESS(ntStatus)) {
  418. DeviceExtension->Interface = ExAllocatePoolWithTag(NonPagedPool, usbInterface->Length, HIDUSB_TAG);
  419. if (DeviceExtension->Interface) {
  420. //
  421. // save a copy of the interface information returned
  422. //
  423. RtlCopyMemory(DeviceExtension->Interface, usbInterface, usbInterface->Length);
  424. #if DBG
  425. {
  426. ULONG j;
  427. //
  428. // Dump the interface to the debugger
  429. //
  430. DBGPRINT (2,("---------"));
  431. DBGPRINT (2,("NumberOfPipes 0x%x", DeviceExtension->Interface->NumberOfPipes));
  432. DBGPRINT (2,("Length 0x%x", DeviceExtension->Interface->Length));
  433. DBGPRINT (2,("Alt Setting 0x%x", DeviceExtension->Interface->AlternateSetting));
  434. DBGPRINT (2,("Interface Number 0x%x", DeviceExtension->Interface->InterfaceNumber));
  435. DBGPRINT (2,("Class, subclass, protocol 0x%x 0x%x 0x%x",
  436. DeviceExtension->Interface->Class,
  437. DeviceExtension->Interface->SubClass,
  438. DeviceExtension->Interface->Protocol));
  439. // Dump the pipe info
  440. for (j=0; j<DeviceExtension->Interface->NumberOfPipes; j++) {
  441. PUSBD_PIPE_INFORMATION pipeInformation;
  442. pipeInformation = &DeviceExtension->Interface->Pipes[j];
  443. DBGPRINT (2,("---------"));
  444. DBGPRINT (2,("PipeType 0x%x", pipeInformation->PipeType));
  445. DBGPRINT (2,("EndpointAddress 0x%x", pipeInformation->EndpointAddress));
  446. DBGPRINT (2,("MaxPacketSize 0x%x", pipeInformation->MaximumPacketSize));
  447. DBGPRINT (2,("Interval 0x%x", pipeInformation->Interval));
  448. DBGPRINT (2,("Handle 0x%x", pipeInformation->PipeHandle));
  449. DBGPRINT (2,("MaximumTransferSize 0x%x", pipeInformation->MaximumTransferSize));
  450. }
  451. DBGPRINT (2,("---------"));
  452. }
  453. #endif
  454. }
  455. }
  456. if (urb) {
  457. ExFreePool(urb);
  458. }
  459. DBGPRINT(1,("HumSelectConfiguration Exit = %x", ntStatus));
  460. return ntStatus;
  461. }
  462. NTSTATUS HumSetIdle(IN PDEVICE_OBJECT DeviceObject)
  463. /*++
  464. Routine Description:
  465. Initializes the idle timeout value for a HID device
  466. Arguments:
  467. DeviceObject - pointer to the device object for this instance of a UTB
  468. Return Value:
  469. NT status code
  470. --*/
  471. {
  472. NTSTATUS ntStatus;
  473. PURB Urb;
  474. ULONG TypeSize;
  475. PDEVICE_EXTENSION DeviceExtension;
  476. DBGPRINT(1,("HumSetIdle Enter"));
  477. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  478. if (DeviceExtension) {
  479. //
  480. // Allocate buffer
  481. //
  482. TypeSize = (USHORT) sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  483. Urb = ExAllocatePoolWithTag(NonPagedPool, TypeSize, HIDUSB_TAG);
  484. if(Urb) {
  485. RtlZeroMemory(Urb, TypeSize);
  486. if (DeviceExtension->DeviceFlags & DEVICE_FLAGS_HID_1_0_D3_COMPAT_DEVICE) {
  487. HumBuildClassRequest(Urb,
  488. URB_FUNCTION_CLASS_ENDPOINT, // function
  489. 0, // transferFlags
  490. NULL, // transferBuffer
  491. 0, // transferBufferLength
  492. 0x22, // requestTypeFlags
  493. HID_SET_IDLE, // request
  494. 0, // value
  495. 0, // index
  496. 0); // reqLength
  497. } else {
  498. HumBuildClassRequest(Urb,
  499. URB_FUNCTION_CLASS_INTERFACE, // function
  500. 0, // transferFlags
  501. NULL, // transferBuffer
  502. 0, // transferBufferLength
  503. 0x22, // requestTypeFlags
  504. HID_SET_IDLE, // request
  505. 0, // value
  506. DeviceExtension->Interface->InterfaceNumber, // index
  507. 0); // reqLength
  508. }
  509. ntStatus = HumCallUSB(DeviceObject, Urb);
  510. ExFreePool(Urb);
  511. }
  512. else {
  513. ntStatus = STATUS_NO_MEMORY;
  514. }
  515. }
  516. else {
  517. ntStatus = STATUS_NOT_FOUND;
  518. }
  519. DBGPRINT(1,("HumSetIdle Exit = %x", ntStatus));
  520. return ntStatus;
  521. }
  522. NTSTATUS
  523. HumGetDescriptorRequest(
  524. IN PDEVICE_OBJECT DeviceObject,
  525. IN USHORT Function,
  526. IN ULONG DescriptorType,
  527. IN OUT PVOID *Descriptor,
  528. IN OUT ULONG *DescSize,
  529. IN ULONG TypeSize,
  530. IN ULONG Index,
  531. IN ULONG LangID
  532. )
  533. /*++
  534. Routine Description:
  535. Retrieves the specified descriptor for this device. Allocates buffer, if
  536. necessary.
  537. Arguments:
  538. DeviceObject - pointer to the device object
  539. Function -
  540. Return Value:
  541. NT status code.
  542. --*/
  543. {
  544. NTSTATUS ntStatus;
  545. PURB Urb;
  546. BOOLEAN AllocOnBehalf = FALSE;
  547. DBGPRINT(1,("HumGetDescriptorRequest Enter"));
  548. DBGPRINT(1,("DeviceObject = %x", DeviceObject));
  549. //
  550. // Allocate Descriptor buffer
  551. //
  552. Urb = ExAllocatePoolWithTag(NonPagedPool, TypeSize, HIDUSB_TAG);
  553. if (Urb){
  554. RtlZeroMemory(Urb, TypeSize);
  555. //
  556. // Allocate Buffer for Caller if wanted
  557. //
  558. if (!*Descriptor){
  559. ASSERT(*DescSize > 0);
  560. *Descriptor = ExAllocatePoolWithTag(NonPagedPool, *DescSize, HIDUSB_TAG);
  561. AllocOnBehalf = TRUE;
  562. }
  563. if (*Descriptor){
  564. RtlZeroMemory(*Descriptor, *DescSize);
  565. HumBuildGetDescriptorRequest(Urb,
  566. (USHORT) Function,
  567. (SHORT)TypeSize,
  568. (UCHAR) DescriptorType,
  569. (UCHAR) Index,
  570. (USHORT) LangID,
  571. *Descriptor,
  572. NULL,
  573. *DescSize,
  574. NULL);
  575. ntStatus = HumCallUSB(DeviceObject, Urb);
  576. if (NT_SUCCESS(ntStatus)){
  577. DBGPRINT(1,("Descriptor = %x, length = %x, status = %x", *Descriptor, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbHeader.Status));
  578. if (USBD_SUCCESS(Urb->UrbHeader.Status)){
  579. ntStatus = STATUS_SUCCESS;
  580. *DescSize = Urb->UrbControlDescriptorRequest.TransferBufferLength;
  581. }
  582. else {
  583. ntStatus = STATUS_UNSUCCESSFUL;
  584. goto HumGetDescriptorRequestFailure;
  585. }
  586. }
  587. else {
  588. HumGetDescriptorRequestFailure:
  589. if (AllocOnBehalf) {
  590. ExFreePool(*Descriptor);
  591. *Descriptor = NULL;
  592. }
  593. *DescSize = 0;
  594. }
  595. }
  596. else {
  597. ntStatus = STATUS_NO_MEMORY;
  598. }
  599. ExFreePool(Urb);
  600. }
  601. else {
  602. ntStatus = STATUS_NO_MEMORY;
  603. }
  604. DBGPRINT(1,("HumGetDescriptorRequest Exit = %x", ntStatus));
  605. return ntStatus;
  606. }
  607. NTSTATUS HumCallUsbComplete(IN PDEVICE_OBJECT DeviceObject,
  608. IN PIRP Irp,
  609. IN PKEVENT Event)
  610. {
  611. ASSERT(Event);
  612. KeSetEvent(Event, 0, FALSE);
  613. return STATUS_MORE_PROCESSING_REQUIRED;
  614. }
  615. NTSTATUS HumCallUSB(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb)
  616. /*++
  617. Routine Description:
  618. Passes a URB to the USBD class driver
  619. Arguments:
  620. DeviceObject - pointer to the device object for this instance of a UTB
  621. Urb - pointer to Urb request block
  622. Return Value:
  623. STATUS_SUCCESS if successful,
  624. STATUS_UNSUCCESSFUL otherwise
  625. --*/
  626. {
  627. NTSTATUS ntStatus;
  628. PDEVICE_EXTENSION DeviceExtension;
  629. PIRP Irp;
  630. KEVENT event;
  631. IO_STATUS_BLOCK ioStatus;
  632. PIO_STACK_LOCATION NextStack;
  633. DBGPRINT(2,("HumCallUSB Entry"));
  634. DBGPRINT(2,("DeviceObject = %x", DeviceObject));
  635. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  636. DBGPRINT(2,("DeviceExtension = %x", DeviceExtension));
  637. //
  638. // issue a synchronous request to read the UTB
  639. //
  640. KeInitializeEvent(&event, NotificationEvent, FALSE);
  641. Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
  642. GET_NEXT_DEVICE_OBJECT(DeviceObject),
  643. NULL,
  644. 0,
  645. NULL,
  646. 0,
  647. TRUE, /* INTERNAL */
  648. &event,
  649. &ioStatus);
  650. if (Irp){
  651. DBGPRINT(2,("Irp = %x", Irp));
  652. DBGPRINT(2,("PDO = %x", GET_NEXT_DEVICE_OBJECT(DeviceObject)));
  653. //
  654. // Set a completion routine so that we can avoid this race condition:
  655. // 1) Wait times out.
  656. // 2) Irp completes and gets freed
  657. // 3) We call IoCancelIrp (boom!)
  658. //
  659. IoSetCompletionRoutine(
  660. Irp,
  661. HumCallUsbComplete,
  662. &event,
  663. TRUE,
  664. TRUE,
  665. TRUE
  666. );
  667. //
  668. // pass the URB to the USB 'class driver'
  669. //
  670. NextStack = IoGetNextIrpStackLocation(Irp);
  671. ASSERT(NextStack != NULL);
  672. DBGPRINT(2,("NextStack = %x", NextStack));
  673. NextStack->Parameters.Others.Argument1 = Urb;
  674. DBGPRINT(2,("Calling USBD"));
  675. ntStatus = IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
  676. DBGPRINT(2,("IoCallDriver(USBD) = %x", ntStatus));
  677. if (ntStatus == STATUS_PENDING) {
  678. NTSTATUS waitStatus;
  679. /*
  680. * Specify a timeout of 5 seconds for this call to complete.
  681. */
  682. static LARGE_INTEGER timeout = {(ULONG) -50000000, 0xFFFFFFFF };
  683. DBGPRINT(2,("Wait for single object"));
  684. waitStatus = KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, &timeout);
  685. if (waitStatus == STATUS_TIMEOUT){
  686. DBGWARN(("URB timed out after 5 seconds in HumCallUSB() !!"));
  687. //
  688. // Cancel the Irp we just sent.
  689. //
  690. IoCancelIrp(Irp);
  691. //
  692. // Now wait for the Irp to be cancelled/completed below
  693. //
  694. waitStatus = KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
  695. /*
  696. * Note - Return STATUS_IO_TIMEOUT, not STATUS_TIMEOUT.
  697. * STATUS_IO_TIMEOUT is an NT error status, STATUS_TIMEOUT is not.
  698. */
  699. ioStatus.Status = STATUS_IO_TIMEOUT;
  700. }
  701. DBGPRINT(2,("Wait for single object returned %x", waitStatus));
  702. }
  703. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  704. if (ntStatus == STATUS_PENDING) {
  705. //
  706. // If the request was asynchronous, the iostatus field has
  707. // our real status.
  708. //
  709. ntStatus = ioStatus.Status;
  710. }
  711. DBGPRINT(2,("URB status = %x status = %x", Urb->UrbHeader.Status, ntStatus));
  712. }
  713. else {
  714. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  715. }
  716. DBGPRINT(2,("HumCallUSB Exit = %x", ntStatus));
  717. return ntStatus;
  718. }
  719. #if DBG
  720. NTSTATUS DumpConfigDescriptor( IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc,
  721. IN ULONG DescriptorLength)
  722. /*++
  723. Routine Description:
  724. Dumps a given config descriptor
  725. Arguments:
  726. ConfigDesc - pointer to the USB configuration descriptor
  727. DescriptorLength - length of config descriptor
  728. Return Value:
  729. NT status code.
  730. --*/
  731. {
  732. NTSTATUS ntStatus = STATUS_SUCCESS;
  733. ULONG iInterface;
  734. ULONG iEndpoint;
  735. ULONG iCommon;
  736. PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
  737. PUSB_ENDPOINT_DESCRIPTOR EndpointDesc;
  738. PUSB_COMMON_DESCRIPTOR CommonDesc;
  739. PUSB_HID_DESCRIPTOR pHidDescriptor = NULL;
  740. PVOID EndOfDescriptor;
  741. //
  742. // Determine end of valid data
  743. //
  744. if (ConfigDesc->wTotalLength > DescriptorLength) {
  745. EndOfDescriptor = (PVOID)((ULONG_PTR)ConfigDesc + DescriptorLength);
  746. }
  747. else {
  748. EndOfDescriptor = (PVOID)((ULONG_PTR)ConfigDesc + ConfigDesc->wTotalLength);
  749. }
  750. DBGPRINT(2,("EndOfDescriptor = 0x%x", EndOfDescriptor));
  751. //
  752. // Begin parsing config descriptor
  753. //
  754. DBGPRINT(2,("Config = 0x%x", ConfigDesc));
  755. DBGPRINT(2,("Config->bLength = 0x%x", ConfigDesc->bLength));
  756. DBGPRINT(2,("Config->bDescriptorType = 0x%x", ConfigDesc->bDescriptorType));
  757. DBGPRINT(2,("Config->wTotalLength = 0x%x", ConfigDesc->wTotalLength));
  758. DBGPRINT(2,("Config->bNumInterfaces = 0x%x", ConfigDesc->bNumInterfaces));
  759. DBGPRINT(2,("Config->bConfigurationValue = 0x%x", ConfigDesc->bConfigurationValue));
  760. DBGPRINT(2,("Config->iConfiguration = 0x%x", ConfigDesc->iConfiguration));
  761. DBGPRINT(2,("Config->bmAttributes = 0x%x", ConfigDesc->bmAttributes));
  762. DBGPRINT(2,("Config->MaxPower = 0x%x", ConfigDesc->MaxPower));
  763. ASSERT (ConfigDesc->bLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
  764. #ifndef STRICT_COMPLIANCE
  765. if (ConfigDesc->bLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
  766. DBGPRINT(2,("WARINING -- Correcting bad Config->bLength"));
  767. ConfigDesc->bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
  768. }
  769. #endif
  770. //
  771. // Walk interfaces
  772. //
  773. InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) ((ULONG_PTR)ConfigDesc + ConfigDesc->bLength);
  774. for (iInterface = 0; iInterface < ConfigDesc->bNumInterfaces; iInterface++) {
  775. DBGPRINT(2,("Interface[%d] = 0x%x", iInterface, InterfaceDesc));
  776. DBGPRINT(2,("Interface[%d]->bLength = 0x%x", iInterface, InterfaceDesc->bLength));
  777. DBGPRINT(2,("Interface[%d]->bDescriptorType = 0x%x", iInterface, InterfaceDesc->bDescriptorType));
  778. DBGPRINT(2,("Interface[%d]->bInterfaceNumber = 0x%x", iInterface, InterfaceDesc->bNumEndpoints));
  779. DBGPRINT(2,("Interface[%d]->bAlternateSetting = 0x%x", iInterface, InterfaceDesc->bAlternateSetting));
  780. DBGPRINT(2,("Interface[%d]->bNumEndpoints = 0x%x", iInterface, InterfaceDesc->bNumEndpoints));
  781. DBGPRINT(2,("Interface[%d]->bInterfaceClass = 0x%x", iInterface, InterfaceDesc->bInterfaceClass));
  782. DBGPRINT(2,("Interface[%d]->bInterfaceSubClass = 0x%x", iInterface, InterfaceDesc->bInterfaceSubClass));
  783. DBGPRINT(2,("Interface[%d]->bInterfaceProtocol = 0x%x", iInterface, InterfaceDesc->bInterfaceProtocol));
  784. DBGPRINT(2,("Interface[%d]->iInterface = 0x%x", iInterface, InterfaceDesc->iInterface));
  785. ASSERT (InterfaceDesc->bLength >= sizeof(USB_INTERFACE_DESCRIPTOR));
  786. CommonDesc = (PUSB_COMMON_DESCRIPTOR) ((ULONG_PTR)InterfaceDesc + InterfaceDesc->bLength);
  787. if (CommonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) {
  788. DBGPRINT(2,("HID Device < HID 1.0 Draft 4 spec compliant"));
  789. //
  790. // Walk endpoints for old style device
  791. //
  792. EndpointDesc = (PUSB_ENDPOINT_DESCRIPTOR) CommonDesc;
  793. for (iEndpoint = 0; iEndpoint < InterfaceDesc->bNumEndpoints; iEndpoint++) {
  794. DBGPRINT(2,("Endpoint[%d] = 0x%x", iEndpoint, EndpointDesc));
  795. DBGPRINT(2,("Endpoint[%d]->bLength = 0x%x", iEndpoint, EndpointDesc->bLength));
  796. DBGPRINT(2,("Endpoint[%d]->bDescriptorType = 0x%x", iEndpoint, EndpointDesc->bDescriptorType));
  797. DBGPRINT(2,("Endpoint[%d]->bEndpointAddress = 0x%x", iEndpoint, EndpointDesc->bEndpointAddress));
  798. ASSERT (EndpointDesc->bLength >= sizeof(USB_ENDPOINT_DESCRIPTOR));
  799. EndpointDesc = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDesc + EndpointDesc->bLength);
  800. }
  801. CommonDesc = (PUSB_COMMON_DESCRIPTOR) EndpointDesc;
  802. }
  803. else {
  804. DBGPRINT(2,("HID Device is HID 1.0 Draft 4 compliant"));
  805. }
  806. //
  807. // Walk misc/common descriptors
  808. //
  809. iCommon = 0;
  810. while (((PVOID)CommonDesc < EndOfDescriptor) &&
  811. (CommonDesc->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE) &&
  812. (CommonDesc->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE)) {
  813. DBGPRINT(2,("Common[%d] = 0x%x", iCommon, CommonDesc));
  814. DBGPRINT(2,("Common[%d]->bLength = 0x%x", iCommon, CommonDesc->bLength));
  815. DBGPRINT(2,("Common[%d]->bDescriptorType = 0x%x", iCommon, CommonDesc->bDescriptorType));
  816. ASSERT (CommonDesc->bLength >= sizeof(USB_COMMON_DESCRIPTOR));
  817. if (CommonDesc->bLength == 0) {
  818. DBGPRINT(2,("WARNING: Common[%d]->bLength = 0x%x", iCommon, CommonDesc->bLength));
  819. break;
  820. }
  821. //
  822. // Is this a HID Interface?
  823. //
  824. if (InterfaceDesc->bInterfaceClass == USB_INTERFACE_CLASS_HID) {
  825. //
  826. // Is this the HID Descriptor?
  827. //
  828. if (CommonDesc->bDescriptorType == USB_DESCRIPTOR_TYPE_HID) {
  829. pHidDescriptor = (PUSB_HID_DESCRIPTOR) CommonDesc;
  830. }
  831. else {
  832. //
  833. // This is either an unknown type of descriptor or the device is
  834. // reporting back a bad descriptor type.
  835. //
  836. DBGPRINT(2,("WARINING -- Unknown descriptor in HID interface"));
  837. #ifndef STRICT_COMPLIANCE
  838. if (CommonDesc->bLength == sizeof(USB_HID_DESCRIPTOR)) {
  839. DBGPRINT(2,("WARINING -- Guessing descriptor of length %d is actually HID!", sizeof(USB_HID_DESCRIPTOR)));
  840. pHidDescriptor = (PUSB_HID_DESCRIPTOR) CommonDesc;
  841. break;
  842. }
  843. #endif
  844. }
  845. }
  846. CommonDesc = (PUSB_COMMON_DESCRIPTOR) ((ULONG_PTR)CommonDesc + CommonDesc->bLength);
  847. iCommon++;
  848. }
  849. if (CommonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) {
  850. //
  851. // Walk endpoints for full draft 4 HID 1.0 device
  852. //
  853. EndpointDesc = (PUSB_ENDPOINT_DESCRIPTOR) CommonDesc;
  854. for (iEndpoint = 0; iEndpoint < InterfaceDesc->bNumEndpoints; iEndpoint++) {
  855. DBGPRINT(2,("Endpoint[%d] = 0x%x", iEndpoint, EndpointDesc));
  856. DBGPRINT(2,("Endpoint[%d]->bLength = 0x%x", iEndpoint, EndpointDesc->bLength));
  857. DBGPRINT(2,("Endpoint[%d]->bDescriptorType = 0x%x", iEndpoint, EndpointDesc->bDescriptorType));
  858. DBGPRINT(2,("Endpoint[%d]->bEndpointAddress = 0x%x", iEndpoint, EndpointDesc->bEndpointAddress));
  859. ASSERT (EndpointDesc->bLength >= sizeof(USB_ENDPOINT_DESCRIPTOR));
  860. EndpointDesc = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDesc + EndpointDesc->bLength);
  861. }
  862. CommonDesc = (PUSB_COMMON_DESCRIPTOR) EndpointDesc;
  863. }
  864. //
  865. // If we have found the HID descriptor, we don't need to look at the
  866. // rest of the interfaces for this device.
  867. //
  868. if (pHidDescriptor) {
  869. break;
  870. }
  871. InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) CommonDesc;
  872. }
  873. if (pHidDescriptor) {
  874. ASSERT (pHidDescriptor->bLength >= sizeof(USB_HID_DESCRIPTOR));
  875. DBGPRINT(2,("pHidDescriptor = 0x%x", pHidDescriptor));
  876. DBGPRINT(2,("pHidDescriptor->bLength = 0x%x", pHidDescriptor->bLength));
  877. DBGPRINT(2,("pHidDescriptor->bDescriptorType = 0x%x", pHidDescriptor->bDescriptorType));
  878. DBGPRINT(2,("pHidDescriptor->bcdHID = 0x%x", pHidDescriptor->bcdHID));
  879. DBGPRINT(2,("pHidDescriptor->bCountryCode = 0x%x", pHidDescriptor->bCountry));
  880. DBGPRINT(2,("pHidDescriptor->bNumDescriptors = 0x%x", pHidDescriptor->bNumDescriptors));
  881. DBGPRINT(2,("pHidDescriptor->bReportType = 0x%x", pHidDescriptor->bReportType));
  882. DBGPRINT(2,("pHidDescriptor->wReportLength = 0x%x", pHidDescriptor->wReportLength));
  883. }
  884. else {
  885. //
  886. // We did not find a HID interface or HID descriptor!
  887. //
  888. DBGPRINT(2,("Failed to find a HID Descriptor!"));
  889. DBGBREAK;
  890. ntStatus = STATUS_UNSUCCESSFUL;
  891. }
  892. return ntStatus;
  893. }
  894. #endif