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.

1746 lines
57 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. USB.C
  5. Abstract:
  6. This source file contains the functions for communicating with
  7. the usb bus.
  8. Environment:
  9. kernel mode
  10. Revision History:
  11. Sep 2001 : Copied from USBMASS
  12. --*/
  13. //*****************************************************************************
  14. // I N C L U D E S
  15. //*****************************************************************************
  16. #include "genusb.h"
  17. //*****************************************************************************
  18. // L O C A L F U N C T I O N P R O T O T Y P E S
  19. //*****************************************************************************
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(PAGE, GenUSB_GetDescriptor)
  22. #pragma alloc_text(PAGE, GenUSB_GetDescriptors)
  23. #pragma alloc_text(PAGE, GenUSB_GetStringDescriptors)
  24. #pragma alloc_text(PAGE, GenUSB_VendorControlRequest)
  25. #pragma alloc_text(PAGE, GenUSB_ResetPipe)
  26. #endif
  27. //******************************************************************************
  28. //
  29. // GenUSB_GetDescriptors()
  30. //
  31. // This routine is called at START_DEVICE time for the FDO to retrieve the
  32. // Device and Configurations descriptors from the device and store them in
  33. // the device extension.
  34. //
  35. //******************************************************************************
  36. NTSTATUS
  37. GenUSB_GetDescriptors (
  38. IN PDEVICE_OBJECT DeviceObject
  39. )
  40. {
  41. PDEVICE_EXTENSION deviceExtension;
  42. PUCHAR descriptor;
  43. ULONG descriptorLength;
  44. NTSTATUS status;
  45. PAGED_CODE();
  46. DBGPRINT(2, ("enter: GenUSB_GetDescriptors\n"));
  47. deviceExtension = DeviceObject->DeviceExtension;
  48. descriptor = NULL;
  49. LOGENTRY(deviceExtension, 'GDSC', DeviceObject, 0, 0);
  50. //
  51. // Get Device Descriptor
  52. //
  53. status = GenUSB_GetDescriptor(DeviceObject,
  54. USB_RECIPIENT_DEVICE,
  55. USB_DEVICE_DESCRIPTOR_TYPE,
  56. 0, // Index
  57. 0, // LanguageId
  58. 2, // RetryCount
  59. sizeof(USB_DEVICE_DESCRIPTOR),
  60. &descriptor);
  61. if (!NT_SUCCESS(status))
  62. {
  63. DBGPRINT(1, ("Get Device Descriptor failed\n"));
  64. goto GenUSB_GetDescriptorsDone;
  65. }
  66. ASSERT(NULL == deviceExtension->DeviceDescriptor);
  67. deviceExtension->DeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)descriptor;
  68. descriptor = NULL;
  69. //
  70. // Get Configuration Descriptor (just the Configuration Descriptor)
  71. //
  72. status = GenUSB_GetDescriptor(DeviceObject,
  73. USB_RECIPIENT_DEVICE,
  74. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  75. 0, // Index
  76. 0, // LanguageId
  77. 2, // RetryCount
  78. sizeof(USB_CONFIGURATION_DESCRIPTOR),
  79. &descriptor);
  80. if (!NT_SUCCESS(status))
  81. {
  82. DBGPRINT(1, ("Get Configuration Descriptor failed (1)\n"));
  83. goto GenUSB_GetDescriptorsDone;
  84. }
  85. descriptorLength = ((PUSB_CONFIGURATION_DESCRIPTOR)descriptor)->wTotalLength;
  86. ExFreePool(descriptor);
  87. descriptor = NULL;
  88. if (descriptorLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
  89. {
  90. status = STATUS_DEVICE_DATA_ERROR;
  91. DBGPRINT(1, ("Get Configuration Descriptor failed (2)\n"));
  92. goto GenUSB_GetDescriptorsDone;
  93. }
  94. //
  95. // Get Configuration Descriptor (and Interface and Endpoint Descriptors)
  96. //
  97. status = GenUSB_GetDescriptor(DeviceObject,
  98. USB_RECIPIENT_DEVICE,
  99. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  100. 0, // Index
  101. 0, // LanguageId
  102. 2, // RetryCount
  103. descriptorLength,
  104. &descriptor);
  105. if (!NT_SUCCESS(status))
  106. {
  107. DBGPRINT(1, ("Get Configuration Descriptor failed (3)\n"));
  108. goto GenUSB_GetDescriptorsDone;
  109. }
  110. ASSERT(NULL == deviceExtension->ConfigurationDescriptor);
  111. deviceExtension->ConfigurationDescriptor =
  112. (PUSB_CONFIGURATION_DESCRIPTOR)descriptor;
  113. //
  114. // Get the Serial Number String Descriptor, if there is one
  115. //
  116. if (deviceExtension->DeviceDescriptor->iSerialNumber)
  117. {
  118. GenUSB_GetStringDescriptors(DeviceObject);
  119. }
  120. #if DBG
  121. DumpDeviceDesc(deviceExtension->DeviceDescriptor);
  122. DumpConfigDesc(deviceExtension->ConfigurationDescriptor);
  123. #endif
  124. GenUSB_GetDescriptorsDone:
  125. DBGPRINT(2, ("exit: GenUSB_GetDescriptors %08X\n", status));
  126. LOGENTRY(deviceExtension,
  127. 'gdsc',
  128. status,
  129. deviceExtension->DeviceDescriptor,
  130. deviceExtension->ConfigurationDescriptor);
  131. return status;
  132. }
  133. //******************************************************************************
  134. //
  135. // GenUSB_GetDescriptor()
  136. //
  137. // Must be called at IRQL PASSIVE_LEVEL
  138. //
  139. //******************************************************************************
  140. NTSTATUS
  141. GenUSB_GetDescriptor (
  142. IN PDEVICE_OBJECT DeviceObject,
  143. IN UCHAR Function,
  144. IN UCHAR DescriptorType,
  145. IN UCHAR Index,
  146. IN USHORT LanguageId,
  147. IN ULONG RetryCount,
  148. IN ULONG DescriptorLength,
  149. OUT PUCHAR *Descriptor
  150. )
  151. {
  152. PURB urb;
  153. NTSTATUS status;
  154. BOOLEAN descriptorAllocated = FALSE;
  155. PAGED_CODE();
  156. DBGPRINT(2, ("enter: GenUSB_GetDescriptor\n"));
  157. if (NULL == *Descriptor)
  158. {
  159. // Allocate a descriptor buffer
  160. *Descriptor = ExAllocatePool(NonPagedPool, DescriptorLength);
  161. descriptorAllocated = TRUE;
  162. }
  163. if (NULL != *Descriptor)
  164. {
  165. // Allocate a URB for the Get Descriptor request
  166. urb = ExAllocatePool(NonPagedPool,
  167. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  168. if (NULL != urb)
  169. {
  170. do
  171. {
  172. // Initialize the URB
  173. urb->UrbHeader.Function = Function;
  174. urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
  175. urb->UrbControlDescriptorRequest.TransferBufferLength = DescriptorLength;
  176. urb->UrbControlDescriptorRequest.TransferBuffer = *Descriptor;
  177. urb->UrbControlDescriptorRequest.TransferBufferMDL = NULL;
  178. urb->UrbControlDescriptorRequest.UrbLink = NULL;
  179. urb->UrbControlDescriptorRequest.DescriptorType = DescriptorType;
  180. urb->UrbControlDescriptorRequest.Index = Index;
  181. urb->UrbControlDescriptorRequest.LanguageId = LanguageId;
  182. // Send the URB down the stack
  183. status = GenUSB_SyncSendUsbRequest(DeviceObject, urb);
  184. if (NT_SUCCESS(status))
  185. {
  186. // No error, make sure the length and type are correct
  187. if ((DescriptorLength ==
  188. urb->UrbControlDescriptorRequest.TransferBufferLength) &&
  189. (DescriptorType ==
  190. ((PUSB_COMMON_DESCRIPTOR)*Descriptor)->bDescriptorType))
  191. {
  192. // The length and type are correct, all done
  193. break;
  194. }
  195. else
  196. {
  197. // No error, but the length or type is incorrect
  198. status = STATUS_DEVICE_DATA_ERROR;
  199. }
  200. }
  201. } while (RetryCount-- > 0);
  202. ExFreePool(urb);
  203. }
  204. else
  205. {
  206. // Failed to allocate the URB
  207. status = STATUS_INSUFFICIENT_RESOURCES;
  208. }
  209. }
  210. else
  211. {
  212. // Failed to allocate the descriptor buffer
  213. status = STATUS_INSUFFICIENT_RESOURCES;
  214. }
  215. if (!NT_SUCCESS(status))
  216. {
  217. if ((*Descriptor != NULL) && descriptorAllocated)
  218. {
  219. ExFreePool(*Descriptor);
  220. *Descriptor = NULL;
  221. }
  222. }
  223. DBGPRINT(2, ("exit: GenUSB_GetDescriptor %08X\n", status));
  224. return status;
  225. }
  226. //******************************************************************************
  227. //
  228. // GenUSB_GetStringDescriptors()
  229. //
  230. // This routine is called at START_DEVICE time for the FDO to retrieve the
  231. // Serial Number string descriptor from the device and store it in
  232. // the device extension.
  233. //
  234. //******************************************************************************
  235. GenUSB_GetStringDescriptors (
  236. IN PDEVICE_OBJECT DeviceObject
  237. )
  238. {
  239. PDEVICE_EXTENSION deviceExtension;
  240. PUCHAR descriptor;
  241. ULONG descriptorLength;
  242. ULONG i, numIds;
  243. NTSTATUS status;
  244. PAGED_CODE();
  245. DBGPRINT(2, ("enter: GenUSB_GetStringDescriptors\n"));
  246. deviceExtension = DeviceObject->DeviceExtension;
  247. descriptor = NULL;
  248. LOGENTRY(deviceExtension, 'GSDC', DeviceObject, 0, 0);
  249. // Get the list of Language IDs (descriptor header only)
  250. status = GenUSB_GetDescriptor(DeviceObject,
  251. USB_RECIPIENT_DEVICE,
  252. USB_STRING_DESCRIPTOR_TYPE,
  253. 0, // Index
  254. 0, // LanguageId
  255. 2, // RetryCount
  256. sizeof(USB_COMMON_DESCRIPTOR),
  257. &descriptor);
  258. if (!NT_SUCCESS(status))
  259. {
  260. DBGPRINT(1, ("Get Language IDs failed (1) %08X\n", status));
  261. goto GenUSB_GetStringDescriptorsDone;
  262. }
  263. descriptorLength = ((PUSB_COMMON_DESCRIPTOR)descriptor)->bLength;
  264. ExFreePool(descriptor);
  265. descriptor = NULL;
  266. if ((descriptorLength < sizeof(USB_COMMON_DESCRIPTOR) + sizeof(USHORT)) ||
  267. (descriptorLength & 1))
  268. {
  269. status = STATUS_DEVICE_DATA_ERROR;
  270. DBGPRINT(1, ("Get Language IDs failed (2) %d\n", descriptorLength));
  271. goto GenUSB_GetStringDescriptorsDone;
  272. }
  273. // Get the list of Language IDs (complete descriptor)
  274. status = GenUSB_GetDescriptor(DeviceObject,
  275. USB_RECIPIENT_DEVICE,
  276. USB_STRING_DESCRIPTOR_TYPE,
  277. 0, // Index
  278. 0, // LanguageId
  279. 2, // RetryCount
  280. descriptorLength,
  281. &descriptor);
  282. if (!NT_SUCCESS(status))
  283. {
  284. DBGPRINT(1, ("Get Language IDs failed (3) %08X\n", status));
  285. goto GenUSB_GetStringDescriptorsDone;
  286. }
  287. // Search the list of LanguageIDs for US-English (0x0409). If we find
  288. // it in the list, that's the LanguageID we'll use. Else just default
  289. // to the first LanguageID in the list.
  290. numIds = (descriptorLength - sizeof(USB_COMMON_DESCRIPTOR)) / sizeof(USHORT);
  291. deviceExtension->LanguageId = ((PUSHORT)descriptor)[1];
  292. for (i = 2; i <= numIds; i++)
  293. {
  294. if (((PUSHORT)descriptor)[i] == 0x0409)
  295. {
  296. deviceExtension->LanguageId = 0x0409;
  297. break;
  298. }
  299. }
  300. ExFreePool(descriptor);
  301. descriptor = NULL;
  302. //
  303. // Get the Serial Number (descriptor header only)
  304. //
  305. status = GenUSB_GetDescriptor(DeviceObject,
  306. USB_RECIPIENT_DEVICE,
  307. USB_STRING_DESCRIPTOR_TYPE,
  308. deviceExtension->DeviceDescriptor->iSerialNumber,
  309. deviceExtension->LanguageId,
  310. 2, // RetryCount
  311. sizeof(USB_COMMON_DESCRIPTOR),
  312. &descriptor);
  313. if (!NT_SUCCESS(status))
  314. {
  315. DBGPRINT(1, ("Get Serial Number failed (1) %08X\n", status));
  316. goto GenUSB_GetStringDescriptorsDone;
  317. }
  318. descriptorLength = ((PUSB_COMMON_DESCRIPTOR)descriptor)->bLength;
  319. ExFreePool(descriptor);
  320. descriptor = NULL;
  321. if ((descriptorLength < sizeof(USB_COMMON_DESCRIPTOR) + sizeof(USHORT)) ||
  322. (descriptorLength & 1))
  323. {
  324. status = STATUS_DEVICE_DATA_ERROR;
  325. DBGPRINT(1, ("Get Serial Number failed (2) %d\n", descriptorLength));
  326. goto GenUSB_GetStringDescriptorsDone;
  327. }
  328. //
  329. // Get the Serial Number (complete descriptor)
  330. //
  331. status = GenUSB_GetDescriptor(DeviceObject,
  332. USB_RECIPIENT_DEVICE,
  333. USB_STRING_DESCRIPTOR_TYPE,
  334. deviceExtension->DeviceDescriptor->iSerialNumber,
  335. deviceExtension->LanguageId,
  336. 2, // RetryCount
  337. descriptorLength,
  338. &descriptor);
  339. if (!NT_SUCCESS(status))
  340. {
  341. DBGPRINT(1, ("Get Serial Number failed (3) %08X\n", status));
  342. goto GenUSB_GetStringDescriptorsDone;
  343. }
  344. ASSERT(NULL == deviceExtension->SerialNumber);
  345. deviceExtension->SerialNumber = (PUSB_STRING_DESCRIPTOR)descriptor;
  346. GenUSB_GetStringDescriptorsDone:
  347. DBGPRINT(2, ("exit: GenUSB_GetStringDescriptors %08X %08X\n",
  348. status, deviceExtension->SerialNumber));
  349. LOGENTRY(deviceExtension,
  350. 'gdsc',
  351. status,
  352. deviceExtension->LanguageId,
  353. deviceExtension->SerialNumber);
  354. return status;
  355. }
  356. NTSTATUS
  357. GenUSB_VendorControlRequest (
  358. IN PDEVICE_OBJECT DeviceObject,
  359. IN UCHAR RequestType,
  360. IN UCHAR Request,
  361. IN USHORT Value,
  362. IN USHORT Index,
  363. IN USHORT Length,
  364. IN ULONG RetryCount,
  365. OUT PULONG UrbStatus,
  366. OUT PUSHORT ResultLength,
  367. OUT PUCHAR *Descriptor
  368. )
  369. {
  370. PURB urb;
  371. NTSTATUS status;
  372. BOOLEAN descriptorAllocated = FALSE;
  373. PAGED_CODE();
  374. DBGPRINT(2, ("enter: GenUSB_GetDescriptor\n"));
  375. if (NULL == *Descriptor)
  376. {
  377. // Allocate a descriptor buffer
  378. *Descriptor = ExAllocatePool(NonPagedPool, Length);
  379. descriptorAllocated = TRUE;
  380. }
  381. if (NULL != *Descriptor)
  382. {
  383. // Allocate a URB for the Get Descriptor request
  384. urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_TRANSFER));
  385. if (NULL != urb)
  386. {
  387. do
  388. {
  389. // Initialize the URB
  390. urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
  391. urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_TRANSFER);
  392. urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
  393. urb->UrbControlTransfer.PipeHandle = NULL;
  394. urb->UrbControlTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN
  395. | USBD_DEFAULT_PIPE_TRANSFER
  396. | USBD_SHORT_TRANSFER_OK;
  397. urb->UrbControlTransfer.TransferBufferLength = Length;
  398. urb->UrbControlTransfer.TransferBuffer = *Descriptor;
  399. urb->UrbControlTransfer.TransferBufferMDL = NULL;
  400. urb->UrbControlTransfer.UrbLink = NULL;
  401. urb->UrbControlTransfer.SetupPacket [0] = RequestType;
  402. urb->UrbControlTransfer.SetupPacket [1] = Request;
  403. ((WCHAR *) urb->UrbControlTransfer.SetupPacket) [1] = Value;
  404. ((WCHAR *) urb->UrbControlTransfer.SetupPacket) [2] = Index;
  405. ((WCHAR *) urb->UrbControlTransfer.SetupPacket) [3] = Length;
  406. // Send the URB down the stack
  407. status = GenUSB_SyncSendUsbRequest(DeviceObject, urb);
  408. if (NT_SUCCESS(status))
  409. {
  410. break;
  411. }
  412. } while (RetryCount-- > 0);
  413. *UrbStatus = urb->UrbHeader.Status;
  414. *ResultLength = (USHORT) urb->UrbControlTransfer.TransferBufferLength;
  415. ExFreePool(urb);
  416. }
  417. else
  418. {
  419. // Failed to allocate the URB
  420. status = STATUS_INSUFFICIENT_RESOURCES;
  421. }
  422. }
  423. else
  424. {
  425. // Failed to allocate the descriptor buffer
  426. status = STATUS_INSUFFICIENT_RESOURCES;
  427. }
  428. if (!NT_SUCCESS(status))
  429. {
  430. if ((*Descriptor != NULL) && descriptorAllocated)
  431. {
  432. ExFreePool(*Descriptor);
  433. *Descriptor = NULL;
  434. }
  435. }
  436. DBGPRINT(2, ("exit: GenUSB_GetDescriptor %08X\n", status));
  437. return status;
  438. }
  439. void blah()
  440. {
  441. return;
  442. }
  443. VOID
  444. GenUSB_ParseConfigurationDescriptors(
  445. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  446. IN ULONG NumberInterfaces,
  447. IN USB_INTERFACE_DESCRIPTOR DesiredArray[],
  448. OUT USB_INTERFACE_DESCRIPTOR FoundArray[],
  449. OUT PUCHAR InterfacesFound,
  450. OUT PUSBD_INTERFACE_LIST_ENTRY DescriptorArray
  451. )
  452. /*++
  453. Routine Description:
  454. Parses a standard USB configuration descriptor (returned from a device)
  455. for an array of specific interfaces, alternate setting class subclass or
  456. protocol codes
  457. Arguments:
  458. Return Value:
  459. NT status code.
  460. --*/
  461. {
  462. ULONG i;
  463. ULONG foo;
  464. PUSB_INTERFACE_DESCRIPTOR inter;
  465. PAGED_CODE();
  466. ASSERT (NULL != InterfacesFound);
  467. ASSERT (NULL != DescriptorArray);
  468. *InterfacesFound = 0; // none found yet.
  469. ASSERT(ConfigurationDescriptor->bDescriptorType
  470. == USB_CONFIGURATION_DESCRIPTOR_TYPE);
  471. //
  472. // we walk the table of desired interfaces descriptors looking for an
  473. // looking for all of them in the configuration descriptor
  474. //
  475. //
  476. // here we use ParseConfigurationDescriptorEx, which walks through the
  477. // entire configuration descriptor looking for matches. While this is
  478. // more or less order n^2 things are not much better if done by hand
  479. // so just use the given routine.
  480. //
  481. for (i = 0; i < NumberInterfaces; i++)
  482. {
  483. inter = USBD_ParseConfigurationDescriptorEx (
  484. ConfigurationDescriptor,
  485. ConfigurationDescriptor,
  486. (CHAR) DesiredArray[i].bInterfaceNumber,
  487. (CHAR) DesiredArray[i].bAlternateSetting,
  488. (CHAR) DesiredArray[i].bInterfaceClass,
  489. (CHAR) DesiredArray[i].bInterfaceSubClass,
  490. (CHAR) DesiredArray[i].bInterfaceProtocol);
  491. if (NULL != inter)
  492. {
  493. DescriptorArray[*InterfacesFound].InterfaceDescriptor = inter;
  494. (*InterfacesFound)++;
  495. FoundArray[i] = *inter;
  496. }
  497. }
  498. }
  499. //******************************************************************************
  500. //
  501. // GenUSB_SelectConfiguration()
  502. //
  503. // Must be called at IRQL PASSIVE_LEVEL
  504. //
  505. //******************************************************************************
  506. NTSTATUS
  507. GenUSB_SelectConfiguration (
  508. IN PDEVICE_EXTENSION DeviceExtension,
  509. IN ULONG NumberInterfaces,
  510. IN PUSB_INTERFACE_DESCRIPTOR DesiredArray,
  511. OUT PUSB_INTERFACE_DESCRIPTOR FoundArray
  512. )
  513. {
  514. PGENUSB_INTERFACE inter;
  515. // Apparently the compiler will not allow a local variable of the name
  516. // interface for some probably valid but frustrating reason.
  517. PURB urb;
  518. NTSTATUS status;
  519. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  520. PUSBD_INTERFACE_INFORMATION interfaceInfo;
  521. PUSBD_INTERFACE_LIST_ENTRY interfaceList;
  522. ULONG i,j;
  523. ULONG size;
  524. UCHAR interfacesFound;
  525. BOOLEAN directionIn;
  526. KIRQL irql;
  527. ExAcquireFastMutex (&DeviceExtension->ConfigMutex);
  528. DBGPRINT(2, ("enter: GenUSB_SelectConfiguration\n"));
  529. LOGENTRY(DeviceExtension, 'SCON', DeviceExtension->Self, 0, 0);
  530. urb = 0;
  531. interfaceList = 0;
  532. //
  533. // We shouldn't have a currently selected interface.
  534. // You must unconfigure the device before configuring it again.
  535. //
  536. if (NULL != DeviceExtension->ConfigurationHandle)
  537. {
  538. status = STATUS_INVALID_PARAMETER;
  539. goto GenUSB_SelectConfigurationReject;
  540. }
  541. ASSERT (NULL == DeviceExtension->Interface);
  542. ASSERT (0 == DeviceExtension->InterfacesFound);
  543. configurationDescriptor = DeviceExtension->ConfigurationDescriptor;
  544. // Allocate storage for an Inteface List to use as an input/output
  545. // parameter to USBD_CreateConfigurationRequestEx().
  546. //
  547. interfaceList =
  548. ExAllocatePool(PagedPool,
  549. sizeof(USBD_INTERFACE_LIST_ENTRY) * (NumberInterfaces + 1));
  550. if (NULL == interfaceList)
  551. {
  552. status = STATUS_INSUFFICIENT_RESOURCES;
  553. goto GenUSB_SelectConfigurationReject;
  554. }
  555. // NB we are holding a Fast Mutex whist calling this function
  556. GenUSB_ParseConfigurationDescriptors(configurationDescriptor,
  557. NumberInterfaces,
  558. DesiredArray,
  559. FoundArray,
  560. &interfacesFound,
  561. interfaceList);
  562. if (interfacesFound < NumberInterfaces)
  563. {
  564. // We couldn't select all of the interfaces.
  565. // For now, allow that.
  566. // status = STATUS_INVALID_PARAMETER;
  567. // goto GenUSB_SelectConfigurationReject;
  568. ;
  569. }
  570. ASSERT (interfacesFound <= NumberInterfaces);
  571. // Terminate the list.
  572. interfaceList[interfacesFound].InterfaceDescriptor = NULL;
  573. // Create a SELECT_CONFIGURATION URB, turning the Interface
  574. // Descriptors in the interfaceList into USBD_INTERFACE_INFORMATION
  575. // structures in the URB.
  576. //
  577. // NB we are holding a Fast Mutex whist calling this function
  578. urb = USBD_CreateConfigurationRequestEx(
  579. configurationDescriptor,
  580. interfaceList);
  581. if (NULL == urb)
  582. {
  583. status = STATUS_INSUFFICIENT_RESOURCES;
  584. goto GenUSB_SelectConfigurationReject;
  585. }
  586. // Now issue the USB request to set the Configuration
  587. // NB we are holding a Fast Mutex whist calling this function
  588. status = GenUSB_SyncSendUsbRequest(DeviceExtension->Self, urb);
  589. if (!NT_SUCCESS(status))
  590. {
  591. goto GenUSB_SelectConfigurationReject;
  592. }
  593. KeAcquireSpinLock (&DeviceExtension->SpinLock, &irql);
  594. {
  595. DeviceExtension->InterfacesFound = interfacesFound;
  596. DeviceExtension->TotalNumberOfPipes = 0;
  597. // Save the configuration handle for this device in
  598. // the Device Extension.
  599. DeviceExtension->ConfigurationHandle =
  600. urb->UrbSelectConfiguration.ConfigurationHandle;
  601. //
  602. // Now for each interface in the list...
  603. // Save a copy of the interface information returned
  604. // by the SELECT_CONFIGURATION request in the Device
  605. // Extension. This gives us a list of PIPE_INFORMATION
  606. // structures for each pipe opened in this configuration.
  607. //
  608. size = interfacesFound * sizeof (PVOID);
  609. DeviceExtension->Interface = ExAllocatePool (NonPagedPool, size);
  610. if (NULL == DeviceExtension->Interface)
  611. {
  612. status = STATUS_INSUFFICIENT_RESOURCES;
  613. }
  614. else
  615. {
  616. RtlZeroMemory (DeviceExtension->Interface, size);
  617. interfaceInfo = &urb->UrbSelectConfiguration.Interface;
  618. for (i=0; i < interfacesFound; i++)
  619. {
  620. size = sizeof (GENUSB_INTERFACE)
  621. + (interfaceInfo->NumberOfPipes * sizeof(GENUSB_PIPE_INFO));
  622. inter =
  623. DeviceExtension->Interface[i] =
  624. ExAllocatePool (NonPagedPool, size);
  625. if (inter)
  626. {
  627. RtlZeroMemory (inter, size);
  628. inter->InterfaceNumber = interfaceInfo->InterfaceNumber;
  629. inter->CurrentAlternate = interfaceInfo->AlternateSetting;
  630. inter->Handle = interfaceInfo->InterfaceHandle;
  631. inter->NumberOfPipes = (UCHAR)interfaceInfo->NumberOfPipes;
  632. DeviceExtension->TotalNumberOfPipes += inter->NumberOfPipes;
  633. for (j=0; j < inter->NumberOfPipes; j++)
  634. {
  635. inter->Pipes[j].Info = interfaceInfo->Pipes[j];
  636. // Set the default timeout for this device to be zero.
  637. // (structure already initialized to zero.)
  638. //
  639. // inter->Pipes[j].Properties.DefaultTimeout = 0;
  640. // inter->Pipes[j].CurrentTimeout = 0;
  641. // set the outstanding number of transactions for this
  642. // pipe to be 0.
  643. //
  644. // inter->Pipes[j].OutandingIO = 0;
  645. directionIn =
  646. USBD_PIPE_DIRECTION_IN (&inter->Pipes[j].Info);
  647. if (directionIn)
  648. {
  649. //
  650. // by default we always truncate reads requests from
  651. // the device.
  652. //
  653. inter->Pipes[j].Properties.DirectionIn = TRUE;
  654. inter->Pipes[j].Properties.NoTruncateToMaxPacket = FALSE;
  655. }
  656. }
  657. }
  658. else
  659. {
  660. // Could not allocate a copy of interface information
  661. status = STATUS_INSUFFICIENT_RESOURCES;
  662. break;
  663. }
  664. //
  665. // find the next interfaceInfo
  666. //
  667. interfaceInfo = (PUSBD_INTERFACE_INFORMATION)
  668. ((PUCHAR) interfaceInfo + interfaceInfo->Length);
  669. }
  670. }
  671. //
  672. // Regardless of whether or not we've been successful...
  673. // We've just invalidated the pipe table so blow away the
  674. // read and write values.
  675. //
  676. DeviceExtension->ReadInterface = -1;
  677. DeviceExtension->ReadPipe = -1;
  678. DeviceExtension->WriteInterface = -1;
  679. DeviceExtension->WritePipe = -1;
  680. }
  681. KeReleaseSpinLock (&DeviceExtension->SpinLock, irql);
  682. if (!NT_SUCCESS (status))
  683. {
  684. goto GenUSB_SelectConfigurationReject;
  685. }
  686. IoInitializeRemoveLock (&DeviceExtension->ConfigurationRemoveLock,
  687. POOL_TAG,
  688. 0,
  689. 0);
  690. IoStartTimer (DeviceExtension->Self);
  691. ExFreePool(urb);
  692. ExFreePool(interfaceList);
  693. DBGPRINT(2, ("exit: GenUSB_SelectConfiguration %08X\n", status));
  694. LOGENTRY(DeviceExtension, 'scon', 0, 0, status);
  695. ExReleaseFastMutex (&DeviceExtension->ConfigMutex);
  696. return status;
  697. GenUSB_SelectConfigurationReject:
  698. if (interfaceList)
  699. {
  700. ExFreePool (interfaceList);
  701. }
  702. if (urb)
  703. {
  704. ExFreePool (urb);
  705. }
  706. GenUSB_FreeInterfaceTable (DeviceExtension);
  707. LOGENTRY(DeviceExtension, 'scon', 0, 0, status);
  708. ExReleaseFastMutex (&DeviceExtension->ConfigMutex);
  709. return status;
  710. }
  711. VOID
  712. GenUSB_FreeInterfaceTable (
  713. PDEVICE_EXTENSION DeviceExtension
  714. )
  715. {
  716. KIRQL irql;
  717. ULONG i;
  718. KeAcquireSpinLock (&DeviceExtension->SpinLock, &irql);
  719. {
  720. if (DeviceExtension->Interface)
  721. {
  722. for (i = 0; i < DeviceExtension->InterfacesFound; i++)
  723. {
  724. if (DeviceExtension->Interface[i])
  725. {
  726. ExFreePool (DeviceExtension->Interface[i]);
  727. }
  728. }
  729. ExFreePool (DeviceExtension->Interface);
  730. DeviceExtension->Interface = 0;
  731. }
  732. DeviceExtension->InterfacesFound = 0;
  733. DeviceExtension->ConfigurationHandle = NULL; // Freed automatically by USB
  734. }
  735. KeReleaseSpinLock (&DeviceExtension->SpinLock, irql);
  736. }
  737. //******************************************************************************
  738. //
  739. // GenUSB_UnConfigure()
  740. //
  741. // Must be called at IRQL PASSIVE_LEVEL
  742. //
  743. //******************************************************************************
  744. NTSTATUS
  745. GenUSB_DeselectConfiguration (
  746. PDEVICE_EXTENSION DeviceExtension,
  747. BOOLEAN SendUrb
  748. )
  749. {
  750. NTSTATUS status;
  751. PURB urb;
  752. ULONG ulSize;
  753. ExAcquireFastMutex (&DeviceExtension->ConfigMutex);
  754. DBGPRINT(2, ("enter: GenUSB_UnConfigure\n"));
  755. LOGENTRY(DeviceExtension, 'UCON', DeviceExtension->Self, 0, 0);
  756. if (NULL == DeviceExtension->ConfigurationHandle)
  757. {
  758. status = STATUS_UNSUCCESSFUL;
  759. LOGENTRY(DeviceExtension, 'ucon', 1, 0, status);
  760. ExReleaseFastMutex (&DeviceExtension->ConfigMutex);
  761. return status;
  762. }
  763. status = STATUS_SUCCESS;
  764. IoStopTimer (DeviceExtension->Self);
  765. // Allocate a URB for the SELECT_CONFIGURATION request. As we are
  766. // unconfiguring the device, the request needs no pipe and interface
  767. // information structures.
  768. if (SendUrb)
  769. {
  770. ulSize = sizeof(struct _URB_SELECT_CONFIGURATION);
  771. urb = ExAllocatePool (NonPagedPool, ulSize);
  772. if (urb)
  773. {
  774. // Initialize the URB. A NULL Configuration Descriptor indicates
  775. // that the device should be unconfigured.
  776. //
  777. UsbBuildSelectConfigurationRequest(urb, (USHORT)ulSize, NULL);
  778. // Now issue the USB request to set the Configuration
  779. //
  780. status = GenUSB_SyncSendUsbRequest(DeviceExtension->Self, urb);
  781. ASSERT ((STATUS_SUCCESS == status) ||
  782. (STATUS_DEVICE_NOT_CONNECTED == status) ||
  783. (STATUS_DEVICE_POWERED_OFF == status));
  784. ExFreePool (urb);
  785. }
  786. else
  787. {
  788. // Could not allocate the URB.
  789. //
  790. status = STATUS_INSUFFICIENT_RESOURCES;
  791. }
  792. }
  793. //
  794. // We need to wait for all outstanding IO to finish before
  795. // freeing the pipe table
  796. //
  797. // In order to use ReleaseAndWait, we need to first take the lock another
  798. // time.
  799. //
  800. status = IoAcquireRemoveLock (&DeviceExtension->ConfigurationRemoveLock,
  801. DeviceExtension);
  802. ASSERT (STATUS_SUCCESS == status);
  803. IoReleaseRemoveLockAndWait (&DeviceExtension->ConfigurationRemoveLock,
  804. DeviceExtension);
  805. GenUSB_FreeInterfaceTable (DeviceExtension);
  806. //
  807. // We've just invalidated the pipe table so blow away the
  808. // read and write values.
  809. //
  810. DeviceExtension->ReadInterface = -1;
  811. DeviceExtension->ReadPipe = -1;
  812. DeviceExtension->WriteInterface = -1;
  813. DeviceExtension->WritePipe = -1;
  814. DBGPRINT(2, ("exit: GenUSB_UnConfigure %08X\n", status));
  815. LOGENTRY(DeviceExtension, 'ucon', 0, 0, status);
  816. ExReleaseFastMutex (&DeviceExtension->ConfigMutex);
  817. return status;
  818. }
  819. NTSTATUS
  820. GenUSB_GetSetPipe (
  821. IN PDEVICE_EXTENSION DeviceExtension,
  822. IN PUCHAR InterfaceIndex, // Optional
  823. IN PUCHAR InterfaceNumber, // Optional
  824. IN PUCHAR PipeIndex, // Optional
  825. IN PUCHAR EndpointAddress, // Optional
  826. IN PGENUSB_PIPE_PROPERTIES SetPipeProperties, // Optional
  827. OUT PGENUSB_PIPE_INFORMATION PipeInfo, // Optional
  828. OUT PGENUSB_PIPE_PROPERTIES GetPipeProperties, // Optional
  829. OUT USBD_PIPE_HANDLE * UsbdPipeHandle // Optional
  830. )
  831. {
  832. KIRQL irql;
  833. UCHAR i;
  834. NTSTATUS status;
  835. BOOLEAN directionIn;
  836. UCHAR trueInterIndex;
  837. PGENUSB_INTERFACE genusbInterface;
  838. PGENUSB_PIPE_INFO pipe;
  839. status = IoAcquireRemoveLock (&DeviceExtension->ConfigurationRemoveLock,
  840. PipeInfo);
  841. if (!NT_SUCCESS(status)) {
  842. return status;
  843. }
  844. status = STATUS_INVALID_PARAMETER;
  845. KeAcquireSpinLock (&DeviceExtension->SpinLock, &irql);
  846. {
  847. if (NULL != InterfaceNumber)
  848. {
  849. // We need to walk the list of interfaces looking for this
  850. // interface number.
  851. //
  852. // set trueInterIndex to an invalid value to start so that if it's
  853. // not found, we will fall through the error path.
  854. //
  855. trueInterIndex = DeviceExtension->InterfacesFound;
  856. for (i=0; i<DeviceExtension->InterfacesFound; i++)
  857. {
  858. genusbInterface = DeviceExtension->Interface[i];
  859. if (genusbInterface->InterfaceNumber == *InterfaceNumber)
  860. {
  861. trueInterIndex = i;
  862. break;
  863. }
  864. }
  865. }
  866. else
  867. {
  868. ASSERT (NULL != InterfaceIndex);
  869. trueInterIndex = *InterfaceIndex;
  870. }
  871. if (trueInterIndex < DeviceExtension->InterfacesFound)
  872. {
  873. genusbInterface = DeviceExtension->Interface[trueInterIndex];
  874. //
  875. // Find the Pipe in question using either the PipeIndex
  876. // or the Endpoint Address.
  877. //
  878. pipe = NULL;
  879. if (NULL != PipeIndex)
  880. {
  881. ASSERT (0 == EndpointAddress);
  882. if (*PipeIndex < genusbInterface->NumberOfPipes)
  883. {
  884. pipe = &genusbInterface->Pipes[*PipeIndex];
  885. }
  886. }
  887. else
  888. {
  889. for (i=0; i < genusbInterface->NumberOfPipes; i++)
  890. {
  891. if (genusbInterface->Pipes[i].Info.EndpointAddress ==
  892. *EndpointAddress)
  893. {
  894. // *PipeInfo = genusbInterface->Pipes[i].Info;
  895. pipe = &genusbInterface->Pipes[i];
  896. break;
  897. }
  898. }
  899. }
  900. if (NULL != pipe)
  901. {
  902. //
  903. // Now that we have the Pipe, retrieve and set optional info
  904. //
  905. if (PipeInfo)
  906. {
  907. // *PipeInfo = pipe->Info;
  908. PipeInfo->MaximumPacketSize = pipe->Info.MaximumPacketSize;
  909. PipeInfo->EndpointAddress = pipe->Info.EndpointAddress;
  910. PipeInfo->Interval = pipe->Info.Interval;
  911. PipeInfo->PipeType = pipe->Info.PipeType;
  912. PipeInfo->MaximumTransferSize = pipe->Info.MaximumTransferSize;
  913. PipeInfo->PipeFlags = pipe->Info.PipeFlags;
  914. ((PGENUSB_PIPE_HANDLE)&PipeInfo->PipeHandle)->InterfaceIndex
  915. = trueInterIndex;
  916. ((PGENUSB_PIPE_HANDLE)&PipeInfo->PipeHandle)->PipeIndex = i;
  917. ((PGENUSB_PIPE_HANDLE)&PipeInfo->PipeHandle)->Signature
  918. = CONFIGURATION_CHECK_BITS (DeviceExtension);
  919. status = STATUS_SUCCESS;
  920. }
  921. if (SetPipeProperties)
  922. {
  923. C_ASSERT (RTL_FIELD_SIZE (GENUSB_PIPE_PROPERTIES, ReservedFields) +
  924. FIELD_OFFSET (GENUSB_PIPE_PROPERTIES, ReservedFields) ==
  925. sizeof (GENUSB_PIPE_PROPERTIES));
  926. // ensure that this is a valid set request.
  927. // the check bits must be present that were set when the
  928. // caller did a get, and the unused fields must be zero.
  929. if (!VERIFY_PIPE_PROPERTIES_HANDLE (SetPipeProperties, pipe))
  930. {
  931. ; // status is already set.
  932. }
  933. else if (RtlEqualMemory (pipe->Properties.ReservedFields,
  934. SetPipeProperties->ReservedFields,
  935. RTL_FIELD_SIZE (GENUSB_PIPE_PROPERTIES,
  936. ReservedFields)))
  937. {
  938. // This field is not settable
  939. directionIn = pipe->Properties.DirectionIn;
  940. pipe->Properties = *SetPipeProperties;
  941. // the timeout must be greater than one so fix that here.
  942. if (1 == pipe->Properties.Timeout)
  943. {
  944. pipe->Properties.Timeout++;
  945. }
  946. pipe->Properties.DirectionIn = directionIn;
  947. status = STATUS_SUCCESS;
  948. }
  949. }
  950. if (GetPipeProperties)
  951. {
  952. *GetPipeProperties = pipe->Properties;
  953. // set the checkbits before returning to the user
  954. GetPipeProperties->PipePropertyHandle =
  955. PIPE_PROPERTIES_CHECK_BITS (pipe);
  956. status = STATUS_SUCCESS;
  957. }
  958. if (UsbdPipeHandle)
  959. {
  960. *UsbdPipeHandle = pipe->Info.PipeHandle;
  961. status = STATUS_SUCCESS;
  962. }
  963. }
  964. }
  965. }
  966. KeReleaseSpinLock (&DeviceExtension->SpinLock, irql);
  967. IoReleaseRemoveLock (&DeviceExtension->ConfigurationRemoveLock, PipeInfo);
  968. return status;
  969. }
  970. NTSTATUS
  971. GenUSB_SetReadWritePipes (
  972. IN PDEVICE_EXTENSION DeviceExtension,
  973. IN PGENUSB_PIPE_HANDLE ReadPipe,
  974. IN PGENUSB_PIPE_HANDLE WritePipe
  975. )
  976. {
  977. NTSTATUS status;
  978. KIRQL irql;
  979. PGENUSB_INTERFACE inter;
  980. BOOLEAN isReadPipe;
  981. BOOLEAN isWritePipe;
  982. PUSBD_PIPE_INFORMATION pipeInfo;
  983. isReadPipe = isWritePipe = TRUE;
  984. status = IoAcquireRemoveLock (&DeviceExtension->ConfigurationRemoveLock,
  985. GenUSB_SetReadWritePipes);
  986. if (!NT_SUCCESS(status)) {
  987. return status;
  988. }
  989. if ((0 == ReadPipe->Signature) &&
  990. (0 == ReadPipe->InterfaceIndex) &&
  991. (0 == ReadPipe->PipeIndex))
  992. {
  993. isReadPipe = FALSE;
  994. }
  995. else if (! VERIFY_PIPE_HANDLE_SIG (ReadPipe, DeviceExtension))
  996. {
  997. status = STATUS_INVALID_PARAMETER;
  998. }
  999. if ((0 == WritePipe->Signature) &&
  1000. (0 == WritePipe->InterfaceIndex) &&
  1001. (0 == WritePipe->PipeIndex))
  1002. {
  1003. isWritePipe = FALSE;
  1004. }
  1005. else if (! VERIFY_PIPE_HANDLE_SIG (WritePipe, DeviceExtension))
  1006. {
  1007. status = STATUS_INVALID_PARAMETER;
  1008. }
  1009. if (NT_SUCCESS (status))
  1010. {
  1011. KeAcquireSpinLock (&DeviceExtension->SpinLock, &irql);
  1012. //
  1013. // Verify that the given values for read and write pipes are
  1014. // within range and then set them.
  1015. //
  1016. if (isReadPipe)
  1017. {
  1018. if (ReadPipe->InterfaceIndex < DeviceExtension->InterfacesFound)
  1019. {
  1020. inter = DeviceExtension->Interface[ReadPipe->InterfaceIndex];
  1021. if (ReadPipe->PipeIndex < inter->NumberOfPipes)
  1022. {
  1023. // ok the ranges are now valid, test to make sure that
  1024. // we are configuring for pipes in the correct direction
  1025. // and for the correct endpoint type
  1026. //
  1027. // Right now we only support Bulk and Interrupt.
  1028. pipeInfo = &inter->Pipes[ReadPipe->PipeIndex].Info;
  1029. if ( (USBD_PIPE_DIRECTION_IN (pipeInfo))
  1030. && ( (UsbdPipeTypeBulk == pipeInfo->PipeType)
  1031. || (UsbdPipeTypeInterrupt == pipeInfo->PipeType)))
  1032. {
  1033. DeviceExtension->ReadInterface = ReadPipe->InterfaceIndex;
  1034. DeviceExtension->ReadPipe = ReadPipe->PipeIndex;
  1035. status = STATUS_SUCCESS;
  1036. }
  1037. }
  1038. }
  1039. }
  1040. if (isWritePipe)
  1041. {
  1042. if (WritePipe->InterfaceIndex < DeviceExtension->InterfacesFound)
  1043. {
  1044. inter = DeviceExtension->Interface[WritePipe->InterfaceIndex];
  1045. if (WritePipe->PipeIndex < inter->NumberOfPipes)
  1046. {
  1047. // ok the ranges are now valid, test to make sure that
  1048. // we are configuring for pipes in the correct direction
  1049. // and for the correct endpoint type
  1050. //
  1051. // Right now we only support Bulk and Interrupt.
  1052. pipeInfo = &inter->Pipes[WritePipe->PipeIndex].Info;
  1053. if ( (!USBD_PIPE_DIRECTION_IN (pipeInfo))
  1054. && ( (UsbdPipeTypeBulk == pipeInfo->PipeType)
  1055. || (UsbdPipeTypeInterrupt == pipeInfo->PipeType)))
  1056. {
  1057. DeviceExtension->WriteInterface = WritePipe->InterfaceIndex;
  1058. DeviceExtension->WritePipe = WritePipe->PipeIndex;
  1059. status = STATUS_SUCCESS;
  1060. }
  1061. }
  1062. }
  1063. }
  1064. KeReleaseSpinLock (&DeviceExtension->SpinLock, irql);
  1065. }
  1066. IoReleaseRemoveLock (&DeviceExtension->ConfigurationRemoveLock,
  1067. GenUSB_SetReadWritePipes);
  1068. return status;
  1069. }
  1070. NTSTATUS
  1071. GenUSB_TransmitReceiveComplete (
  1072. IN PDEVICE_OBJECT DeviceObject,
  1073. IN PIRP Irp,
  1074. IN PGENUSB_TRANS_RECV Trc
  1075. )
  1076. {
  1077. PVOID context;
  1078. USBD_STATUS urbStatus;
  1079. ULONG length;
  1080. PDEVICE_EXTENSION deviceExtension;
  1081. PGENUSB_PIPE_INFO pipe;
  1082. PGENUSB_COMPLETION_ROUTINE complete;
  1083. ASSERT (NULL != Trc);
  1084. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1085. complete = Trc->CompletionRoutine;
  1086. context = Trc->Context;
  1087. urbStatus = Trc->TransUrb.Hdr.Status;
  1088. length = Trc->TransUrb.TransferBufferLength;
  1089. pipe = Trc->Pipe;
  1090. LOGENTRY(deviceExtension, 'TR_C', Irp, urbStatus, Irp->IoStatus.Status);
  1091. //
  1092. // JD has convinced me that auto reset is not something we should
  1093. // do for the vendors, since there are so many different cases that
  1094. // require special handling of the data. They will need to do a reset
  1095. // themselves explicitely.
  1096. //
  1097. // if (pipe->Properties.AutoReset &&
  1098. // (!USBD_SUCCESS(urbStatus)) &&
  1099. // urbStatus != USBD_STATUS_CANCELED)
  1100. // {
  1101. // GenUSB_ResetPipe (deviceExtension, Irp, Trc);
  1102. // return STATUS_MORE_PROCESSING_REQUIRED;
  1103. // }
  1104. InterlockedDecrement (&pipe->OutstandingIO);
  1105. ExFreePool (Trc);
  1106. IoReleaseRemoveLock (&deviceExtension->ConfigurationRemoveLock, Irp);
  1107. IoReleaseRemoveLock (&deviceExtension->RemoveLock, Irp);
  1108. return ((*complete) (DeviceObject, Irp, context, urbStatus, length));
  1109. }
  1110. //******************************************************************************
  1111. //
  1112. // GenUSB_TransmitReceive()
  1113. //
  1114. // This routine may run at DPC level.
  1115. //
  1116. // Basic idea:
  1117. //
  1118. // Initializes the Bulk or Interrupt transfer Urb and sends it down the stack
  1119. //
  1120. // scratch: Transfer Flags: USBD_SHORT_TRANSFER_OK
  1121. // USBD_DEFAULT_PIPE_TRANSFER
  1122. // USBD_TRANSFER_DIRECTION_OUT
  1123. // USBD_TRANSFER_DIRECTION_IN
  1124. //
  1125. //
  1126. //******************************************************************************
  1127. NTSTATUS
  1128. GenUSB_TransmitReceive (
  1129. IN PDEVICE_EXTENSION DeviceExtension,
  1130. IN PIRP Irp,
  1131. IN UCHAR InterfaceNo,
  1132. IN UCHAR PipeNo,
  1133. IN ULONG TransferFlags,
  1134. IN PCHAR Buffer,
  1135. IN PMDL BufferMDL,
  1136. IN ULONG BufferLength,
  1137. IN PVOID Context,
  1138. IN PGENUSB_COMPLETION_ROUTINE CompletionRoutine
  1139. )
  1140. {
  1141. PIO_STACK_LOCATION stack;
  1142. KIRQL irql;
  1143. NTSTATUS status;
  1144. GENUSB_TRANS_RECV * trc;
  1145. PGENUSB_PIPE_INFO pipe;
  1146. DBGPRINT(3, ("enter: GenUSB_TransmitReceive\n"));
  1147. LOGENTRY(DeviceExtension,
  1148. 'TR__',
  1149. DeviceExtension,
  1150. ((InterfaceNo << 16) | PipeNo),
  1151. ((NULL == Buffer) ? (PCHAR) BufferMDL : Buffer));
  1152. trc = NULL;
  1153. pipe = NULL;
  1154. //
  1155. // Add another ref count to the remove lock for this completion routine.
  1156. // since the caller will in all cases free the reference that it took.
  1157. //
  1158. status = IoAcquireRemoveLock (&DeviceExtension->RemoveLock, Irp);
  1159. if (!NT_SUCCESS(status)) {
  1160. Irp->IoStatus.Status = status;
  1161. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1162. return status;
  1163. }
  1164. status = IoAcquireRemoveLock (&DeviceExtension->ConfigurationRemoveLock, Irp);
  1165. if (!NT_SUCCESS(status)) {
  1166. IoReleaseRemoveLock (&DeviceExtension->RemoveLock, Irp);
  1167. Irp->IoStatus.Status = status;
  1168. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1169. return status;
  1170. }
  1171. //
  1172. // find the pipe in question.
  1173. //
  1174. KeAcquireSpinLock (&DeviceExtension->SpinLock, &irql);
  1175. {
  1176. if (InterfaceNo < DeviceExtension->InterfacesFound)
  1177. {
  1178. if (PipeNo < DeviceExtension->Interface[InterfaceNo]->NumberOfPipes)
  1179. {
  1180. pipe = &DeviceExtension->Interface[InterfaceNo]->Pipes[PipeNo];
  1181. }
  1182. }
  1183. }
  1184. KeReleaseSpinLock (&DeviceExtension->SpinLock, irql);
  1185. if (NULL == pipe)
  1186. {
  1187. status = STATUS_INVALID_PARAMETER;
  1188. goto GenUSB_TransmitReceiveReject;
  1189. }
  1190. trc = ExAllocatePool (NonPagedPool, sizeof (GENUSB_TRANS_RECV));
  1191. if (NULL == trc)
  1192. {
  1193. status = STATUS_INSUFFICIENT_RESOURCES;
  1194. goto GenUSB_TransmitReceiveReject;
  1195. }
  1196. RtlZeroMemory (trc, sizeof (GENUSB_TRANS_RECV));
  1197. trc->Context = Context;
  1198. trc->Pipe = pipe;
  1199. trc->CompletionRoutine = CompletionRoutine;
  1200. // truncate a read packet to the max packet size if necessary.
  1201. if ((pipe->Properties.DirectionIn) &&
  1202. (!pipe->Properties.NoTruncateToMaxPacket) &&
  1203. (BufferLength > pipe->Info.MaximumPacketSize))
  1204. {
  1205. BufferLength -= (BufferLength % pipe->Info.MaximumPacketSize);
  1206. }
  1207. // Initialize the TransferURB
  1208. trc->TransUrb.Hdr.Length = sizeof (trc->TransUrb);
  1209. trc->TransUrb.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  1210. trc->TransUrb.PipeHandle = pipe->Info.PipeHandle;
  1211. trc->TransUrb.TransferFlags = TransferFlags;
  1212. trc->TransUrb.TransferBufferLength = BufferLength;
  1213. trc->TransUrb.TransferBuffer = Buffer;
  1214. trc->TransUrb.TransferBufferMDL = BufferMDL;
  1215. // Set up the Irp
  1216. stack = IoGetNextIrpStackLocation (Irp);
  1217. stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1218. stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1219. stack->Parameters.Others.Argument1 = &trc->TransUrb;
  1220. InterlockedIncrement (&pipe->OutstandingIO);
  1221. // Reset the timer Value.
  1222. pipe->CurrentTimeout = pipe->Properties.Timeout;
  1223. IoSetCompletionRoutine (Irp,
  1224. GenUSB_TransmitReceiveComplete,
  1225. trc,
  1226. TRUE,
  1227. TRUE,
  1228. TRUE);
  1229. //
  1230. // The rule is: if your completion routine is going to cause the
  1231. // Irp to be completed asynchronously (by returning
  1232. // STATUS_MORE_PROCESSING_REQUIRED) or if it is going to change
  1233. // the status of the Irp, then the dispatch function must mark
  1234. // the Irp as pending and return STATUS_PENDING. The completion
  1235. // routine TransmitReceiveComplete doesn't change the status,
  1236. // but ProbeAndSubmitTransferComlete might.
  1237. //
  1238. // In either case this prevents us from having to perculate the pending
  1239. // bit in the completion routine as well.
  1240. //
  1241. IoMarkIrpPending (Irp);
  1242. status = IoCallDriver (DeviceExtension->StackDeviceObject, Irp);
  1243. DBGPRINT(3, ("exit: GenUSB_TransRcv %08X\n", status));
  1244. LOGENTRY(DeviceExtension, 'TR_x', Irp, trc, status);
  1245. status = STATUS_PENDING;
  1246. return status;
  1247. GenUSB_TransmitReceiveReject:
  1248. if (trc)
  1249. {
  1250. IoReleaseRemoveLock (&DeviceExtension->ConfigurationRemoveLock, Irp);
  1251. IoReleaseRemoveLock (&DeviceExtension->RemoveLock, Irp);
  1252. ExFreePool (trc);
  1253. }
  1254. LOGENTRY(DeviceExtension, 'TR_x', Irp, trc, status);
  1255. ((*CompletionRoutine) (DeviceExtension->Self, Irp, Context, 0, 0));
  1256. //
  1257. // Complete the Irp only after this routine fires, since we pass the
  1258. // Irp into this routine.
  1259. //
  1260. Irp->IoStatus.Status = status;
  1261. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1262. return status;
  1263. }
  1264. //******************************************************************************
  1265. //
  1266. // GenUSB_Timer()
  1267. //
  1268. //
  1269. //
  1270. // This is a watchdog timer routine. The assumption here is that this is not
  1271. // a highly acurate timer (in fact it only has an accuracy of a single second.
  1272. // the point is to see if there is any pipe on this device that has
  1273. // outstanding transactions that are stuck, and then reset that pipe.
  1274. // We therefore do not spend any effort closing the race conditions
  1275. // between a just completing transaction and the timer firing.
  1276. // It is sufficient to know that it got that close to reset the pipe.
  1277. //
  1278. // Apon pipe reset, all outstanding IRPs on the pipe should return with
  1279. // and error. (which is just fine.)
  1280. //
  1281. //
  1282. //******************************************************************************
  1283. typedef struct _GENUSB_ABORT_CONTEXT {
  1284. ULONG NumHandles;
  1285. PIO_WORKITEM WorkItem;
  1286. USBD_PIPE_HANDLE Handles[];
  1287. } GENUSB_ABORT_CONTEXT, *PGENUSB_ABORT_CONTEXT;
  1288. VOID
  1289. GenUSB_AbortPipeWorker (
  1290. IN PDEVICE_OBJECT DeviceObject,
  1291. IN PGENUSB_ABORT_CONTEXT Context
  1292. )
  1293. {
  1294. ULONG i;
  1295. NTSTATUS status;
  1296. PDEVICE_EXTENSION deviceExtension;
  1297. struct _URB_PIPE_REQUEST urb;
  1298. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1299. for (i=0; i < Context->NumHandles; i++)
  1300. {
  1301. RtlZeroMemory (&urb, sizeof (urb));
  1302. urb.Hdr.Length = sizeof (urb);
  1303. urb.Hdr.Function = URB_FUNCTION_ABORT_PIPE;
  1304. urb.PipeHandle = Context->Handles [i];
  1305. LOGENTRY (deviceExtension, 'Abor', urb.PipeHandle, 0, 0);
  1306. status = GenUSB_SyncSendUsbRequest (DeviceObject, (PURB) &urb);
  1307. if (!NT_SUCCESS (status))
  1308. {
  1309. LOGENTRY (deviceExtension, 'Abor', urb.PipeHandle, 0, status);
  1310. }
  1311. }
  1312. IoReleaseRemoveLock (&deviceExtension->ConfigurationRemoveLock, GenUSB_Timer);
  1313. IoFreeWorkItem (Context->WorkItem);
  1314. ExFreePool (Context);
  1315. }
  1316. VOID
  1317. GenUSB_Timer (
  1318. PDEVICE_OBJECT DeviceObject,
  1319. PVOID Unused
  1320. )
  1321. {
  1322. PGENUSB_PIPE_INFO pipe;
  1323. PGENUSB_INTERFACE inter;
  1324. ULONG i,j;
  1325. PDEVICE_EXTENSION deviceExtension;
  1326. KIRQL irql;
  1327. PGENUSB_ABORT_CONTEXT context;
  1328. ULONG size;
  1329. NTSTATUS status;
  1330. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1331. status = IoAcquireRemoveLock (&deviceExtension->ConfigurationRemoveLock,
  1332. GenUSB_Timer);
  1333. if (!NT_SUCCESS(status)) {
  1334. return;
  1335. }
  1336. //
  1337. // BUGBUG preallocate this structure;
  1338. // allowing the workitem and this timer to run at the same time.
  1339. //
  1340. size = sizeof (GENUSB_ABORT_CONTEXT)
  1341. + sizeof (USBD_PIPE_HANDLE) * deviceExtension->TotalNumberOfPipes;
  1342. context = ExAllocatePool (NonPagedPool, size);
  1343. if (NULL == context)
  1344. {
  1345. status = STATUS_INSUFFICIENT_RESOURCES;
  1346. return;
  1347. }
  1348. context->WorkItem = IoAllocateWorkItem (DeviceObject);
  1349. if (NULL == context->WorkItem)
  1350. {
  1351. status = STATUS_INSUFFICIENT_RESOURCES;
  1352. ExFreePool (context);
  1353. return;
  1354. }
  1355. context->NumHandles = 0;
  1356. KeAcquireSpinLock (&deviceExtension->SpinLock, &irql);
  1357. {
  1358. // Walk through the list of interfaces and then pipes on those interfaces
  1359. // to find any pipes that may need a bit of a bump.
  1360. for (i=0; i < deviceExtension->InterfacesFound; i++)
  1361. {
  1362. inter = deviceExtension->Interface [i];
  1363. for (j=0; j < inter->NumberOfPipes; j++)
  1364. {
  1365. pipe = &inter->Pipes[j];
  1366. // now test for the timeout (given the assumptions above)
  1367. if (pipe->OutstandingIO)
  1368. {
  1369. if (0 != pipe->Properties.Timeout)
  1370. {
  1371. ASSERT (0 < pipe->CurrentTimeout);
  1372. if (0 == InterlockedDecrement (&pipe->CurrentTimeout))
  1373. {
  1374. // abort this pipe.
  1375. context->Handles[context->NumHandles]
  1376. = pipe->Info.PipeHandle;
  1377. context->NumHandles++;
  1378. }
  1379. }
  1380. }
  1381. }
  1382. }
  1383. }
  1384. KeReleaseSpinLock (&deviceExtension->SpinLock, irql);
  1385. LOGENTRY(deviceExtension,
  1386. 'Time',
  1387. deviceExtension->InterfacesFound,
  1388. deviceExtension->TotalNumberOfPipes,
  1389. context->NumHandles);
  1390. if (0 < context->NumHandles)
  1391. {
  1392. IoQueueWorkItem (context->WorkItem,
  1393. GenUSB_AbortPipeWorker,
  1394. DelayedWorkQueue,
  1395. context);
  1396. }
  1397. else
  1398. {
  1399. IoFreeWorkItem (context->WorkItem);
  1400. ExFreePool (context);
  1401. IoReleaseRemoveLock (&deviceExtension->ConfigurationRemoveLock,
  1402. GenUSB_Timer);
  1403. }
  1404. return;
  1405. }
  1406. //******************************************************************************
  1407. //
  1408. // GenUSB_ResetPipe()
  1409. //
  1410. //******************************************************************************
  1411. NTSTATUS
  1412. GenUSB_ResetPipe (
  1413. IN PDEVICE_EXTENSION DeviceExtension,
  1414. IN USBD_PIPE_HANDLE UsbdPipeHandle,
  1415. IN BOOLEAN ResetPipe,
  1416. IN BOOLEAN ClearStall,
  1417. IN BOOLEAN FlushData
  1418. )
  1419. {
  1420. NTSTATUS status;
  1421. struct _URB_PIPE_REQUEST urb;
  1422. PAGED_CODE ();
  1423. DBGPRINT(2, ("enter: GenUSB_ResetPipe\n"));
  1424. LOGENTRY(DeviceExtension, 'RESP',
  1425. UsbdPipeHandle,
  1426. (ResetPipe << 24) | (ClearStall << 16) | (FlushData << 8),
  1427. 0);
  1428. RtlZeroMemory (&urb, sizeof (urb));
  1429. urb.Hdr.Length = sizeof (urb);
  1430. urb.PipeHandle = UsbdPipeHandle;
  1431. if (ResetPipe && ClearStall)
  1432. {
  1433. urb.Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
  1434. }
  1435. else if (ResetPipe)
  1436. {
  1437. urb.Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE;
  1438. }
  1439. else if (ClearStall)
  1440. {
  1441. urb.Hdr.Function = URB_FUNCTION_SYNC_CLEAR_STALL;
  1442. }
  1443. status = GenUSB_SyncSendUsbRequest (DeviceExtension->Self, (PURB) &urb);
  1444. LOGENTRY(DeviceExtension, 'resp',
  1445. UsbdPipeHandle,
  1446. (ResetPipe << 24) | (ClearStall << 16) | (FlushData << 8),
  1447. status);
  1448. DBGPRINT(2, ("exit: GenUSB_ResetPipe %08X\n", status));
  1449. return status;
  1450. }