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.

1806 lines
55 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. CONFIG.C
  5. Abstract:
  6. This module contains the code to process the select configuration
  7. and select interface commands.
  8. Environment:
  9. kernel mode only
  10. Notes:
  11. Revision History:
  12. 01-10-96 : created
  13. --*/
  14. #include "wdm.h"
  15. #include "stdarg.h"
  16. #include "stdio.h"
  17. #include "usbdi.h" //public data structures
  18. #include "hcdi.h"
  19. #include "usbd.h" //private data strutures
  20. #ifdef USBD_DRIVER // USBPORT supercedes most of USBD, so we will remove
  21. // the obsolete code by compiling it only if
  22. // USBD_DRIVER is set.
  23. #ifdef PAGE_CODE
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(PAGE, USBD_InternalParseConfigurationDescriptor)
  26. #pragma alloc_text(PAGE, USBD_InitializeConfigurationHandle)
  27. #pragma alloc_text(PAGE, USBD_InternalInterfaceBusy)
  28. #pragma alloc_text(PAGE, USBD_InternalOpenInterface)
  29. #pragma alloc_text(PAGE, USBD_SelectConfiguration)
  30. #pragma alloc_text(PAGE, USBD_InternalCloseConfiguration)
  31. #pragma alloc_text(PAGE, USBD_SelectInterface)
  32. #endif
  33. #endif
  34. USBD_PIPE_TYPE PipeTypes[4] = {UsbdPipeTypeControl, UsbdPipeTypeIsochronous,
  35. UsbdPipeTypeBulk, UsbdPipeTypeInterrupt};
  36. PUSB_INTERFACE_DESCRIPTOR
  37. USBD_InternalParseConfigurationDescriptor(
  38. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  39. IN UCHAR InterfaceNumber,
  40. IN UCHAR AlternateSetting,
  41. PBOOLEAN HasAlternateSettings
  42. )
  43. /*++
  44. Routine Description:
  45. Get the configuration descriptor for a given device.
  46. Arguments:
  47. DeviceObject -
  48. DeviceData -
  49. Urb -
  50. ConfigurationDescriptor -
  51. Return Value:
  52. --*/
  53. {
  54. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  55. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptorSetting = NULL;
  56. PUCHAR pch = (PUCHAR) ConfigurationDescriptor, end;
  57. ULONG i, len;
  58. PUSB_COMMON_DESCRIPTOR commonDescriptor;
  59. PAGED_CODE();
  60. if (HasAlternateSettings) {
  61. *HasAlternateSettings = FALSE;
  62. }
  63. commonDescriptor =
  64. (PUSB_COMMON_DESCRIPTOR) (pch + ConfigurationDescriptor->bLength);
  65. while (commonDescriptor->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE) {
  66. ((PUCHAR)(commonDescriptor))+= commonDescriptor->bLength;
  67. }
  68. interfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) commonDescriptor;
  69. ASSERT(interfaceDescriptor->bDescriptorType ==
  70. USB_INTERFACE_DESCRIPTOR_TYPE);
  71. end = pch + ConfigurationDescriptor->wTotalLength;
  72. //
  73. // First find the matching InterfaceNumber
  74. //
  75. while (pch < end && interfaceDescriptor->bInterfaceNumber != InterfaceNumber) {
  76. pch = (PUCHAR) interfaceDescriptor;
  77. len = USBD_InternalGetInterfaceLength(interfaceDescriptor, end);
  78. if (len == 0) {
  79. // Descriptors are bad, fail.
  80. interfaceDescriptorSetting = NULL;
  81. goto USBD_InternalParseConfigurationDescriptor_exit;
  82. }
  83. pch += len;
  84. // point to the next interface
  85. interfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) pch;
  86. #if DBG
  87. if (pch < end) {
  88. ASSERT(interfaceDescriptor->bDescriptorType ==
  89. USB_INTERFACE_DESCRIPTOR_TYPE);
  90. }
  91. #endif //MAX_DEBUG
  92. }
  93. #ifdef MAX_DEBUG
  94. if (pch >= end) {
  95. USBD_KdPrint(3, ("'Interface %x alt %x not found!\n", InterfaceNumber,
  96. AlternateSetting));
  97. TEST_TRAP();
  98. }
  99. #endif //MAX_DEBUG
  100. i = 0;
  101. // Now find the proper alternate setting
  102. while (pch < end && interfaceDescriptor->bInterfaceNumber == InterfaceNumber) {
  103. if (interfaceDescriptor->bAlternateSetting == AlternateSetting) {
  104. interfaceDescriptorSetting = interfaceDescriptor;
  105. }
  106. pch = (PUCHAR) interfaceDescriptor;
  107. len = USBD_InternalGetInterfaceLength(interfaceDescriptor, end);
  108. if (len == 0) {
  109. // Descriptors are bad, fail.
  110. interfaceDescriptorSetting = NULL;
  111. goto USBD_InternalParseConfigurationDescriptor_exit;
  112. }
  113. pch += len;
  114. // point to next interface
  115. interfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) pch;
  116. #if DBG
  117. if (pch < end) {
  118. ASSERT(interfaceDescriptor->bDescriptorType ==
  119. USB_INTERFACE_DESCRIPTOR_TYPE);
  120. }
  121. #endif
  122. i++;
  123. }
  124. if (i>1 && HasAlternateSettings) {
  125. *HasAlternateSettings = TRUE;
  126. USBD_KdPrint(3, ("'device has alternate settings!\n"));
  127. }
  128. USBD_InternalParseConfigurationDescriptor_exit:
  129. return interfaceDescriptorSetting;
  130. }
  131. NTSTATUS
  132. USBD_InitializeConfigurationHandle(
  133. IN PUSBD_DEVICE_DATA DeviceData,
  134. IN PDEVICE_OBJECT DeviceObject,
  135. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  136. IN ULONG NumberOfInterfaces,
  137. IN OUT PUSBD_CONFIG *ConfigHandle
  138. )
  139. /*++
  140. Routine Description:
  141. Initialize the configuration handle structure
  142. Arguments:
  143. DeviceData -
  144. DeviceObject -
  145. ConfigurationDescriptor -
  146. ConfigHandle -
  147. Return Value:
  148. --*/
  149. {
  150. NTSTATUS ntStatus = STATUS_SUCCESS;
  151. PUSBD_CONFIG configHandle;
  152. ULONG i;
  153. PAGED_CODE();
  154. USBD_KdPrint(3, ("' enter USBD_InitializeConfigurationHandle\n"));
  155. USBD_ASSERT(ConfigurationDescriptor->bNumInterfaces > 0);
  156. configHandle = GETHEAP(PagedPool,
  157. sizeof(USBD_CONFIG) +
  158. sizeof(PUSBD_INTERFACE) *
  159. (NumberOfInterfaces-1));
  160. if (configHandle) {
  161. configHandle->ConfigurationDescriptor =
  162. GETHEAP(PagedPool, ConfigurationDescriptor->wTotalLength);
  163. if (configHandle->ConfigurationDescriptor) {
  164. RtlCopyMemory(configHandle->ConfigurationDescriptor,
  165. ConfigurationDescriptor,
  166. ConfigurationDescriptor->wTotalLength);
  167. configHandle->Sig = SIG_CONFIG;
  168. *ConfigHandle = configHandle;
  169. //
  170. // Initilaize the interface handles
  171. //
  172. for (i=0; i< NumberOfInterfaces; i++) {
  173. configHandle->InterfaceHandle[i] = NULL;
  174. }
  175. } else {
  176. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  177. RETHEAP(configHandle);
  178. }
  179. } else
  180. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  181. USBD_KdPrint(3, ("' exit USBD_InitializeConfigurationHandle 0x%x\n", ntStatus));
  182. return ntStatus;
  183. }
  184. BOOLEAN
  185. USBD_InternalInterfaceBusy(
  186. IN PUSBD_DEVICE_DATA DeviceData,
  187. IN PDEVICE_OBJECT DeviceObject,
  188. IN PUSBD_INTERFACE InterfaceHandle
  189. )
  190. /*++
  191. Routine Description:
  192. Arguments:
  193. DeviceObject - deviceobject for specific BUS
  194. DeviceData - device data structure for specific device
  195. InterfaceHandle - Interface Handle to close
  196. Return Value:
  197. --*/
  198. {
  199. BOOLEAN busy = FALSE;
  200. ULONG i, endpointState;
  201. NTSTATUS ntStatus;
  202. USBD_STATUS usbdStatus;
  203. PAGED_CODE();
  204. USBD_KdPrint(3, ("' enter USBD_InternalInterfaceBusy\n"));
  205. for (i=0; i<InterfaceHandle->InterfaceDescriptor.bNumEndpoints; i++) {
  206. USBD_KdPrint(3, ("'checking pipe %x\n", &InterfaceHandle->PipeHandle[i]));
  207. if (!PIPE_CLOSED(&InterfaceHandle->PipeHandle[i])) {
  208. // get the state of the endpoint
  209. ntStatus = USBD_GetEndpointState(DeviceData,
  210. DeviceObject,
  211. &InterfaceHandle->PipeHandle[i],
  212. &usbdStatus,
  213. &endpointState);
  214. if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(usbdStatus) &&
  215. (endpointState & HCD_ENDPOINT_TRANSFERS_QUEUED)) {
  216. busy = TRUE;
  217. break;
  218. }
  219. }
  220. }
  221. USBD_KdPrint(3, ("' exit USBD_InternalInterfaceBusy %d\n", busy));
  222. return busy;
  223. }
  224. NTSTATUS
  225. USBD_InternalOpenInterface(
  226. IN PUSBD_DEVICE_DATA DeviceData,
  227. IN PDEVICE_OBJECT DeviceObject,
  228. IN PUSBD_CONFIG ConfigHandle,
  229. IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInformation,
  230. IN OUT PUSBD_INTERFACE *InterfaceHandle,
  231. IN BOOLEAN SendSetInterfaceCommand,
  232. IN PBOOLEAN NoBandwidth
  233. )
  234. /*++
  235. Routine Description:
  236. Arguments:
  237. DeviceObject -
  238. DeviceData - USBD device handle for this device.
  239. ConfigHandle - USBD configuration handle.
  240. InterfaceInformation - pointer to USBD interface information structure
  241. passed in by the client.
  242. On success the .Length field is filled in with the actual length
  243. of the interface_information structure and the Pipe[] fields are filled
  244. in with the handles for the opened pipes.
  245. InterfaceHandle - pointer to an interface handle pointer, filled in
  246. with the allocated interface handle structure if NULL otherwise the
  247. structure passed in is used.
  248. SendSetInterfaceCommand - indicates if the set_interface command should be
  249. sent.
  250. Return Value:
  251. --*/
  252. {
  253. NTSTATUS ntStatus = STATUS_SUCCESS;
  254. NTSTATUS ntStatusHold = STATUS_SUCCESS;
  255. USBD_STATUS usbdStatus = USBD_STATUS_SUCCESS;
  256. BOOLEAN hasAlternateSettings;
  257. PUSBD_INTERFACE interfaceHandle = NULL;
  258. PUSB_ENDPOINT_DESCRIPTOR endpointDescriptor;
  259. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  260. PUCHAR pch;
  261. ULONG i;
  262. BOOLEAN allocated = FALSE;
  263. PUSB_COMMON_DESCRIPTOR descriptor;
  264. PAGED_CODE();
  265. if (NoBandwidth) {
  266. *NoBandwidth = FALSE;
  267. }
  268. // LOGENTRY("ioIf", DeviceData, ConfigHandle, SendSetInterfaceCommand);
  269. ASSERT_CONFIG(ConfigHandle);
  270. #ifdef MAX_DEBUG
  271. if (*InterfaceHandle != NULL) {
  272. // using a previously allocated interface handle
  273. ASSERT_INTERFACE(*InterfaceHandle);
  274. TEST_TRAP();
  275. }
  276. #endif
  277. USBD_KdPrint(3, ("' enter USBD_InternalOpenInterface\n"));
  278. USBD_KdPrint(3, ("' Interface %d Altsetting %d\n",
  279. InterfaceInformation->InterfaceNumber,
  280. InterfaceInformation->AlternateSetting));
  281. //
  282. // Find the interface descriptor we are interested in inside
  283. // the configuration descriptor.
  284. //
  285. interfaceDescriptor =
  286. USBD_InternalParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
  287. InterfaceInformation->InterfaceNumber,
  288. InterfaceInformation->AlternateSetting,
  289. &hasAlternateSettings);
  290. //
  291. // We got the interface descriptor, now try
  292. // to open all the pipes.
  293. //
  294. if (interfaceDescriptor) {
  295. USHORT need;
  296. USBD_KdPrint(3, ("'Interface Descriptor\n"));
  297. USBD_KdPrint(3, ("'bLength 0x%x\n", interfaceDescriptor->bLength));
  298. USBD_KdPrint(3, ("'bDescriptorType 0x%x\n", interfaceDescriptor->bDescriptorType));
  299. USBD_KdPrint(3, ("'bInterfaceNumber 0x%x\n", interfaceDescriptor->bInterfaceNumber));
  300. USBD_KdPrint(3, ("'bAlternateSetting 0x%x\n", interfaceDescriptor->bAlternateSetting));
  301. USBD_KdPrint(3, ("'bNumEndpoints 0x%x\n", interfaceDescriptor->bNumEndpoints));
  302. // found the requested interface in the configuration descriptor.
  303. // Here is where we verify there is enough room in the client
  304. // buffer since we know how many pipes we'll need based on the
  305. // interface descriptor.
  306. need = (USHORT) ((interfaceDescriptor->bNumEndpoints * sizeof(USBD_PIPE_INFORMATION) +
  307. sizeof(USBD_INTERFACE_INFORMATION)));
  308. USBD_KdPrint(3, ("'Interface.Length = %d need = %d\n", InterfaceInformation->Length, need));
  309. if (InterfaceInformation->Length < need) {
  310. TEST_TRAP();
  311. ntStatus = STATUS_BUFFER_TOO_SMALL;
  312. } else if (hasAlternateSettings && SendSetInterfaceCommand) {
  313. //
  314. // If we have alternate settings we need
  315. // to send the set interface command.
  316. //
  317. ntStatus = USBD_SendCommand(DeviceData,
  318. DeviceObject,
  319. STANDARD_COMMAND_SET_INTERFACE,
  320. InterfaceInformation->AlternateSetting,
  321. InterfaceInformation->InterfaceNumber,
  322. 0,
  323. NULL,
  324. 0,
  325. NULL,
  326. &usbdStatus);
  327. }
  328. if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(usbdStatus)) {
  329. //
  330. // we successfully selected the alternate interface
  331. // initialize the interface handle and open the pipes
  332. //
  333. if (*InterfaceHandle == NULL) {
  334. interfaceHandle = GETHEAP(NonPagedPool,
  335. sizeof(USBD_INTERFACE) +
  336. sizeof(USBD_PIPE) * interfaceDescriptor->bNumEndpoints +
  337. need);
  338. if (interfaceHandle) {
  339. interfaceHandle->InterfaceInformation =
  340. (PUSBD_INTERFACE_INFORMATION)
  341. ((PUCHAR) interfaceHandle +
  342. sizeof(USBD_INTERFACE) +
  343. sizeof(USBD_PIPE) * interfaceDescriptor->bNumEndpoints);
  344. allocated = TRUE;
  345. }
  346. } else {
  347. // using old handle
  348. interfaceHandle = *InterfaceHandle;
  349. }
  350. if (interfaceHandle) {
  351. interfaceHandle->Sig = SIG_INTERFACE;
  352. interfaceHandle->HasAlternateSettings = hasAlternateSettings;
  353. InterfaceInformation->NumberOfPipes = interfaceDescriptor->bNumEndpoints;
  354. InterfaceInformation->Class =
  355. interfaceDescriptor->bInterfaceClass;
  356. InterfaceInformation->SubClass =
  357. interfaceDescriptor->bInterfaceSubClass;
  358. InterfaceInformation->Protocol =
  359. interfaceDescriptor->bInterfaceProtocol;
  360. InterfaceInformation->Reserved =
  361. 0;
  362. // start with first endpoint
  363. // skip over any non-endpoint descriptors
  364. pch = (PUCHAR) (interfaceDescriptor) +
  365. interfaceDescriptor->bLength;
  366. //
  367. // initialize all endpoints to closed state
  368. //
  369. for (i=0; i<interfaceDescriptor->bNumEndpoints; i++) {
  370. interfaceHandle->PipeHandle[i].HcdEndpoint = NULL;
  371. }
  372. interfaceHandle->InterfaceDescriptor = *interfaceDescriptor;
  373. for (i=0; i<interfaceDescriptor->bNumEndpoints; i++) {
  374. descriptor = (PUSB_COMMON_DESCRIPTOR) pch;
  375. while (descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE) {
  376. pch += descriptor->bLength;
  377. descriptor = (PUSB_COMMON_DESCRIPTOR) pch;
  378. }
  379. endpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) pch;
  380. ASSERT(endpointDescriptor->bDescriptorType ==
  381. USB_ENDPOINT_DESCRIPTOR_TYPE);
  382. USBD_KdPrint(3, ("'Endpoint Descriptor\n"));
  383. USBD_KdPrint(3, ("'bLength 0x%x\n", endpointDescriptor->bLength));
  384. USBD_KdPrint(3, ("'bDescriptorType 0x%x\n", endpointDescriptor->bDescriptorType));
  385. USBD_KdPrint(3, ("'bMaxPacket 0x%x\n", endpointDescriptor->wMaxPacketSize));
  386. USBD_KdPrint(3, ("'bInterval 0x%x\n", endpointDescriptor->bInterval));
  387. USBD_KdPrint(3, ("'bmAttributes 0x%x\n", endpointDescriptor->bmAttributes));
  388. USBD_KdPrint(3, ("'bEndpointAddress 0x%x\n", endpointDescriptor->bEndpointAddress));
  389. USBD_KdPrint(3, ("'MaxTransferSize 0x%x\n", InterfaceInformation->Pipes[i].MaximumTransferSize));
  390. #if DBG
  391. if (InterfaceInformation->Pipes[i].PipeFlags & ~ USBD_PF_VALID_MASK) {
  392. // client driver may have uninitialized pipe flags
  393. TEST_TRAP();
  394. }
  395. #endif
  396. // init pipe flags
  397. interfaceHandle->PipeHandle[i].UsbdPipeFlags =
  398. InterfaceInformation->Pipes[i].PipeFlags;
  399. if (InterfaceInformation->Pipes[i].PipeFlags &
  400. USBD_PF_CHANGE_MAX_PACKET) {
  401. // client want sto override original max_packet
  402. // size in endpoint descriptor
  403. endpointDescriptor->wMaxPacketSize =
  404. InterfaceInformation->Pipes[i].MaximumPacketSize;
  405. USBD_KdPrint(3,
  406. ("'new bMaxPacket 0x%x\n", endpointDescriptor->wMaxPacketSize));
  407. }
  408. //
  409. // copy the endpoint descriptor into the
  410. // pipe handle structure.
  411. //
  412. RtlCopyMemory(&interfaceHandle->PipeHandle[i].EndpointDescriptor,
  413. pch,
  414. sizeof(interfaceHandle->PipeHandle[i].EndpointDescriptor) );
  415. // advance to next endpoint
  416. // first field in endpoint descriptor is length
  417. pch += endpointDescriptor->bLength;
  418. interfaceHandle->PipeHandle[i].MaxTransferSize =
  419. InterfaceInformation->Pipes[i].MaximumTransferSize;
  420. ntStatus = USBD_OpenEndpoint(DeviceData,
  421. DeviceObject,
  422. &interfaceHandle->PipeHandle[i],
  423. &usbdStatus,
  424. FALSE);
  425. //
  426. // return information about the pipe
  427. //
  428. InterfaceInformation->Pipes[i].EndpointAddress =
  429. endpointDescriptor->bEndpointAddress;
  430. InterfaceInformation->Pipes[i].PipeType =
  431. PipeTypes[endpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK];
  432. InterfaceInformation->Pipes[i].MaximumPacketSize =
  433. endpointDescriptor->wMaxPacketSize;
  434. InterfaceInformation->Pipes[i].Interval =
  435. endpointDescriptor->bInterval;
  436. if (NT_SUCCESS(ntStatus)) {
  437. InterfaceInformation->Pipes[i].PipeHandle = &interfaceHandle->PipeHandle[i];
  438. USBD_KdPrint(3, ("'pipe handle = 0x%x\n", InterfaceInformation->Pipes[i].PipeHandle ));
  439. } else {
  440. USBD_KdPrint(1,
  441. ("'error opening one of the pipes in interface (%x)\n", usbdStatus));
  442. if (usbdStatus == USBD_STATUS_NO_BANDWIDTH &&
  443. NoBandwidth) {
  444. *NoBandwidth = TRUE;
  445. }
  446. ntStatusHold = ntStatus; // Remember ntStatus for later.
  447. }
  448. }
  449. } else {
  450. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  451. }
  452. if (!NT_SUCCESS(ntStatusHold)) {
  453. ntStatus = ntStatusHold; // Get back any error condition.
  454. }
  455. if (NT_SUCCESS(ntStatus)) {
  456. //
  457. // successfully opened the interface, return the handle
  458. //
  459. *InterfaceHandle =
  460. InterfaceInformation->InterfaceHandle = interfaceHandle;
  461. //
  462. // set the length properly
  463. //
  464. InterfaceInformation->Length = (USHORT)
  465. ((sizeof(USBD_INTERFACE_INFORMATION) ) +
  466. sizeof(USBD_PIPE_INFORMATION) *
  467. interfaceDescriptor->bNumEndpoints);
  468. // make a copy of the interface information
  469. RtlCopyMemory(interfaceHandle->InterfaceInformation,
  470. InterfaceInformation,
  471. InterfaceInformation->Length);
  472. } else {
  473. //
  474. // had a problem, go back thru and close anything we opened.
  475. //
  476. if (interfaceHandle) {
  477. for (i=0; i<interfaceDescriptor->bNumEndpoints; i++) {
  478. if (!PIPE_CLOSED(&interfaceHandle->PipeHandle[i])) {
  479. USBD_KdPrint(3, ("'open interface cleanup -- closing endpoint %x\n",
  480. &interfaceHandle->PipeHandle[i]));
  481. //
  482. // if this guy fails we just drop the endpoint
  483. // on the floor
  484. //
  485. USBD_CloseEndpoint(DeviceData,
  486. DeviceObject,
  487. &interfaceHandle->PipeHandle[i],
  488. NULL);
  489. }
  490. }
  491. if (allocated) {
  492. RETHEAP(interfaceHandle);
  493. }
  494. }
  495. }
  496. }
  497. #ifdef MAX_DEBUG
  498. else {
  499. //
  500. // interface length was too small, or device failed the select
  501. // interface request.
  502. //
  503. TEST_TRAP();
  504. }
  505. #endif
  506. } else {
  507. ntStatus = STATUS_INVALID_PARAMETER;
  508. }
  509. // LOGENTRY("ioIx", 0, 0, ntStatus);
  510. USBD_KdPrint(3, ("' exit USBD_InternalOpenInterface 0x%x\n", ntStatus));
  511. return ntStatus;
  512. }
  513. NTSTATUS
  514. USBD_InternalRestoreInterface(
  515. IN PUSBD_DEVICE_DATA DeviceData,
  516. IN PDEVICE_OBJECT DeviceObject,
  517. IN PUSBD_CONFIG ConfigHandle,
  518. IN OUT PUSBD_INTERFACE InterfaceHandle
  519. )
  520. /*++
  521. Routine Description:
  522. Arguments:
  523. DeviceObject -
  524. Return Value:
  525. --*/
  526. {
  527. NTSTATUS ntStatus = STATUS_SUCCESS;
  528. USBD_STATUS usbdStatus = USBD_STATUS_SUCCESS;
  529. PUSB_ENDPOINT_DESCRIPTOR endpointDescriptor;
  530. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  531. PUSBD_INTERFACE_INFORMATION interfaceInformation;
  532. ULONG i;
  533. PAGED_CODE();
  534. // LOGENTRY("ioIf", DeviceData, ConfigHandle, SendSetInterfaceCommand);
  535. ASSERT_CONFIG(ConfigHandle);
  536. // using a previously allocated interface handle
  537. ASSERT_INTERFACE(InterfaceHandle);
  538. if (!InterfaceHandle) {
  539. ntStatus = STATUS_INVALID_PARAMETER;
  540. goto USBD_InternalRestoreInterfaceExit;
  541. }
  542. interfaceDescriptor = &InterfaceHandle->InterfaceDescriptor;
  543. interfaceInformation = InterfaceHandle->InterfaceInformation;
  544. USBD_KdPrint(3, ("' enter USBD_InternalRestoreInterface\n"));
  545. USBD_KdPrint(3, ("' Interface %d Altsetting %d\n",
  546. interfaceInformation->InterfaceNumber,
  547. interfaceInformation->AlternateSetting));
  548. //
  549. // We got the interface descriptor, now try
  550. // to open all the pipes.
  551. //
  552. USBD_KdPrint(3, ("'Interface Descriptor\n"));
  553. USBD_KdPrint(3, ("'bLength 0x%x\n", interfaceDescriptor->bLength));
  554. USBD_KdPrint(3, ("'bDescriptorType 0x%x\n", interfaceDescriptor->bDescriptorType));
  555. USBD_KdPrint(3, ("'bInterfaceNumber 0x%x\n", interfaceDescriptor->bInterfaceNumber));
  556. USBD_KdPrint(3, ("'bAlternateSetting 0x%x\n", interfaceDescriptor->bAlternateSetting));
  557. USBD_KdPrint(3, ("'bNumEndpoints 0x%x\n", interfaceDescriptor->bNumEndpoints));
  558. // found the requested interface in the configuration descriptor.
  559. // Here is where we verify there is enough room in the client
  560. // buffer since we know how many pipes we'll need based on the
  561. // interface descriptor.
  562. #if 0
  563. need = (USHORT) ((interfaceDescriptor->bNumEndpoints * sizeof(USBD_PIPE_INFORMATION) +
  564. sizeof(USBD_INTERFACE_INFORMATION)));
  565. USBD_KdPrint(3, ("'Interface.Length = %d need = %d\n", interfaceInformation->Length, need));
  566. #endif
  567. if (InterfaceHandle->HasAlternateSettings) {
  568. //
  569. // If we have alternate settings we need
  570. // to send the set interface command.
  571. //
  572. ntStatus = USBD_SendCommand(DeviceData,
  573. DeviceObject,
  574. STANDARD_COMMAND_SET_INTERFACE,
  575. interfaceInformation->AlternateSetting,
  576. interfaceInformation->InterfaceNumber,
  577. 0,
  578. NULL,
  579. 0,
  580. NULL,
  581. &usbdStatus);
  582. }
  583. if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(usbdStatus)) {
  584. //
  585. // we successfully selected the alternate interface
  586. // initialize the interface handle and open the pipes
  587. //
  588. ASSERT(interfaceInformation->NumberOfPipes ==
  589. interfaceDescriptor->bNumEndpoints);
  590. ASSERT(interfaceInformation->Class ==
  591. interfaceDescriptor->bInterfaceClass);
  592. ASSERT(interfaceInformation->SubClass ==
  593. interfaceDescriptor->bInterfaceSubClass);
  594. ASSERT(interfaceInformation->Protocol ==
  595. interfaceDescriptor->bInterfaceProtocol);
  596. //
  597. // initialize all endpoints to closed state
  598. //
  599. for (i=0; i<interfaceDescriptor->bNumEndpoints; i++) {
  600. InterfaceHandle->PipeHandle[i].HcdEndpoint = NULL;
  601. }
  602. for (i=0; i<interfaceDescriptor->bNumEndpoints; i++) {
  603. endpointDescriptor =
  604. &InterfaceHandle->PipeHandle[i].EndpointDescriptor;
  605. ASSERT(endpointDescriptor->bDescriptorType ==
  606. USB_ENDPOINT_DESCRIPTOR_TYPE);
  607. USBD_KdPrint(3, ("'Endpoint Descriptor\n"));
  608. USBD_KdPrint(3, ("'bLength 0x%x\n", endpointDescriptor->bLength));
  609. USBD_KdPrint(3, ("'bDescriptorType 0x%x\n", endpointDescriptor->bDescriptorType));
  610. USBD_KdPrint(3, ("'bMaxPacket 0x%x\n", endpointDescriptor->wMaxPacketSize));
  611. USBD_KdPrint(3, ("'bInterval 0x%x\n", endpointDescriptor->bInterval));
  612. USBD_KdPrint(3, ("'bmAttributes 0x%x\n", endpointDescriptor->bmAttributes));
  613. USBD_KdPrint(3, ("'bEndpointAddress 0x%x\n", endpointDescriptor->bEndpointAddress));
  614. USBD_KdPrint(3, ("'MaxTransferSize 0x%x\n", interfaceInformation->Pipes[i].MaximumTransferSize));
  615. //
  616. // open the eendpoint again
  617. //
  618. ntStatus = USBD_OpenEndpoint(DeviceData,
  619. DeviceObject,
  620. &InterfaceHandle->PipeHandle[i],
  621. NULL,
  622. FALSE);
  623. if (NT_SUCCESS(ntStatus)) {
  624. //
  625. // return information about the pipe
  626. //
  627. ASSERT(interfaceInformation->Pipes[i].EndpointAddress ==
  628. endpointDescriptor->bEndpointAddress);
  629. ASSERT(interfaceInformation->Pipes[i].PipeType ==
  630. PipeTypes[endpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK]);
  631. ASSERT(interfaceInformation->Pipes[i].MaximumPacketSize ==
  632. endpointDescriptor->wMaxPacketSize);
  633. ASSERT(interfaceInformation->Pipes[i].Interval ==
  634. endpointDescriptor->bInterval);
  635. ASSERT(interfaceInformation->Pipes[i].PipeHandle ==
  636. &InterfaceHandle->PipeHandle[i]);
  637. USBD_KdPrint(3, ("'pipe handle = 0x%x\n", interfaceInformation->Pipes[i].PipeHandle ));
  638. } else {
  639. USBD_KdPrint(3, ("'error opening one of the pipes in an interface\n"));
  640. TEST_TRAP();
  641. break;
  642. }
  643. }
  644. } else {
  645. ntStatus = STATUS_INVALID_PARAMETER;
  646. }
  647. USBD_InternalRestoreInterfaceExit:
  648. // LOGENTRY("ioIx", 0, 0, ntStatus);
  649. USBD_KdPrint(3, ("' exit USBD_InternalRestoreInterface 0x%x\n", ntStatus));
  650. return ntStatus;
  651. }
  652. NTSTATUS
  653. USBD_InternalRestoreConfiguration(
  654. IN PUSBD_DEVICE_DATA DeviceData,
  655. IN PDEVICE_OBJECT DeviceObject,
  656. IN PUSBD_CONFIG ConfigHandle
  657. )
  658. /*++
  659. Routine Description:
  660. Arguments:
  661. DeviceObject -
  662. Return Value:
  663. --*/
  664. {
  665. NTSTATUS ntStatus = STATUS_SUCCESS;
  666. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  667. USBD_STATUS usbdStatus = USBD_STATUS_SUCCESS;
  668. ULONG i;
  669. BOOLEAN noBandwidth = FALSE;
  670. if (!ConfigHandle) {
  671. ntStatus = STATUS_INVALID_PARAMETER;
  672. goto USBD_InternalRestoreConfigurationExit;
  673. }
  674. configurationDescriptor = ConfigHandle->ConfigurationDescriptor;
  675. ntStatus = USBD_SendCommand(DeviceData,
  676. DeviceObject,
  677. STANDARD_COMMAND_SET_CONFIGURATION,
  678. configurationDescriptor->bConfigurationValue,
  679. 0,
  680. 0,
  681. NULL,
  682. 0,
  683. NULL,
  684. &usbdStatus);
  685. USBD_KdPrint(3, ("' SendCommand, SetConfiguration returned 0x%x\n", ntStatus));
  686. if (NT_SUCCESS(ntStatus)) {
  687. for (i=0; i<configurationDescriptor->bNumInterfaces; i++) {
  688. ntStatus = USBD_InternalRestoreInterface(DeviceData,
  689. DeviceObject,
  690. ConfigHandle,
  691. ConfigHandle->InterfaceHandle[i]);
  692. USBD_KdPrint(3, ("' InternalRestoreInterface returned 0x%x\n", ntStatus));
  693. if (!NT_SUCCESS(ntStatus)) {
  694. TEST_TRAP();
  695. break;
  696. }
  697. }
  698. }
  699. USBD_InternalRestoreConfigurationExit:
  700. return ntStatus;
  701. }
  702. NTSTATUS
  703. USBD_SelectConfiguration(
  704. IN PDEVICE_OBJECT DeviceObject,
  705. IN PIRP Irp,
  706. IN PURB Urb,
  707. OUT PBOOLEAN IrpIsPending
  708. )
  709. /*++
  710. Routine Description:
  711. Open a configuration for a USB device.
  712. Client will pass in a buffer that looks like this:
  713. -----------------
  714. Config Info
  715. - client inputs:
  716. Length of entire URB
  717. ConfigurationDescriptor
  718. - class driver outputs:
  719. ConfigurationHandle
  720. -----------------
  721. Interface Info 0 one of these for each interface in the
  722. configuration
  723. - client inputs:
  724. InterfaceNumber (can be zero)
  725. AlternateSetting (can be zero)
  726. - class driver outputs:
  727. Length
  728. InterfaceHandle
  729. -----------------
  730. pipe info 0,0 one of these for each pipe in the
  731. interface
  732. - client inputs:
  733. - class driver outputs:
  734. -----------------
  735. pipe info 0,1
  736. -----------------
  737. Interface Info 1
  738. -----------------
  739. pipe info 1, 0
  740. -----------------
  741. pipe info 1, 1
  742. -----------------
  743. ...
  744. On input:
  745. The Config Info must specify the number of interfaces
  746. in the configuration
  747. The Interface Info will specify a specific alt setting
  748. to be selected for the interface.
  749. 1. First we look at the configuration descriptor for the
  750. requested configuration and validate the client
  751. input buffer agianst it.
  752. 2. We open the interfaces for the requested configuration
  753. and open the pipes within those interfaces, setting
  754. alt settings were appropriate.
  755. 3. We set the configuration for the device with the
  756. appropriate control request.
  757. Arguments:
  758. DeviceObject -
  759. Irp - IO request block
  760. Urb - ptr to USB request block
  761. IrpIsPending -
  762. Return Value:
  763. --*/
  764. {
  765. NTSTATUS ntStatus = STATUS_SUCCESS;
  766. PUSBD_DEVICE_DATA deviceData;
  767. PUSBD_CONFIG configHandle = NULL;
  768. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  769. PUSBD_INTERFACE_INFORMATION interfaceInformation;
  770. PUCHAR pch;
  771. ULONG i;
  772. PUSBD_EXTENSION deviceExtension;
  773. ULONG numInterfaces;
  774. PUCHAR end;
  775. BOOLEAN noBandwidth = FALSE;
  776. PAGED_CODE();
  777. USBD_KdPrint(3, ("' enter USBD_SelectConfiguration\n"));
  778. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  779. USBD_WaitForUsbDeviceMutex(deviceExtension);
  780. deviceData = Urb->UrbHeader.UsbdDeviceHandle;
  781. if (deviceData == NULL) {
  782. ntStatus = STATUS_INVALID_PARAMETER;
  783. goto USBD_SelectConfiguration_Done;
  784. }
  785. //
  786. // dump old configuration data if we have any
  787. //
  788. if (deviceData->ConfigurationHandle) {
  789. // This is where we close the old configuration
  790. // handle, all pipes and all interfaces.
  791. ntStatus = USBD_InternalCloseConfiguration(deviceData,
  792. DeviceObject,
  793. &Urb->UrbSelectConfiguration.Status,
  794. FALSE,
  795. FALSE);
  796. if (!USBD_SUCCESS(Urb->UrbSelectConfiguration.Status) ||
  797. !NT_SUCCESS(ntStatus)) {
  798. //
  799. // if we got an error closing the current
  800. // config then abort the select configuration operation.
  801. //
  802. goto USBD_SelectConfiguration_Done;
  803. }
  804. }
  805. configurationDescriptor =
  806. Urb->UrbSelectConfiguration.ConfigurationDescriptor;
  807. //
  808. // if null pased in set configuration to 0
  809. // 'unconfigured'
  810. //
  811. if (configurationDescriptor == NULL) {
  812. // device needs to be in the unconfigured state
  813. //
  814. // This may fail if the configuration is being
  815. // closed as the result of the device being unplugged
  816. //
  817. ntStatus = USBD_SendCommand(deviceData,
  818. DeviceObject,
  819. STANDARD_COMMAND_SET_CONFIGURATION,
  820. 0,
  821. 0,
  822. 0,
  823. NULL,
  824. 0,
  825. NULL,
  826. &Urb->UrbSelectConfiguration.Status);
  827. goto USBD_SelectConfiguration_Done;
  828. }
  829. //
  830. // count the number of interfaces to process in this
  831. // request
  832. //
  833. pch = (PUCHAR) &Urb->UrbSelectConfiguration.Interface;
  834. numInterfaces = 0;
  835. end = ((PUCHAR) Urb) + Urb->UrbSelectConfiguration.Length;
  836. do {
  837. numInterfaces++;
  838. interfaceInformation = (PUSBD_INTERFACE_INFORMATION) pch;
  839. pch+=interfaceInformation->Length;
  840. } while (pch < end);
  841. USBD_KdPrint(3, ("'USBD_SelectConfiguration -- %d interfaces\n", numInterfaces));
  842. if (numInterfaces != configurationDescriptor->bNumInterfaces) {
  843. //
  844. // driver is broken, config request does not match
  845. // config descriptor passes in!!!
  846. //
  847. USBD_KdTrap(
  848. ("config request does not match config descriptor passes in!!!\n"));
  849. ntStatus = STATUS_INVALID_PARAMETER;
  850. }
  851. //
  852. // Allocate a configuration handle and
  853. // verify there is enough room to store
  854. // all the information in the client buffer.
  855. //
  856. if (NT_SUCCESS(ntStatus)) {
  857. ntStatus = USBD_InitializeConfigurationHandle(deviceData,
  858. DeviceObject,
  859. configurationDescriptor,
  860. numInterfaces,
  861. &configHandle);
  862. }
  863. //
  864. // Send the 'set configuration' command
  865. //
  866. if (NT_SUCCESS(ntStatus)) {
  867. ntStatus = USBD_SendCommand(deviceData,
  868. DeviceObject,
  869. STANDARD_COMMAND_SET_CONFIGURATION,
  870. configurationDescriptor->bConfigurationValue,
  871. 0,
  872. 0,
  873. NULL,
  874. 0,
  875. NULL,
  876. &Urb->UrbSelectConfiguration.Status);
  877. USBD_KdPrint(3, ("' SendCommand, SetConfiguration returned 0x%x\n", ntStatus));
  878. }
  879. if (NT_SUCCESS(ntStatus)) {
  880. //
  881. // Users buffer checks out, parse thru the configuration
  882. // descriptor and open the interfaces.
  883. //
  884. // At this stage of the game we are not strict with validation,
  885. // we assume the client passed in a configuration request buffer
  886. // of the proper size and format. All we do for now is walk through
  887. // the client buffer and open the interfaces specified.
  888. pch = (PUCHAR) &Urb->UrbSelectConfiguration.Interface;
  889. for (i=0; i<configurationDescriptor->bNumInterfaces; i++) {
  890. //
  891. // all interface handles to null for this config
  892. //
  893. configHandle->InterfaceHandle[i] = NULL;
  894. }
  895. for (i=0; i<numInterfaces; i++) {
  896. interfaceInformation = (PUSBD_INTERFACE_INFORMATION) pch;
  897. ntStatus = USBD_InternalOpenInterface(deviceData,
  898. DeviceObject,
  899. configHandle,
  900. interfaceInformation,
  901. &configHandle->InterfaceHandle[i],
  902. TRUE,
  903. &noBandwidth);
  904. pch+=interfaceInformation->Length;
  905. USBD_KdPrint(3, ("' InternalOpenInterface returned 0x%x\n", ntStatus));
  906. if (!NT_SUCCESS(ntStatus)) {
  907. break;
  908. }
  909. }
  910. }
  911. //
  912. // If interfaces were successfully set up then return
  913. // success.
  914. //
  915. USBD_SelectConfiguration_Done:
  916. if (NT_SUCCESS(ntStatus) &&
  917. USBD_SUCCESS(Urb->UrbSelectConfiguration.Status)) {
  918. Urb->UrbSelectConfiguration.ConfigurationHandle = configHandle;
  919. deviceData->ConfigurationHandle = configHandle;
  920. } else {
  921. //
  922. // something failed, clean up before we return an error.
  923. //
  924. if (configHandle) {
  925. ASSERT_DEVICE(deviceData);
  926. //
  927. // if we have a configHandle then we need to free it
  928. deviceData->ConfigurationHandle =
  929. configHandle;
  930. //
  931. // attempt to close it
  932. //
  933. USBD_InternalCloseConfiguration(deviceData,
  934. DeviceObject,
  935. &Urb->UrbSelectConfiguration.Status,
  936. FALSE,
  937. FALSE);
  938. deviceData->ConfigurationHandle = NULL;
  939. }
  940. // make sure we return an error in the URB.
  941. if (!USBD_ERROR(Urb->UrbSelectConfiguration.Status)) {
  942. if (noBandwidth) {
  943. Urb->UrbSelectConfiguration.Status =
  944. SET_USBD_ERROR(USBD_STATUS_NO_BANDWIDTH);
  945. USBD_KdPrint(1, ("Failing SelectConfig -- No BW\n"));
  946. } else {
  947. Urb->UrbSelectConfiguration.Status = SET_USBD_ERROR(USBD_STATUS_REQUEST_FAILED);
  948. USBD_KdPrint(1, ("Failing SelectConfig\n"));
  949. }
  950. }
  951. }
  952. //
  953. // We did everything synchronously
  954. //
  955. *IrpIsPending = FALSE;
  956. USBD_ReleaseUsbDeviceMutex(deviceExtension);
  957. USBD_KdPrint(3, ("' exit USBD_SelectConfiguration 0x%x\n", ntStatus));
  958. return ntStatus;
  959. }
  960. NTSTATUS
  961. USBD_InternalCloseConfiguration(
  962. IN PUSBD_DEVICE_DATA DeviceData,
  963. IN PDEVICE_OBJECT DeviceObject,
  964. IN OUT USBD_STATUS *UsbdStatus,
  965. IN BOOLEAN AbortTransfers,
  966. IN BOOLEAN KeepConfig
  967. )
  968. /*++
  969. Routine Description:
  970. Closes the current configuration for a device.
  971. Arguments:
  972. Return Value:
  973. --*/
  974. {
  975. ULONG i, j;
  976. NTSTATUS ntStatus = STATUS_SUCCESS;
  977. PUSBD_CONFIG configHandle = NULL;
  978. BOOLEAN retry = TRUE;
  979. PAGED_CODE();
  980. *UsbdStatus = USBD_STATUS_SUCCESS;
  981. if (DeviceData == NULL || DeviceData->ConfigurationHandle == NULL) {
  982. return STATUS_INVALID_PARAMETER;
  983. }
  984. configHandle = DeviceData->ConfigurationHandle;
  985. //
  986. // first see if all the endpoints are idle
  987. //
  988. USBD_InternalCloseConfiguration_Retry:
  989. for (i=0; i<configHandle->ConfigurationDescriptor->bNumInterfaces; i++) {
  990. if ( configHandle->InterfaceHandle[i] &&
  991. USBD_InternalInterfaceBusy(DeviceData,
  992. DeviceObject,
  993. configHandle->InterfaceHandle[i]) ) {
  994. //
  995. // We have a busy interface on this config
  996. //
  997. if (AbortTransfers) {
  998. //
  999. // If we get here it means that the device driver
  1000. // has pending transfers even though it has processed
  1001. // the pnp REMOVE message!
  1002. //
  1003. // This is a bug in the driver, we'll loop here
  1004. // on the chance that the driver did manage to send
  1005. // an abort first and the transfers will soon
  1006. // complete.
  1007. //
  1008. USBD_Warning(DeviceData,
  1009. "Driver still has pending transfers while closing the configuration, wait\n",
  1010. TRUE);
  1011. //
  1012. // wait for any pending transfers to abort
  1013. //
  1014. goto USBD_InternalCloseConfiguration_Retry;
  1015. } else {
  1016. // The driver has closed the configuration while
  1017. // it still has active tranfers -- this is a bug
  1018. // in the driver -- all we do here is fail the
  1019. // close request
  1020. USBD_Warning(DeviceData,
  1021. "Driver still has pending transfers while closing the configuration, fail\n",
  1022. TRUE);
  1023. *UsbdStatus =
  1024. SET_USBD_ERROR(USBD_STATUS_ERROR_BUSY);
  1025. if (retry) {
  1026. LARGE_INTEGER deltaTime;
  1027. deltaTime.QuadPart = 50 * -10000;
  1028. (VOID) KeDelayExecutionThread(KernelMode,
  1029. FALSE,
  1030. &deltaTime);
  1031. retry = FALSE;
  1032. *UsbdStatus = USBD_STATUS_SUCCESS;
  1033. goto USBD_InternalCloseConfiguration_Retry;
  1034. } else {
  1035. goto USBD_InternalCloseConfiguration_Done;
  1036. }
  1037. }
  1038. }
  1039. }
  1040. //
  1041. // endpoints are idle, go ahead and clean up all pipes and
  1042. // interfaces for this configuration.
  1043. //
  1044. for (i=0; i<configHandle->ConfigurationDescriptor->bNumInterfaces; i++) {
  1045. //
  1046. // found an open interface, close it
  1047. //
  1048. if (configHandle->InterfaceHandle[i]) {
  1049. USBD_KdPrint(3, ("'%d endpoints to close\n",
  1050. configHandle->InterfaceHandle[i]->InterfaceDescriptor.bNumEndpoints));
  1051. for (j=0; j<configHandle->InterfaceHandle[i]->InterfaceDescriptor.bNumEndpoints; j++) {
  1052. if (!PIPE_CLOSED(&configHandle->InterfaceHandle[i]->PipeHandle[j])) {
  1053. USBD_KdPrint(3, ("'close config -- closing endpoint %x\n",
  1054. &configHandle->InterfaceHandle[i]->PipeHandle[j]));
  1055. ntStatus = USBD_CloseEndpoint(DeviceData,
  1056. DeviceObject,
  1057. &configHandle->InterfaceHandle[i]->PipeHandle[j],
  1058. UsbdStatus);
  1059. }
  1060. //
  1061. // problem closing an endpoint, abort the
  1062. // SelectConfiguration operation and return an error.
  1063. //
  1064. if (NT_SUCCESS(ntStatus)) {
  1065. configHandle->InterfaceHandle[i]->PipeHandle[j].HcdEndpoint
  1066. = NULL;
  1067. } else {
  1068. USBD_KdTrap(("Unable to close configuration\n"));
  1069. goto USBD_InternalCloseConfiguration_Done;
  1070. }
  1071. }
  1072. if (!KeepConfig) {
  1073. RETHEAP(configHandle->InterfaceHandle[i]);
  1074. configHandle->InterfaceHandle[i] = NULL;
  1075. }
  1076. }
  1077. }
  1078. if (!KeepConfig) {
  1079. RETHEAP(DeviceData->ConfigurationHandle->ConfigurationDescriptor);
  1080. RETHEAP(DeviceData->ConfigurationHandle);
  1081. DeviceData->ConfigurationHandle = NULL;
  1082. }
  1083. USBD_InternalCloseConfiguration_Done:
  1084. USBD_KdPrint(3, ("'USBD_SelectConfiguration, current configuration closed\n"));
  1085. return ntStatus;
  1086. }
  1087. NTSTATUS
  1088. USBD_InternalCloseDefaultPipe(
  1089. IN PUSBD_DEVICE_DATA DeviceData,
  1090. IN PDEVICE_OBJECT DeviceObject,
  1091. IN OUT USBD_STATUS *UsbdStatus,
  1092. IN BOOLEAN AbortTransfers
  1093. )
  1094. /*++
  1095. Routine Description:
  1096. Closes the current configuration for a device.
  1097. Arguments:
  1098. Return Value:
  1099. --*/
  1100. {
  1101. NTSTATUS ntStatus = STATUS_SUCCESS;
  1102. BOOLEAN retry = TRUE;
  1103. ULONG endpointState = 0;
  1104. PUSBD_PIPE defaultPipe;
  1105. PAGED_CODE();
  1106. *UsbdStatus = USBD_STATUS_SUCCESS;
  1107. //
  1108. // first see if eop is idle
  1109. //
  1110. defaultPipe = &DeviceData->DefaultPipe;
  1111. USBD_InternalCloseDefaultPipe_Retry:
  1112. ntStatus = USBD_GetEndpointState(DeviceData,
  1113. DeviceObject,
  1114. defaultPipe,
  1115. UsbdStatus,
  1116. &endpointState);
  1117. if (NT_SUCCESS(ntStatus) &&
  1118. (endpointState & HCD_ENDPOINT_TRANSFERS_QUEUED)) {
  1119. //
  1120. // We have busy pipe
  1121. //
  1122. if (AbortTransfers) {
  1123. //
  1124. // If we get here it means that the device driver
  1125. // has pending transfers even though it has processed
  1126. // the pnp REMOVE message!
  1127. //
  1128. // This is a bug in the driver, we'll loop here
  1129. // on the chance that the driver did manage to send
  1130. // an abort first and the transfers will soon
  1131. // complete.
  1132. //
  1133. USBD_Warning(DeviceData,
  1134. "Driver still has pending transfers while closing pipe 0, wait\n",
  1135. TRUE);
  1136. //
  1137. // wait for any pending transfers to abort
  1138. //
  1139. goto USBD_InternalCloseDefaultPipe_Retry;
  1140. } else {
  1141. // The driver has closed the configuration while
  1142. // it still has active tranfers -- this is a bug
  1143. // in the driver -- all we do here is fail the
  1144. // close request
  1145. USBD_Warning(DeviceData,
  1146. "Driver still has pending transfers while closing pipe 0, fail\n",
  1147. TRUE);
  1148. *UsbdStatus =
  1149. SET_USBD_ERROR(USBD_STATUS_ERROR_BUSY);
  1150. if (retry) {
  1151. LARGE_INTEGER deltaTime;
  1152. deltaTime.QuadPart = 50 * -10000;
  1153. (VOID) KeDelayExecutionThread(KernelMode,
  1154. FALSE,
  1155. &deltaTime);
  1156. retry = FALSE;
  1157. *UsbdStatus = USBD_STATUS_SUCCESS;
  1158. goto USBD_InternalCloseDefaultPipe_Retry;
  1159. } else {
  1160. goto USBD_InternalCloseDefaultPipe_Done;
  1161. }
  1162. }
  1163. }
  1164. //
  1165. // idle pipe, close it now
  1166. //
  1167. if (!PIPE_CLOSED(defaultPipe)) {
  1168. USBD_KdPrint(3, ("'close pipe 0 -- closing endpoint %x\n",
  1169. defaultPipe));
  1170. ntStatus = USBD_CloseEndpoint(DeviceData,
  1171. DeviceObject,
  1172. defaultPipe,
  1173. UsbdStatus);
  1174. }
  1175. //
  1176. // problem closing an endpoint, abort the
  1177. // SelectConfiguration operation and return an error.
  1178. //
  1179. if (NT_SUCCESS(ntStatus)) {
  1180. defaultPipe->HcdEndpoint = NULL;
  1181. } else {
  1182. USBD_KdTrap(("Unable to close configuration\n"));
  1183. goto USBD_InternalCloseDefaultPipe_Done;
  1184. }
  1185. USBD_InternalCloseDefaultPipe_Done:
  1186. USBD_KdPrint(3, ("'USBD_InternalCloseDefaultPipe, closed (%x)\n", ntStatus));
  1187. return ntStatus;
  1188. }
  1189. NTSTATUS
  1190. USBD_SelectInterface(
  1191. IN PDEVICE_OBJECT DeviceObject,
  1192. IN PIRP Irp,
  1193. IN PURB Urb,
  1194. OUT PBOOLEAN IrpIsPending
  1195. )
  1196. /*++
  1197. Routine Description:
  1198. Select an alternate interface for a USB device.
  1199. Client will pass in a buffer that looks like this:
  1200. -----------------
  1201. Config Info
  1202. - client inputs
  1203. Configuration Handle
  1204. -----------------
  1205. Interface Info
  1206. - client Inputs
  1207. InterfaceNumber
  1208. AlternateSetting
  1209. - class driver outputs:
  1210. Length
  1211. InterfaceHandle
  1212. -----------------
  1213. pipe info 0,0 one of these for each pipe in the
  1214. interface
  1215. - client inputs:
  1216. - class driver outputs:
  1217. -----------------
  1218. pipe info 0,1
  1219. -----------------
  1220. ...
  1221. Arguments:
  1222. DeviceObject -
  1223. Irp - IO request block
  1224. Urb - ptr to USB request block
  1225. IrpIsPending -
  1226. Return Value:
  1227. --*/
  1228. {
  1229. NTSTATUS ntStatus = STATUS_SUCCESS;
  1230. PUSBD_DEVICE_DATA deviceData;
  1231. PUSBD_CONFIG configHandle = NULL;
  1232. ULONG i, j;
  1233. PUSBD_INTERFACE oldInterfaceHandle;
  1234. PUSBD_EXTENSION deviceExtension;
  1235. BOOLEAN noBandwidth = FALSE;
  1236. PAGED_CODE();
  1237. deviceData = Urb->UrbHeader.UsbdDeviceHandle;
  1238. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  1239. USBD_WaitForUsbDeviceMutex(deviceExtension);
  1240. configHandle = Urb->UrbSelectInterface.ConfigurationHandle;
  1241. ASSERT_CONFIG(configHandle);
  1242. //
  1243. // Select the interface number we are interested in
  1244. //
  1245. i = Urb->UrbSelectInterface.Interface.InterfaceNumber;
  1246. //
  1247. // first close the current interface
  1248. //
  1249. ASSERT_INTERFACE(configHandle->InterfaceHandle[i]);
  1250. if (USBD_InternalInterfaceBusy(deviceData,
  1251. DeviceObject,
  1252. configHandle->InterfaceHandle[i])) {
  1253. Urb->UrbSelectInterface.Status =
  1254. SET_USBD_ERROR(USBD_STATUS_ERROR_BUSY);
  1255. // Note: usbd will map the urb error to to IoStatus
  1256. // block when the irp completes
  1257. goto USBD_SelectInterface_Done;
  1258. }
  1259. //
  1260. // Interface is not busy go ahead and close it
  1261. //
  1262. USBD_KdPrint(3, ("'close interface -- %d endpoints to close\n",
  1263. configHandle->InterfaceHandle[i]->InterfaceDescriptor.bNumEndpoints));
  1264. for (j=0; j<configHandle->InterfaceHandle[i]->InterfaceDescriptor.bNumEndpoints; j++) {
  1265. if (!PIPE_CLOSED(&configHandle->InterfaceHandle[i]->PipeHandle[j])) {
  1266. USBD_KdPrint(3, ("'close interface -- closing endpoint %x\n",
  1267. &configHandle->InterfaceHandle[i]->PipeHandle[j]));
  1268. ntStatus = USBD_CloseEndpoint(deviceData,
  1269. DeviceObject,
  1270. &configHandle->InterfaceHandle[i]->PipeHandle[j],
  1271. &Urb->UrbSelectInterface.Status);
  1272. //
  1273. // problem closing an endpoint, abort the SelectInterface operation.
  1274. // Note: This leaves the interface handle in an odd state ie some
  1275. // of the pipes are closed and some are not. We set a flag so that
  1276. // we can keep track of the pipes that have already beem closed
  1277. //
  1278. if (NT_SUCCESS(ntStatus)) {
  1279. // note that we closed this pipe
  1280. configHandle->InterfaceHandle[i]->PipeHandle[j].HcdEndpoint =
  1281. NULL;
  1282. } else {
  1283. TEST_TRAP();
  1284. goto USBD_SelectInterface_Done;
  1285. }
  1286. }
  1287. #if DBG
  1288. else {
  1289. // TEST_TRAP(); // This is normal in some multi-endpoint
  1290. // configurations if one has a bandwidth error.
  1291. USBD_KdPrint(3, ("'close interface -- encountered previously closed endpoint %x\n",
  1292. &configHandle->InterfaceHandle[i]->PipeHandle[j]));
  1293. }
  1294. #endif
  1295. }
  1296. USBD_ASSERT(NT_SUCCESS(ntStatus));
  1297. //
  1298. // All pipes in the current interface are now closed, free the memory
  1299. // associated with this interface
  1300. //
  1301. //
  1302. // save the old interface handle
  1303. //
  1304. oldInterfaceHandle = configHandle->InterfaceHandle[i];
  1305. configHandle->InterfaceHandle[i] = NULL;
  1306. //
  1307. // Now open the new interface with the new alternate setting
  1308. //
  1309. ntStatus = USBD_InternalOpenInterface(deviceData,
  1310. DeviceObject,
  1311. configHandle,
  1312. &Urb->UrbSelectInterface.Interface,
  1313. &configHandle->InterfaceHandle[i],
  1314. TRUE,
  1315. &noBandwidth);
  1316. if (NT_SUCCESS(ntStatus)) {
  1317. //
  1318. // successfully opened the new interface, we can free the old
  1319. // handle now.
  1320. //
  1321. RETHEAP(oldInterfaceHandle);
  1322. } else {
  1323. NTSTATUS status;
  1324. //
  1325. // selecting the aternate interface failed,
  1326. // possible reasons:
  1327. //
  1328. // 1. we didn't have enough BW
  1329. // 2. the device stalled the set_interface request
  1330. //
  1331. if (noBandwidth) {
  1332. Urb->UrbSelectInterface.Status = SET_USBD_ERROR(USBD_STATUS_NO_BANDWIDTH);
  1333. USBD_KdPrint(1, ("Failing SelectInterface -- No BW\n"));
  1334. }
  1335. // make sure everything is cleaned up.
  1336. //
  1337. USBD_ASSERT(configHandle->InterfaceHandle[i] == NULL);
  1338. // At this point we will attempt to restore the original interface,
  1339. // since the pipe handles are just pointers in to the interface structure
  1340. // they will remain valid even though the hcd endpoint handles have changed
  1341. // from being closed and re-opening.
  1342. configHandle->InterfaceHandle[i] = oldInterfaceHandle;
  1343. status = USBD_InternalOpenInterface(deviceData,
  1344. DeviceObject,
  1345. configHandle,
  1346. oldInterfaceHandle->InterfaceInformation,
  1347. &configHandle->InterfaceHandle[i],
  1348. FALSE,
  1349. NULL);
  1350. #if DBG
  1351. if (!NT_SUCCESS(status)) {
  1352. USBD_KdPrint(1, ("failed to restore the original interface\n"));
  1353. }
  1354. #endif
  1355. }
  1356. USBD_SelectInterface_Done:
  1357. //
  1358. // We did everything synchronously
  1359. //
  1360. USBD_ReleaseUsbDeviceMutex(deviceExtension);
  1361. *IrpIsPending = FALSE;
  1362. USBD_KdPrint(3, ("' exit USBD_SelectInterface 0x%x\n", ntStatus));
  1363. return ntStatus;
  1364. }
  1365. #endif // USBD_DRIVER