Leaked source code of windows server 2003
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.

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