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.

686 lines
24 KiB

  1. /* ++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. USBUTILS.C
  5. Abstract:
  6. USB configuration utility functions.
  7. These functions are called in the context of PNP_START_DEVICE.
  8. In order to mark them pageable we don't use a spinlock,
  9. which is OK because of the context.
  10. We do not use look-aside lists to manage pool allocs here since they are one-shot.
  11. If the allocs fail then the load will fail.
  12. Environment:
  13. kernel mode only
  14. Revision History:
  15. 07-14-99 : created
  16. Authors:
  17. Jeff Midkiff (jeffmi)
  18. -- */
  19. #include <wdm.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <usbdi.h>
  23. #include <usbdlib.h>
  24. #include <ntddser.h>
  25. #include "wceusbsh.h"
  26. NTSTATUS
  27. UsbSelectInterface(
  28. IN PDEVICE_OBJECT PDevObj,
  29. IN PUSB_CONFIGURATION_DESCRIPTOR PConfigDesc,
  30. IN UCHAR AlternateSetting
  31. );
  32. #ifdef ALLOC_PRAGMA
  33. #pragma alloc_text(PAGEWCE1, UsbGetDeviceDescriptor)
  34. #pragma alloc_text(PAGEWCE1, UsbSelectInterface)
  35. #pragma alloc_text(PAGEWCE1, UsbConfigureDevice)
  36. #endif
  37. /*
  38. Sample dump for the Anchor EZ-Link (AN2720) cable:
  39. WCEUSBSH(0): DeviceDescriptor: fbfa8fe8
  40. WCEUSBSH(0): Length 12
  41. WCEUSBSH(0):
  42. WCEUSBSH(0): Device Descriptor
  43. WCEUSBSH(0): ------------------------
  44. WCEUSBSH(0): bLength 12
  45. WCEUSBSH(0): bDescriptorType 1
  46. WCEUSBSH(0): bcdUSB 100
  47. WCEUSBSH(0): bDeviceClass ff
  48. WCEUSBSH(0): bDeviceSubClass ff
  49. WCEUSBSH(0): bDeviceProtocol ff
  50. WCEUSBSH(0): bMaxPacketSize0 8
  51. WCEUSBSH(0): idVendor 547
  52. WCEUSBSH(0): idProduct 2720
  53. WCEUSBSH(0): bcdDevice 0
  54. WCEUSBSH(0): iManufacturer 0
  55. WCEUSBSH(0): iProduct 0
  56. WCEUSBSH(0): iSerialNumber 0
  57. WCEUSBSH(0): bNumConfigs 1
  58. WCEUSBSH(0): ------------------------
  59. WCEUSBSH(0):
  60. WCEUSBSH(0): Configuration Descriptor
  61. WCEUSBSH(0): ----------------
  62. WCEUSBSH(0): bLength 9
  63. WCEUSBSH(0): bDescriptorType 2
  64. WCEUSBSH(0): wTotalLength d0
  65. WCEUSBSH(0): bNumInterfaces 1
  66. WCEUSBSH(0): bConfigurationValue 1
  67. WCEUSBSH(0): iConfiguration 0
  68. WCEUSBSH(0): bmAttributes a0
  69. WCEUSBSH(0): MaxPower 32
  70. WCEUSBSH(0): ----------------
  71. WCEUSBSH(0):
  72. WCEUSBSH(0): Interface Descriptor(0)
  73. WCEUSBSH(0): ------------------------
  74. WCEUSBSH(0): bLength 9
  75. WCEUSBSH(0): bDescriptorType 4
  76. WCEUSBSH(0): bInterfaceNumber 0
  77. WCEUSBSH(0): bAlternateSetting 0
  78. WCEUSBSH(0): bNumEndpoints 2
  79. WCEUSBSH(0): bInterfaceClass ff
  80. WCEUSBSH(0): bInterfaceSubClass ff
  81. WCEUSBSH(0): bInterfaceProtocol ff
  82. WCEUSBSH(0): iInterface 0
  83. WCEUSBSH(0): ------------------------
  84. WCEUSBSH(0):
  85. WCEUSBSH(0): Interface Definition
  86. WCEUSBSH(0): ------------------------
  87. WCEUSBSH(0): Number of pipes 2
  88. WCEUSBSH(0): Length 38
  89. WCEUSBSH(0): Alt Setting 0
  90. WCEUSBSH(0): Interface Number 0
  91. WCEUSBSH(0): Class ff
  92. WCEUSBSH(0): Subclass ff
  93. WCEUSBSH(0): Protocol ff
  94. WCEUSBSH(0): ------------------------
  95. WCEUSBSH(0): 'COMM' Device Found at Index:0 InterfaceNumber:0 AlternateSetting: 0
  96. WCEUSBSH(0):
  97. WCEUSBSH(0): Pipe Information (0)
  98. WCEUSBSH(0): ----------------
  99. WCEUSBSH(0): Pipe Type 2
  100. WCEUSBSH(0): Endpoint Addr 82
  101. WCEUSBSH(0): MaxPacketSize 40
  102. WCEUSBSH(0): Interval 0
  103. WCEUSBSH(0): Handle fbfcef90
  104. WCEUSBSH(0): MaxTransSize 1ffff
  105. WCEUSBSH(0): ----------------
  106. WCEUSBSH(0):
  107. WCEUSBSH(0): Pipe Information (1)
  108. WCEUSBSH(0): ----------------
  109. WCEUSBSH(0): Pipe Type 2
  110. WCEUSBSH(0): Endpoint Addr 2
  111. WCEUSBSH(0): MaxPacketSize 40
  112. WCEUSBSH(0): Interval 0
  113. WCEUSBSH(0): Handle fbfcefac
  114. WCEUSBSH(0): MaxTransSize 1ffff
  115. WCEUSBSH(0): ----------------
  116. WCEUSBSH(0): IntPipe: 0 DataOutPipe: fbfcefac DataInPipe: fbfcef90
  117. */
  118. NTSTATUS
  119. UsbGetDeviceDescriptor(
  120. IN PDEVICE_OBJECT PDevObj
  121. )
  122. {
  123. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  124. NTSTATUS status;
  125. ULONG descSize;
  126. ULONG urbCDRSize;
  127. PURB pUrb;
  128. DbgDump(DBG_USB, (">UsbGetDeviceDescriptor\n"));
  129. PAGED_CODE();
  130. urbCDRSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
  131. pUrb = ExAllocatePool(NonPagedPool, urbCDRSize);
  132. if (pUrb != NULL) {
  133. descSize = sizeof(USB_DEVICE_DESCRIPTOR);
  134. RtlZeroMemory(&pDevExt->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
  135. UsbBuildGetDescriptorRequest(pUrb,
  136. (USHORT)urbCDRSize,
  137. USB_DEVICE_DESCRIPTOR_TYPE,
  138. 0,
  139. 0,
  140. &pDevExt->DeviceDescriptor,
  141. NULL,
  142. descSize,
  143. NULL );
  144. status = UsbSubmitSyncUrb( PDevObj, pUrb, TRUE, DEFAULT_CTRL_TIMEOUT );
  145. if (STATUS_SUCCESS == status) {
  146. #if DBG
  147. if (DebugLevel & DBG_USB) {
  148. DbgDump(DBG_USB, ("Device Descriptor\n"));
  149. DbgDump(DBG_USB, ("------------------------\n"));
  150. DbgDump(DBG_USB, ("bLength 0x%x\n", pDevExt->DeviceDescriptor.bLength));
  151. DbgDump(DBG_USB, ("bDescriptorType 0x%x\n", pDevExt->DeviceDescriptor.bDescriptorType));
  152. DbgDump(DBG_USB, ("bcdUSB 0x%x\n", pDevExt->DeviceDescriptor.bcdUSB));
  153. DbgDump(DBG_USB, ("bDeviceClass 0x%x\n", pDevExt->DeviceDescriptor.bDeviceClass));
  154. DbgDump(DBG_USB, ("bDeviceSubClass 0x%x\n", pDevExt->DeviceDescriptor.bDeviceSubClass));
  155. DbgDump(DBG_USB, ("bDeviceProtocol 0x%x\n", pDevExt->DeviceDescriptor.bDeviceProtocol));
  156. DbgDump(DBG_USB, ("bMaxPacketSize0 0x%x\n", pDevExt->DeviceDescriptor.bMaxPacketSize0));
  157. DbgDump(DBG_USB, ("idVendor 0x%x\n", pDevExt->DeviceDescriptor.idVendor));
  158. DbgDump(DBG_USB, ("idProduct 0x%x\n", pDevExt->DeviceDescriptor.idProduct));
  159. DbgDump(DBG_USB, ("bcdDevice 0x%x\n", pDevExt->DeviceDescriptor.bcdDevice));
  160. DbgDump(DBG_USB, ("iManufacturer 0x%x\n", pDevExt->DeviceDescriptor.iManufacturer));
  161. DbgDump(DBG_USB, ("iProduct 0x%x\n", pDevExt->DeviceDescriptor.iProduct));
  162. DbgDump(DBG_USB, ("iSerialNumber 0x%x\n", pDevExt->DeviceDescriptor.iSerialNumber));
  163. DbgDump(DBG_USB, ("bNumConfigs 0x%x\n", pDevExt->DeviceDescriptor.bNumConfigurations));
  164. DbgDump(DBG_USB, ("------------------------\n"));
  165. }
  166. #endif
  167. } else {
  168. DbgDump(DBG_ERR, ("UsbSubmitSyncUrb error: 0x%x\n", status));
  169. RtlZeroMemory(&pDevExt->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
  170. }
  171. ExFreePool(pUrb);
  172. } else {
  173. status = STATUS_INSUFFICIENT_RESOURCES;
  174. DbgDump(DBG_ERR, ("UsbGetDeviceDescriptor 0x%x\n", status));
  175. }
  176. if (STATUS_INSUFFICIENT_RESOURCES == status) {
  177. LogError( NULL,
  178. PDevObj,
  179. 0, 0, 0,
  180. ERR_GET_DEVICE_DESCRIPTOR,
  181. status,
  182. SERIAL_INSUFFICIENT_RESOURCES,
  183. pDevExt->DeviceName.Length + sizeof(WCHAR),
  184. pDevExt->DeviceName.Buffer,
  185. 0, NULL );
  186. } else if (STATUS_SUCCESS != status ) {
  187. // handles all other failures
  188. LogError( NULL,
  189. PDevObj,
  190. 0, 0, 0,
  191. ERR_GET_DEVICE_DESCRIPTOR,
  192. status,
  193. SERIAL_HARDWARE_FAILURE,
  194. pDevExt->DeviceName.Length + sizeof(WCHAR),
  195. pDevExt->DeviceName.Buffer,
  196. 0,
  197. NULL
  198. );
  199. }
  200. DbgDump(DBG_USB, ("<UsbGetDeviceDescriptor 0x%x\n", status));
  201. return status;
  202. }
  203. //
  204. // BUGBUG: currently assumes 1 interface
  205. //
  206. NTSTATUS
  207. UsbSelectInterface(
  208. IN PDEVICE_OBJECT PDevObj,
  209. IN PUSB_CONFIGURATION_DESCRIPTOR PConfigDesc,
  210. IN UCHAR AlternateSetting
  211. )
  212. {
  213. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  214. NTSTATUS status = STATUS_SUCCESS;
  215. PURB pUrb = NULL;
  216. ULONG pipe;
  217. ULONG index = 0;
  218. UCHAR interfaceNumber = 0;
  219. PUSBD_INTERFACE_INFORMATION pInterfaceInfo = NULL;
  220. BOOLEAN foundCommDevice = FALSE;
  221. USBD_INTERFACE_LIST_ENTRY interfaceList[2] = {0, 0};
  222. DbgDump(DBG_USB, (">UsbSelectInterface %d\n", AlternateSetting));
  223. PAGED_CODE();
  224. if ( !PDevObj || !PConfigDesc ) {
  225. status = STATUS_INVALID_PARAMETER;
  226. DbgDump(DBG_ERR, ("UsbSelectInterface 0x%x\n", status));
  227. goto SelectInterfaceError;
  228. }
  229. interfaceList[0].InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
  230. PConfigDesc,
  231. PConfigDesc,
  232. -1,
  233. AlternateSetting,
  234. -1,
  235. -1,
  236. -1 );
  237. if (interfaceList[0].InterfaceDescriptor) {
  238. // interfaceList[1].InterfaceDescriptor = NULL;
  239. DbgDump(DBG_USB, ("\n"));
  240. DbgDump(DBG_USB, ("Interface Descriptor(%d)\n", interfaceNumber ));
  241. DbgDump(DBG_USB, ("------------------------\n"));
  242. DbgDump(DBG_USB, ("bLength 0x%x\n", interfaceList[0].InterfaceDescriptor->bLength ));
  243. DbgDump(DBG_USB, ("bDescriptorType 0x%x\n", interfaceList[0].InterfaceDescriptor->bDescriptorType));
  244. DbgDump(DBG_USB, ("bInterfaceNumber 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceNumber ));
  245. DbgDump(DBG_USB, ("bAlternateSetting 0x%x\n", interfaceList[0].InterfaceDescriptor->bAlternateSetting ));
  246. DbgDump(DBG_USB, ("bNumEndpoints 0x%x\n", interfaceList[0].InterfaceDescriptor->bNumEndpoints ));
  247. DbgDump(DBG_USB, ("bInterfaceClass 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceClass ));
  248. DbgDump(DBG_USB, ("bInterfaceSubClass 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceSubClass ));
  249. DbgDump(DBG_USB, ("bInterfaceProtocol 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceProtocol ));
  250. DbgDump(DBG_USB, ("iInterface 0x%x\n", interfaceList[0].InterfaceDescriptor->iInterface ));
  251. DbgDump(DBG_USB, ("------------------------\n"));
  252. pUrb = USBD_CreateConfigurationRequestEx( PConfigDesc,
  253. &interfaceList[0]);
  254. if ( pUrb ) {
  255. //
  256. // perform any pipe initialization here
  257. //
  258. PUSBD_INTERFACE_INFORMATION pInitInterfaceInfo = &pUrb->UrbSelectConfiguration.Interface;
  259. for ( index = 0;
  260. index < interfaceList[0].InterfaceDescriptor->bNumEndpoints;
  261. index++) {
  262. pInitInterfaceInfo->Pipes[index].MaximumTransferSize = pDevExt->MaximumTransferSize;
  263. pInitInterfaceInfo->Pipes[index].PipeFlags = 0;
  264. }
  265. status = UsbSubmitSyncUrb(PDevObj, pUrb, TRUE, DEFAULT_CTRL_TIMEOUT );
  266. if (STATUS_SUCCESS == status) {
  267. pDevExt->ConfigurationHandle = pUrb->UrbSelectConfiguration.ConfigurationHandle;
  268. pInterfaceInfo = &pUrb->UrbSelectConfiguration.Interface;
  269. DbgDump(DBG_USB, ("Interface Definition\n" ));
  270. DbgDump(DBG_USB, ("------------------------\n"));
  271. DbgDump(DBG_USB, ("Number of pipes 0x%x\n", pInterfaceInfo->NumberOfPipes));
  272. DbgDump(DBG_USB, ("Length 0x%x\n", pInterfaceInfo->Length));
  273. DbgDump(DBG_USB, ("Alt Setting 0x%x\n", pInterfaceInfo->AlternateSetting));
  274. DbgDump(DBG_USB, ("Interface Number 0x%x\n", pInterfaceInfo->InterfaceNumber));
  275. DbgDump(DBG_USB, ("Class 0x%x\n", pInterfaceInfo->Class));
  276. DbgDump(DBG_USB, ("Subclass 0x%x\n", pInterfaceInfo->SubClass));
  277. DbgDump(DBG_USB, ("Protocol 0x%x\n", pInterfaceInfo->Protocol));
  278. DbgDump(DBG_USB, ("------------------------\n"));
  279. if ( (pInterfaceInfo->Class == USB_NULL_MODEM_CLASS) &&
  280. (pInterfaceInfo->AlternateSetting == AlternateSetting) &&
  281. (pInterfaceInfo->NumberOfPipes)) {
  282. foundCommDevice = TRUE;
  283. pDevExt->UsbInterfaceNumber = pInterfaceInfo->InterfaceNumber;
  284. } else {
  285. status = STATUS_NO_SUCH_DEVICE;
  286. DbgDump(DBG_ERR, ("UsbSelectInterface 0x%x\n", status));
  287. goto SelectInterfaceError;
  288. }
  289. } else {
  290. DbgDump(DBG_ERR, ("UsbSubmitSyncUrb 0x%x\n", status));
  291. goto SelectInterfaceError;
  292. }
  293. } else {
  294. status = STATUS_INSUFFICIENT_RESOURCES;
  295. DbgDump(DBG_ERR, ("USBD_CreateConfigurationRequestEx 0x%x\n", status));
  296. goto SelectInterfaceError;
  297. }
  298. DbgDump(DBG_USB, ("\n"));
  299. DbgDump(DBG_USB, ("Function Device Found at Index:0x%x InterfaceNumber:0x%x AlternateSetting: 0x%x\n",
  300. interfaceNumber, pDevExt->UsbInterfaceNumber, AlternateSetting));
  301. //
  302. // We found the interface we want, now discover the pipes
  303. // The standard interface is defined to contain 1 bulk read, 1 bulk write, and an optional INT pipe
  304. // BUGBUG: if there are more endpoints then they will overwrite the previous with this code.
  305. //
  306. ASSERT( pInterfaceInfo );
  307. for ( pipe = 0; pipe < pInterfaceInfo->NumberOfPipes; pipe++) {
  308. PUSBD_PIPE_INFORMATION pPipeInfo;
  309. pPipeInfo = &pInterfaceInfo->Pipes[pipe];
  310. DbgDump(DBG_USB, ("\n"));
  311. DbgDump(DBG_USB, ("Pipe Information (%d)\n", pipe));
  312. DbgDump(DBG_USB, ("----------------\n"));
  313. DbgDump(DBG_USB, ("Pipe Type 0x%x\n", pPipeInfo->PipeType));
  314. DbgDump(DBG_USB, ("Endpoint Addr 0x%x\n", pPipeInfo->EndpointAddress));
  315. DbgDump(DBG_USB, ("MaxPacketSize 0x%x\n", pPipeInfo->MaximumPacketSize));
  316. DbgDump(DBG_USB, ("Interval 0x%x\n", pPipeInfo->Interval));
  317. DbgDump(DBG_USB, ("Handle 0x%x\n", pPipeInfo->PipeHandle));
  318. DbgDump(DBG_USB, ("MaxTransSize 0x%x\n", pPipeInfo->MaximumTransferSize));
  319. DbgDump(DBG_USB, ("----------------\n"));
  320. //
  321. // save pipe info in our device extension
  322. //
  323. if ( USB_ENDPOINT_DIRECTION_IN( pPipeInfo->EndpointAddress ) ) {
  324. //
  325. // Bulk Data In pipe
  326. //
  327. if ( USB_ENDPOINT_TYPE_BULK == pPipeInfo->PipeType) {
  328. //
  329. // Bulk IN pipe
  330. //
  331. pDevExt->ReadPipe.wIndex = pPipeInfo->EndpointAddress;
  332. pDevExt->ReadPipe.hPipe = pPipeInfo->PipeHandle;
  333. pDevExt->ReadPipe.MaxPacketSize = pPipeInfo->MaximumPacketSize;
  334. } else if ( USB_ENDPOINT_TYPE_INTERRUPT == pPipeInfo->PipeType ) {
  335. //
  336. // INT Pipe - alloc a notify buffer for 1 packet
  337. //
  338. PVOID pOldBuff = NULL;
  339. PVOID pNewBuff = NULL;
  340. pDevExt->IntPipe.MaxPacketSize = pPipeInfo->MaximumPacketSize;
  341. if ( pDevExt->IntPipe.MaxPacketSize ) {
  342. pNewBuff = ExAllocatePool( NonPagedPool, pDevExt->IntPipe.MaxPacketSize );
  343. if ( !pNewBuff ) {
  344. status = STATUS_INSUFFICIENT_RESOURCES;
  345. DbgDump(DBG_ERR, ("ExAllocatePool: 0x%x\n", status));
  346. goto SelectInterfaceError;
  347. }
  348. } else {
  349. DbgDump(DBG_ERR, ("No INT MaximumPacketSize\n"));
  350. status = STATUS_NO_SUCH_DEVICE;
  351. goto SelectInterfaceError;
  352. }
  353. if (pDevExt->IntBuff) {
  354. pOldBuff = pDevExt->IntBuff;
  355. ExFreePool(pOldBuff);
  356. }
  357. pDevExt->IntBuff = pNewBuff;
  358. pDevExt->IntPipe.hPipe = pPipeInfo->PipeHandle;
  359. pDevExt->IntPipe.wIndex = pPipeInfo->EndpointAddress;
  360. pDevExt->IntReadTimeOut.QuadPart = MILLISEC_TO_100NANOSEC( g_lIntTimout );
  361. } else {
  362. DbgDump(DBG_ERR, ("Invalid IN PipeType"));
  363. status = STATUS_NO_SUCH_DEVICE;
  364. goto SelectInterfaceError;
  365. }
  366. } else if ( USB_ENDPOINT_DIRECTION_OUT( pPipeInfo->EndpointAddress ) ) {
  367. //
  368. // OUT EPs
  369. //
  370. if ( USB_ENDPOINT_TYPE_BULK == pPipeInfo->PipeType ) {
  371. //
  372. // Bulk OUT Pipe
  373. //
  374. pDevExt->WritePipe.hPipe = pPipeInfo->PipeHandle;
  375. pDevExt->WritePipe.wIndex = pPipeInfo->EndpointAddress;
  376. pDevExt->WritePipe.MaxPacketSize = pPipeInfo->MaximumPacketSize;
  377. } else {
  378. DbgDump(DBG_ERR, ("Invalid OUT PipeType"));
  379. status = STATUS_NO_SUCH_DEVICE;
  380. goto SelectInterfaceError;
  381. }
  382. } else {
  383. DbgDump(DBG_ERR, ("Invalid EndpointAddress"));
  384. status = STATUS_NO_SUCH_DEVICE;
  385. goto SelectInterfaceError;
  386. }
  387. }
  388. DbgDump(DBG_USB, ("\n"));
  389. DbgDump(DBG_USB, ("INT Pipe: %p\t OUT Pipe: %p\t IN Pipe: %p\n",
  390. pDevExt->IntPipe.hPipe, pDevExt->WritePipe.hPipe, pDevExt->ReadPipe.hPipe ));
  391. } else {
  392. DbgDump(DBG_ERR, ("USBD_ParseConfigurationDescriptorEx: No match not found\n"));
  393. status = STATUS_NO_SUCH_DEVICE;
  394. goto SelectInterfaceError;
  395. }
  396. //
  397. // did we find all of our pipes?
  398. //
  399. SelectInterfaceError:
  400. if ( !foundCommDevice || !pDevExt->ReadPipe.hPipe || !pDevExt->WritePipe.hPipe || (STATUS_SUCCESS != status) ) {
  401. LogError( NULL,
  402. PDevObj,
  403. 0, 0, 0,
  404. ERR_SELECT_INTERFACE,
  405. status,
  406. (status == STATUS_INSUFFICIENT_RESOURCES) ? SERIAL_INSUFFICIENT_RESOURCES : SERIAL_HARDWARE_FAILURE,
  407. pDevExt->DeviceName.Length + sizeof(WCHAR),
  408. pDevExt->DeviceName.Buffer,
  409. 0, NULL );
  410. }
  411. if ( pUrb ) {
  412. ExFreePool(pUrb);
  413. }
  414. DbgDump(DBG_USB, ("<UsbSelectInterface 0x%x\n", status));
  415. return status;
  416. }
  417. NTSTATUS
  418. UsbConfigureDevice(
  419. IN PDEVICE_OBJECT PDevObj
  420. )
  421. {
  422. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  423. PUSB_CONFIGURATION_DESCRIPTOR pConDesc = NULL;
  424. NTSTATUS status = STATUS_UNSUCCESSFUL;
  425. PURB pUrb = NULL;
  426. ULONG size;
  427. ULONG urbCDRSize;
  428. ULONG numConfigs;
  429. UCHAR config;
  430. DbgDump(DBG_USB, (">UsbConfigureDevice\n"));
  431. PAGED_CODE();
  432. urbCDRSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
  433. // configure the device
  434. pUrb = ExAllocatePool(NonPagedPool, urbCDRSize);
  435. if (pUrb == NULL) {
  436. status = STATUS_INSUFFICIENT_RESOURCES;
  437. DbgDump(DBG_ERR, ("UsbConfigureDevice ERROR: 0x%x\n", status));
  438. goto ConfigureDeviceError;
  439. }
  440. //
  441. // there may be problems with the 82930 chip, so make this buffer bigger
  442. // to prevent choking
  443. //
  444. size = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 256;
  445. //
  446. // get the number of configurations
  447. //
  448. numConfigs = pDevExt->DeviceDescriptor.bNumConfigurations;
  449. //
  450. // walk all of the configurations looking for a CDC device
  451. //
  452. for (config = 0; config < numConfigs; config++) {
  453. //
  454. // we will probably only do this once, maybe twice
  455. //
  456. while (TRUE) {
  457. pConDesc = ExAllocatePool(NonPagedPool, size);
  458. if (pConDesc == NULL) {
  459. status = STATUS_INSUFFICIENT_RESOURCES;
  460. DbgDump(DBG_ERR, ("ExAllocatePool: 0x%x\n", status));
  461. goto ConfigureDeviceError;
  462. }
  463. //
  464. // Get descriptor information from the host controller driver (HCD).
  465. // All interface, endpoint, class-specific, and vendor-specific descriptors
  466. // for the configuration also are retrieved
  467. //
  468. UsbBuildGetDescriptorRequest( pUrb,
  469. (USHORT)urbCDRSize,
  470. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  471. config, // Index
  472. 0, // LanguageId
  473. pConDesc,// TransferBuffer
  474. NULL, // TransferBufferMdl
  475. size, // TransferBufferLength
  476. NULL); // Link
  477. status = UsbSubmitSyncUrb( PDevObj, pUrb, TRUE, DEFAULT_CTRL_TIMEOUT );
  478. if (status != STATUS_SUCCESS) {
  479. DbgDump(DBG_ERR, ("UsbSubmitSyncUrb: 0x%x\n", status));
  480. goto ConfigureDeviceError;
  481. }
  482. //
  483. // see if we got enough data, we may get an error in URB because of
  484. // buffer overrun
  485. //
  486. if ((pUrb->UrbControlDescriptorRequest.TransferBufferLength > 0)
  487. && (pConDesc->wTotalLength > size)) {
  488. //
  489. // size of data exceeds current buffer size, so allocate correct
  490. // size
  491. //
  492. size = pConDesc->wTotalLength;
  493. ExFreePool(pConDesc);
  494. pConDesc = NULL;
  495. } else {
  496. break;
  497. }
  498. }
  499. #if DBG
  500. DbgDump(DBG_USB, ("\n"));
  501. DbgDump(DBG_USB, ("Configuration Descriptor\n" ));
  502. DbgDump(DBG_USB, ("----------------\n"));
  503. DbgDump(DBG_USB, ("bLength 0x%x\n", pConDesc->bLength ));
  504. DbgDump(DBG_USB, ("bDescriptorType 0x%x\n", pConDesc->bDescriptorType ));
  505. DbgDump(DBG_USB, ("wTotalLength 0x%x\n", pConDesc->wTotalLength ));
  506. DbgDump(DBG_USB, ("bNumInterfaces 0x%x\n", pConDesc->bNumInterfaces ));
  507. DbgDump(DBG_USB, ("bConfigurationValue 0x%x\n", pConDesc->bConfigurationValue ));
  508. DbgDump(DBG_USB, ("iConfiguration 0x%x\n", pConDesc->iConfiguration ));
  509. DbgDump(DBG_USB, ("bmAttributes 0x%x\n", pConDesc->bmAttributes ));
  510. DbgDump(DBG_USB, ("MaxPower 0x%x\n", pConDesc->MaxPower ));
  511. DbgDump(DBG_USB, ("----------------\n"));
  512. DbgDump(DBG_USB, ("\n"));
  513. #endif
  514. status = UsbSelectInterface(PDevObj, pConDesc, (UCHAR)g_ulAlternateSetting);
  515. ExFreePool(pConDesc);
  516. pConDesc = NULL;
  517. //
  518. // found a config we like
  519. //
  520. if (status == STATUS_SUCCESS)
  521. break;
  522. } // config
  523. ConfigureDeviceError:
  524. if (pUrb != NULL) {
  525. ExFreePool(pUrb);
  526. }
  527. if (pConDesc != NULL) {
  528. ExFreePool(pConDesc);
  529. }
  530. if (STATUS_INSUFFICIENT_RESOURCES == status) {
  531. LogError( NULL,
  532. PDevObj,
  533. 0, 0, 0,
  534. ERR_CONFIG_DEVICE,
  535. status,
  536. SERIAL_INSUFFICIENT_RESOURCES,
  537. pDevExt->DeviceName.Length + sizeof(WCHAR),
  538. pDevExt->DeviceName.Buffer,
  539. 0, NULL );
  540. } else if (STATUS_SUCCESS != status ) {
  541. // handles all other failures
  542. LogError( NULL,
  543. PDevObj,
  544. 0, 0, 0,
  545. ERR_CONFIG_DEVICE,
  546. status,
  547. SERIAL_HARDWARE_FAILURE,
  548. pDevExt->DeviceName.Length + sizeof(WCHAR),
  549. pDevExt->DeviceName.Buffer,
  550. 0, NULL );
  551. }
  552. DbgDump(DBG_USB, ("<UsbConfigureDevice (0x%x)\n", status));
  553. return status;
  554. }
  555. // EOF