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.

711 lines
20 KiB

  1. #include "usbcom.h"
  2. #include "usbsc.h"
  3. #include <usbutil.h>
  4. #include <usb.h>
  5. #include <usbdlib.h>
  6. NTSTATUS
  7. UsbWrite(
  8. PREADER_EXTENSION ReaderExtension,
  9. PUCHAR pData,
  10. ULONG DataLen,
  11. LONG Timeout)
  12. /*++
  13. Description:
  14. Write data to the usb port
  15. Arguments:
  16. ReaderExtension context of call
  17. pData ptr to data buffer
  18. DataLen length of data buffer
  19. Return Value:
  20. NTSTATUS
  21. --*/
  22. {
  23. NTSTATUS status = STATUS_SUCCESS;
  24. PURB pUrb = NULL;
  25. PDEVICE_OBJECT DeviceObject;
  26. PDEVICE_EXTENSION DeviceExtension;
  27. ULONG ulSize;
  28. __try
  29. {
  30. SmartcardDebug( DEBUG_TRACE, ("%s!UsbWrite Enter\n",DRIVER_NAME ));
  31. DeviceObject = ReaderExtension->DeviceObject;
  32. DeviceExtension = DeviceObject->DeviceExtension;
  33. ulSize = sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
  34. pUrb = ExAllocatePool( NonPagedPool,
  35. ulSize );
  36. if(pUrb == NULL) {
  37. status = STATUS_INSUFFICIENT_RESOURCES;
  38. } else {
  39. UsbBuildInterruptOrBulkTransferRequest(pUrb,
  40. (USHORT)ulSize,
  41. ReaderExtension->BulkOutHandle,
  42. pData,
  43. NULL,
  44. DataLen,
  45. USBD_SHORT_TRANSFER_OK,
  46. NULL);
  47. status = USBCallSync(DeviceExtension->LowerDeviceObject,
  48. pUrb,
  49. Timeout,
  50. &DeviceExtension->RemoveLock);
  51. ExFreePool( pUrb );
  52. pUrb = NULL;
  53. }
  54. }
  55. __finally
  56. {
  57. if (pUrb) {
  58. ExFreePool(pUrb);
  59. pUrb = NULL;
  60. }
  61. SmartcardDebug( DEBUG_TRACE, ("%s!UsbWrite Exit : 0x%x\n",DRIVER_NAME, status ));
  62. }
  63. return status;
  64. }
  65. NTSTATUS
  66. UsbRead(
  67. PREADER_EXTENSION ReaderExtension,
  68. PUCHAR pData,
  69. ULONG DataLen,
  70. LONG Timeout)
  71. /*++
  72. Description:
  73. Read data from the USB bus
  74. Arguments:
  75. ReaderExtension context of call
  76. pData ptr to data buffer
  77. DataLen length of data buffer
  78. pNBytes number of bytes returned
  79. Return Value:
  80. STATUS_SUCCESS
  81. STATUS_BUFFER_TOO_SMALL
  82. STATUS_UNSUCCESSFUL
  83. --*/
  84. {
  85. NTSTATUS status = STATUS_SUCCESS;
  86. PURB pUrb = NULL;
  87. PDEVICE_OBJECT DeviceObject;
  88. PDEVICE_EXTENSION DeviceExtension;
  89. ULONG ulSize;
  90. __try
  91. {
  92. SmartcardDebug( DEBUG_TRACE, ("%s!UsbRead Enter\n",DRIVER_NAME ));
  93. DeviceObject = ReaderExtension->DeviceObject;
  94. DeviceExtension = DeviceObject->DeviceExtension;
  95. ulSize = sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
  96. pUrb = ExAllocatePool( NonPagedPool,
  97. ulSize );
  98. if(pUrb == NULL) {
  99. status = STATUS_INSUFFICIENT_RESOURCES;
  100. __leave;
  101. } else {
  102. UsbBuildInterruptOrBulkTransferRequest(pUrb,
  103. (USHORT)ulSize,
  104. ReaderExtension->BulkInHandle,
  105. pData,
  106. NULL,
  107. DataLen,
  108. USBD_SHORT_TRANSFER_OK,
  109. NULL);
  110. status = USBCallSync(DeviceExtension->LowerDeviceObject,
  111. pUrb,
  112. Timeout,
  113. &DeviceExtension->RemoveLock);
  114. }
  115. }
  116. __finally
  117. {
  118. if (pUrb) {
  119. ExFreePool(pUrb);
  120. pUrb = NULL;
  121. }
  122. SmartcardDebug( DEBUG_TRACE, ("%s!UsbRead Exit : 0x%x\n",DRIVER_NAME, status ));
  123. }
  124. return status;
  125. }
  126. NTSTATUS
  127. UsbConfigureDevice(
  128. IN PDEVICE_OBJECT DeviceObject
  129. )
  130. /*++
  131. Routine Description:
  132. Initializes a given instance of the device on the USB and
  133. selects and saves the configuration.
  134. Also saves the Class Descriptor and the pipe handles.
  135. Arguments:
  136. DeviceObject - pointer to the physical device object for this instance of the device.
  137. Return Value:
  138. NT status code
  139. --*/
  140. {
  141. PDEVICE_EXTENSION pDevExt;
  142. PSMARTCARD_EXTENSION smartcardExt;
  143. PREADER_EXTENSION readerExt;
  144. NTSTATUS status = STATUS_SUCCESS;
  145. PURB pUrb = NULL;
  146. ULONG ulSize;
  147. PUSB_CONFIGURATION_DESCRIPTOR
  148. ConfigurationDescriptor = NULL;
  149. PUSB_COMMON_DESCRIPTOR
  150. comDesc;
  151. UINT i;
  152. __try
  153. {
  154. SmartcardDebug( DEBUG_TRACE, ("%s!UsbConfigureDevice Enter\n",DRIVER_NAME ));
  155. pDevExt = DeviceObject->DeviceExtension;
  156. smartcardExt = &pDevExt->SmartcardExtension;
  157. readerExt = smartcardExt->ReaderExtension;
  158. pUrb = ExAllocatePool(NonPagedPool,
  159. sizeof( struct _URB_CONTROL_DESCRIPTOR_REQUEST ));
  160. if( pUrb == NULL) {
  161. status = STATUS_INSUFFICIENT_RESOURCES;
  162. __leave;
  163. }
  164. //
  165. // Get the device descriptor
  166. //
  167. pDevExt->DeviceDescriptor = ExAllocatePool(NonPagedPool,
  168. sizeof(USB_DEVICE_DESCRIPTOR));
  169. if(pDevExt->DeviceDescriptor == NULL) {
  170. status = STATUS_INSUFFICIENT_RESOURCES;
  171. __leave;
  172. }
  173. UsbBuildGetDescriptorRequest(pUrb,
  174. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  175. USB_DEVICE_DESCRIPTOR_TYPE,
  176. 0,
  177. 0,
  178. pDevExt->DeviceDescriptor,
  179. NULL,
  180. sizeof(USB_DEVICE_DESCRIPTOR),
  181. NULL);
  182. // Send the urb to the USB driver
  183. status = USBCallSync(pDevExt->LowerDeviceObject,
  184. pUrb,
  185. 0,
  186. &pDevExt->RemoveLock);
  187. if(!NT_SUCCESS(status)) {
  188. __leave;
  189. }
  190. // When USB_CONFIGURATION_DESCRIPTOR_TYPE is specified for DescriptorType
  191. // in a call to UsbBuildGetDescriptorRequest(),
  192. // all interface, endpoint, class-specific, and vendor-specific descriptors
  193. // for the configuration also are retrieved.
  194. // The caller must allocate a buffer large enough to hold all of this
  195. // information or the data is truncated without error.
  196. // Therefore the 'siz' set below is just a guess, and we may have to retry
  197. ulSize = sizeof( USB_CONFIGURATION_DESCRIPTOR );
  198. // We will break out of this 'retry loop' when UsbBuildGetDescriptorRequest()
  199. // has a big enough deviceExtension->UsbConfigurationDescriptor buffer not to truncate
  200. while( 1 ) {
  201. ConfigurationDescriptor = ExAllocatePool( NonPagedPool, ulSize );
  202. if(ConfigurationDescriptor == NULL) {
  203. status = STATUS_INSUFFICIENT_RESOURCES;
  204. __leave;
  205. }
  206. UsbBuildGetDescriptorRequest(pUrb,
  207. sizeof( struct _URB_CONTROL_DESCRIPTOR_REQUEST ),
  208. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  209. 0,
  210. 0,
  211. ConfigurationDescriptor,
  212. NULL,
  213. ulSize,
  214. NULL );
  215. status = USBCallSync(pDevExt->LowerDeviceObject,
  216. pUrb,
  217. 0,
  218. &pDevExt->RemoveLock);
  219. // if we got some data see if it was enough.
  220. // NOTE: we may get an error in URB because of buffer overrun
  221. if (pUrb->UrbControlDescriptorRequest.TransferBufferLength == 0 ||
  222. ConfigurationDescriptor->wTotalLength <= ulSize) {
  223. break;
  224. }
  225. ulSize = ConfigurationDescriptor->wTotalLength;
  226. ExFreePool(ConfigurationDescriptor);
  227. ConfigurationDescriptor = NULL;
  228. }
  229. //
  230. // We have the configuration descriptor for the configuration we want.
  231. // Now we issue the select configuration command to get
  232. // the pipes associated with this configuration.
  233. //
  234. if(!NT_SUCCESS(status)) {
  235. __leave;
  236. }
  237. status = UsbSelectInterfaces(DeviceObject,
  238. ConfigurationDescriptor);
  239. if (!NT_SUCCESS(status)) {
  240. __leave;
  241. }
  242. //
  243. // Get the pipe handles from the interface
  244. //
  245. for (i = 0; i < pDevExt->Interface->NumberOfPipes; i++) {
  246. if (pDevExt->Interface->Pipes[i].PipeType == USB_ENDPOINT_TYPE_INTERRUPT) {
  247. readerExt->InterruptHandle = pDevExt->Interface->Pipes[i].PipeHandle;
  248. readerExt->InterruptIndex = i;
  249. } else if (pDevExt->Interface->Pipes[i].PipeType == USB_ENDPOINT_TYPE_BULK) {
  250. if (pDevExt->Interface->Pipes[i].EndpointAddress & 0x80) { // Bulk-in pipe
  251. readerExt->BulkInHandle = pDevExt->Interface->Pipes[i].PipeHandle;
  252. readerExt->BulkInIndex = i;
  253. } else { // Bulk-out pipe
  254. readerExt->BulkOutHandle = pDevExt->Interface->Pipes[i].PipeHandle;
  255. readerExt->BulkOutIndex = i;
  256. }
  257. }
  258. }
  259. //
  260. // Get CCID Class Descriptor
  261. //
  262. comDesc = USBD_ParseDescriptors(ConfigurationDescriptor,
  263. ConfigurationDescriptor->wTotalLength,
  264. ConfigurationDescriptor,
  265. CCID_CLASS_DESCRIPTOR_TYPE);
  266. ASSERT(comDesc);
  267. readerExt->ClassDescriptor = *((CCID_CLASS_DESCRIPTOR *) comDesc);
  268. readerExt->ExchangeLevel = (WORD) (readerExt->ClassDescriptor.dwFeatures >> 16);
  269. }
  270. __finally
  271. {
  272. if( pUrb ) {
  273. ExFreePool( pUrb );
  274. pUrb = NULL;
  275. }
  276. if( ConfigurationDescriptor ) {
  277. ExFreePool( ConfigurationDescriptor );
  278. ConfigurationDescriptor = NULL;
  279. }
  280. if (!NT_SUCCESS(status) && pDevExt->DeviceDescriptor) {
  281. ExFreePool(pDevExt->DeviceDescriptor);
  282. pDevExt->DeviceDescriptor = NULL;
  283. }
  284. SmartcardDebug( DEBUG_TRACE, ("%s!UsbConfigureDevice Exit : 0x%x\n",DRIVER_NAME, status ));
  285. }
  286. return status;
  287. }
  288. NTSTATUS
  289. UsbSelectInterfaces(
  290. IN PDEVICE_OBJECT DeviceObject,
  291. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
  292. )
  293. /*++
  294. Routine Description:
  295. Initializes a USB reader with (possibly) multiple interfaces;
  296. Arguments:
  297. DeviceObject - pointer to the device object for this instance of the device.
  298. ConfigurationDescriptor - pointer to the USB configuration
  299. descriptor containing the interface and endpoint
  300. descriptors.
  301. Return Value:
  302. NT status code
  303. --*/
  304. {
  305. PDEVICE_EXTENSION pDevExt;
  306. NTSTATUS status;
  307. PURB pUrb = NULL;
  308. USHORT usSize;
  309. ULONG ulNumberOfInterfaces, i;
  310. UCHAR ucNumberOfPipes,
  311. ucAlternateSetting,
  312. ucMyInterfaceNumber;
  313. PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
  314. PUSBD_INTERFACE_INFORMATION InterfaceObject;
  315. USBD_INTERFACE_LIST_ENTRY interfaces[2];
  316. __try
  317. {
  318. SmartcardDebug( DEBUG_TRACE, ("%s!UsbSelectInterfaces Enter\n",DRIVER_NAME ));
  319. pDevExt = DeviceObject->DeviceExtension;
  320. ASSERT(pDevExt->Interface == NULL);
  321. //
  322. // USBD_ParseConfigurationDescriptorEx searches a given configuration
  323. // descriptor and returns a pointer to an interface that matches the
  324. // given search criteria.
  325. //
  326. InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
  327. ConfigurationDescriptor, //search from start of config descriptro
  328. -1, // interface number not a criteria;
  329. -1, // not interested in alternate setting here either
  330. 0x0b, // CCID Device Class
  331. -1, // interface subclass not a criteria
  332. -1); // interface protocol not a criteria
  333. ASSERT( InterfaceDescriptor != NULL );
  334. if (InterfaceDescriptor == NULL) {
  335. status = STATUS_UNSUCCESSFUL;
  336. __leave;
  337. }
  338. interfaces[0].InterfaceDescriptor = InterfaceDescriptor;
  339. interfaces[1].InterfaceDescriptor = NULL;
  340. pUrb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,
  341. interfaces);
  342. if (pUrb == NULL) {
  343. status = STATUS_INSUFFICIENT_RESOURCES;
  344. __leave;
  345. }
  346. ASSERT(pDevExt->LowerDeviceObject);
  347. status = USBCallSync(pDevExt->LowerDeviceObject,
  348. pUrb,
  349. 0,
  350. &pDevExt->RemoveLock);
  351. if(!NT_SUCCESS(status)) {
  352. __leave;
  353. }
  354. // save a copy of the interface information returned
  355. InterfaceObject = interfaces[0].Interface;
  356. ASSERT(pDevExt->Interface == NULL);
  357. pDevExt->Interface = ExAllocatePool(NonPagedPool,
  358. InterfaceObject->Length);
  359. if (pDevExt->Interface == NULL) {
  360. status = STATUS_INSUFFICIENT_RESOURCES;
  361. __leave;
  362. }
  363. RtlCopyMemory(pDevExt->Interface,
  364. InterfaceObject,
  365. InterfaceObject->Length);
  366. }
  367. __finally
  368. {
  369. if (pUrb) {
  370. ExFreePool(pUrb);
  371. pUrb = NULL;
  372. }
  373. if (!NT_SUCCESS(status)) {
  374. if (pDevExt->Interface) {
  375. ExFreePool(pDevExt->Interface);
  376. pDevExt->Interface = NULL;
  377. }
  378. }
  379. SmartcardDebug( DEBUG_TRACE, ("%s!UsbSelectInterfaces Exit : 0x%x\n",DRIVER_NAME, status ));
  380. }
  381. return status;
  382. }
  383. NTSTATUS
  384. GetStringDescriptor(
  385. PDEVICE_OBJECT DeviceObject,
  386. UCHAR StringIndex,
  387. PUCHAR StringBuffer,
  388. PUSHORT StringLength
  389. )
  390. /*++
  391. Routine Description:
  392. Retrieves an ASCII string descriptor from the USB Reader
  393. Arguments:
  394. DeviceObject - The device object
  395. StringIndex - The index of the string to be retrieved
  396. StringBuffer - Caller allocated buffer to hold the string
  397. StringLength - Length of the string
  398. Return Value:
  399. NT status value
  400. --*/
  401. {
  402. NTSTATUS status = STATUS_SUCCESS;
  403. USB_STRING_DESCRIPTOR
  404. USD,
  405. *pFullUSD = NULL;
  406. PURB pUrb;
  407. USHORT langID = 0x0409; // US English
  408. PDEVICE_EXTENSION pDevExt;
  409. UNICODE_STRING uString;
  410. ANSI_STRING aString;
  411. __try
  412. {
  413. SmartcardDebug( DEBUG_TRACE, ("%s!GetStringDescriptor Enter\n",DRIVER_NAME ));
  414. pDevExt = DeviceObject->DeviceExtension;
  415. pUrb = ExAllocatePool(NonPagedPool,
  416. sizeof( struct _URB_CONTROL_DESCRIPTOR_REQUEST ));
  417. if( pUrb == NULL) {
  418. status = STATUS_INSUFFICIENT_RESOURCES;
  419. __leave;
  420. }
  421. UsbBuildGetDescriptorRequest(pUrb, // points to the URB to be filled in
  422. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  423. USB_STRING_DESCRIPTOR_TYPE,
  424. StringIndex, // index of string descriptor
  425. langID, // language ID of string.
  426. &USD, // points to a USB_STRING_DESCRIPTOR.
  427. NULL,
  428. sizeof(USB_STRING_DESCRIPTOR),
  429. NULL);
  430. status = USBCallSync(pDevExt->LowerDeviceObject,
  431. pUrb,
  432. 0,
  433. &pDevExt->RemoveLock);
  434. if (!NT_SUCCESS(status)) {
  435. __leave;
  436. }
  437. pFullUSD = ExAllocatePool(NonPagedPool, USD.bLength);
  438. UsbBuildGetDescriptorRequest(pUrb, // points to the URB to be filled in
  439. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  440. USB_STRING_DESCRIPTOR_TYPE,
  441. StringIndex, // index of string descriptor
  442. langID, // language ID of string
  443. pFullUSD,
  444. NULL,
  445. USD.bLength,
  446. NULL);
  447. status = USBCallSync(pDevExt->LowerDeviceObject,
  448. pUrb,
  449. 0,
  450. &pDevExt->RemoveLock);
  451. if (!NT_SUCCESS(status)) {
  452. __leave;
  453. }
  454. uString.MaximumLength = uString.Length = pFullUSD->bLength-2;
  455. uString.Buffer = pFullUSD->bString;
  456. status = RtlUnicodeStringToAnsiString(&aString,
  457. &uString,
  458. TRUE);
  459. if (!NT_SUCCESS(status)) {
  460. __leave;
  461. }
  462. if (aString.Length > MAXIMUM_ATTR_STRING_LENGTH) {
  463. aString.Length = MAXIMUM_ATTR_STRING_LENGTH;
  464. aString.Buffer[aString.Length - 1] = 0;
  465. }
  466. RtlCopyMemory(StringBuffer, aString.Buffer, aString.Length);
  467. *StringLength = aString.Length;
  468. }
  469. __finally
  470. {
  471. SmartcardDebug( DEBUG_TRACE, ("%s!GetStringDescriptor Exit : 0x%x\n",DRIVER_NAME, status ));
  472. if (aString.Buffer) {
  473. RtlFreeAnsiString(&aString);
  474. }
  475. if (pUrb) {
  476. ExFreePool(pUrb);
  477. pUrb = NULL;
  478. }
  479. if (pFullUSD) {
  480. ExFreePool(pFullUSD);
  481. pFullUSD = NULL;
  482. }
  483. }
  484. return status;
  485. }