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.

1605 lines
52 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. Author:
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include <stdio.h>
  13. #include <stddef.h>
  14. #include <wdm.h>
  15. #include <usbscan.h>
  16. #include "usbd_api.h"
  17. #include "private.h"
  18. //#include "missdef.h"
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, USDeviceControl)
  21. #pragma alloc_text(PAGE, USReadWriteRegisters)
  22. #pragma alloc_text(PAGE, USCancelPipe)
  23. #pragma alloc_text(PAGE, USAbortResetPipe)
  24. #endif
  25. #ifdef _WIN64
  26. BOOLEAN
  27. IoIs32bitProcess(
  28. IN PIRP Irp
  29. );
  30. #endif // _WIN64
  31. NTSTATUS
  32. USDeviceControl(
  33. IN PDEVICE_OBJECT pDeviceObject,
  34. IN PIRP pIrp
  35. )
  36. /*++
  37. Routine Description:
  38. Arguments:
  39. pDeviceObject - Device object for a device.
  40. pIrp - DEVICE IOCTL irp
  41. Return Value:
  42. NT Status - STATUS_SUCCESS
  43. --*/
  44. {
  45. PIO_STACK_LOCATION pIrpStack;
  46. PIO_STACK_LOCATION pNextIrpStack;
  47. PFILE_OBJECT fileObject;
  48. PUSBSCAN_FILE_CONTEXT pFileContext;
  49. ULONG IoControlCode;
  50. PUSBSCAN_DEVICE_EXTENSION pde;
  51. NTSTATUS Status;
  52. PDRV_VERSION pVersion;
  53. PDEVICE_DESCRIPTOR pDesc;
  54. PUSBSCAN_GET_DESCRIPTOR pGetDesc;
  55. PUSBSCAN_PIPE_CONFIGURATION pPipeConfig;
  56. PVOID pBuffer;
  57. IO_BLOCK LocalIoBlock;
  58. IO_BLOCK_EX LocalIoBlockEx;
  59. PIO_BLOCK pIoBlock;
  60. PIO_BLOCK_EX pIoBlockEx;
  61. ULONG InLength;
  62. ULONG OutLength;
  63. BOOLEAN fRead = FALSE;
  64. BOOLEAN fAbort = TRUE;
  65. ULONG i;
  66. PURB pUrb;
  67. PAGED_CODE();
  68. DebugTrace(TRACE_PROC_ENTER,("USDeviceControl: Enter...\n"));
  69. //
  70. // Check arguments.
  71. //
  72. if( (NULL == pDeviceObject)
  73. || (NULL == pDeviceObject->DeviceExtension)
  74. || (NULL == pIrp) )
  75. {
  76. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid parameter passed.\n"));
  77. Status = STATUS_INVALID_PARAMETER;
  78. DebugTrace(TRACE_PROC_LEAVE,("USDeviceControl: Leaving.. Status = %x.\n", Status));
  79. return Status;
  80. }
  81. //
  82. // Indicates I/O processing increase.
  83. //
  84. USIncrementIoCount( pDeviceObject );
  85. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  86. if (FALSE == pde -> AcceptingRequests) {
  87. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! IOCTL issued after device stopped/removed!\n"));
  88. Status = STATUS_DELETE_PENDING;
  89. pIrp -> IoStatus.Status = Status;
  90. pIrp -> IoStatus.Information = 0;
  91. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  92. goto USDeviceControl_return;
  93. }
  94. //
  95. // Check device power state.
  96. //
  97. if (PowerDeviceD0 != pde -> CurrentDevicePowerState) {
  98. DebugTrace(TRACE_WARNING,("USDeviceControl: WARNING!! Device is suspended.\n"));
  99. Status = STATUS_DELETE_PENDING;
  100. pIrp -> IoStatus.Status = Status;
  101. pIrp -> IoStatus.Information = 0;
  102. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  103. goto USDeviceControl_return;
  104. }
  105. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  106. pNextIrpStack = IoGetNextIrpStackLocation( pIrp );
  107. IoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  108. InLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  109. OutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  110. pBuffer = pIrp -> AssociatedIrp.SystemBuffer;
  111. fileObject = pIrpStack->FileObject;
  112. pFileContext = fileObject->FsContext;
  113. DebugTrace(TRACE_STATUS,("USDeviceControl: Control code 0x%x = ", IoControlCode));
  114. switch (IoControlCode) {
  115. case IOCTL_GET_VERSION:
  116. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_VERSION\n"));
  117. if (OutLength < sizeof(DRV_VERSION) ) {
  118. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Buffer(0x%x) too small(<0x%x)\n", OutLength, sizeof(DRV_VERSION)));
  119. DEBUG_BREAKPOINT();
  120. Status = STATUS_INVALID_PARAMETER;
  121. break;
  122. }
  123. pVersion = (PDRV_VERSION)pBuffer;
  124. pVersion->major = 1;
  125. pVersion->minor = 0;
  126. pVersion->internal = 0;
  127. pIrp -> IoStatus.Information = sizeof(DRV_VERSION);
  128. Status = STATUS_SUCCESS;
  129. break;
  130. case IOCTL_CANCEL_IO:
  131. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_CANCEL_IO\n"));
  132. fAbort = TRUE;
  133. //
  134. // Falling through to the next case, this is intentional. We want to reset pipe when
  135. // cancel requested
  136. //
  137. case IOCTL_RESET_PIPE:
  138. if(IOCTL_RESET_PIPE == IoControlCode){
  139. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_RESET_PIPE\n"));
  140. fAbort = FALSE;
  141. }
  142. //
  143. // Validate buffer size
  144. //
  145. if (InLength < sizeof(PIPE_TYPE) ) {
  146. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Pipe type buffer (0x%x bytes) too small\n" ,InLength));
  147. Status = STATUS_INVALID_PARAMETER;
  148. break;
  149. }
  150. Status = USCancelPipe(pDeviceObject,
  151. pIrp,
  152. *(PIPE_TYPE*)pBuffer,
  153. fAbort);
  154. break;
  155. case IOCTL_WAIT_ON_DEVICE_EVENT:
  156. {
  157. ULONG Index;
  158. ULONG Timeout;
  159. PULONG pTimeout;
  160. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_WAIT_ON_DEVICE_EVENT\n"));
  161. Index = USGetPipeIndexToUse(pDeviceObject,
  162. pIrp,
  163. pde -> IndexInterrupt);
  164. if (OutLength < pde -> PipeInfo[Index].MaximumPacketSize) {
  165. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! User buffer(0x%x) too small(<)\n"
  166. , OutLength
  167. , pde -> PipeInfo[Index].MaximumPacketSize));
  168. Status = STATUS_INVALID_PARAMETER;
  169. break;
  170. }
  171. //
  172. // Copy timeout value from file context.
  173. //
  174. Timeout = pFileContext->TimeoutEvent;
  175. //
  176. // If timeout value is 0, then never timeout.
  177. //
  178. if(0 == Timeout){
  179. pTimeout = NULL;
  180. } else {
  181. DebugTrace(TRACE_STATUS,("USDeviceControl: Timeout is set to 0x%x sec.\n", Timeout));
  182. pTimeout = &Timeout;
  183. }
  184. Status = USTransfer(pDeviceObject,
  185. pIrp,
  186. Index,
  187. pIrp -> AssociatedIrp.SystemBuffer,
  188. NULL,
  189. pde -> PipeInfo[Index].MaximumPacketSize,
  190. pTimeout);
  191. //
  192. // IRP should be completed in USTransfer or its completion routine.
  193. //
  194. goto USDeviceControl_return;
  195. }
  196. case IOCTL_READ_REGISTERS:
  197. fRead = TRUE;
  198. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_READ_REGISTERS\n"));
  199. case IOCTL_WRITE_REGISTERS:{
  200. if (IOCTL_WRITE_REGISTERS == IoControlCode) {
  201. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_WRITE_REGISTERS\n"));
  202. fRead = FALSE;
  203. }
  204. #ifdef _WIN64
  205. if(IoIs32bitProcess(pIrp)){
  206. PIO_BLOCK_32 pIoBlock32;
  207. if (InLength < sizeof(IO_BLOCK_32) ) {
  208. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input 32bit buffer size(0x%x<0x%x)\n"
  209. , InLength,
  210. sizeof(IO_BLOCK_32)));
  211. Status = STATUS_INVALID_PARAMETER;
  212. break;
  213. }
  214. //
  215. // Copy all parameters from 32bit structure.
  216. //
  217. pIoBlock32 = (PIO_BLOCK_32)pBuffer;
  218. pIoBlock = &LocalIoBlock;
  219. pIoBlock -> uOffset = pIoBlock32 -> uOffset;
  220. pIoBlock -> uLength = pIoBlock32 -> uLength;
  221. pIoBlock -> pbyData = pIoBlock32 -> pbyData;
  222. pIoBlock -> uIndex = pIoBlock32 -> uIndex;
  223. } else { // if(IoIs32bitProcess(pIrp))
  224. #endif // _WIN64
  225. if (InLength < sizeof(IO_BLOCK) ) {
  226. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input buffer size(0x%x<0x%x)\n"
  227. , InLength,
  228. sizeof(IO_BLOCK)));
  229. Status = STATUS_INVALID_PARAMETER;
  230. break;
  231. }
  232. pIoBlock = (PIO_BLOCK)pBuffer;
  233. #ifdef _WIN64
  234. } // if(IoIs32bitProcess(pIrp))
  235. #endif // _WIN64
  236. if(TRUE == fRead){
  237. //
  238. // Check the size of Output buffer.
  239. //
  240. if (OutLength < pIoBlock -> uLength) {
  241. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Out buffer(0x%x) too small(<0x%x)\n"
  242. , OutLength
  243. , pIoBlock -> uLength));
  244. Status = STATUS_INVALID_PARAMETER;
  245. break;
  246. } // if (OutLength < pIoBlock -> uLength)
  247. } // if(TRUE == fRead)
  248. pIrp -> IoStatus.Information = pIoBlock -> uLength;
  249. //
  250. // Caller gives us a pointer, embedded into IOCTL buffer. If call is made from
  251. // user-mode , we need to validate that given pointer is readable.
  252. //
  253. if (pIrp->RequestorMode != KernelMode) {
  254. try {
  255. ProbeForRead(pIoBlock->pbyData,
  256. pIoBlock -> uLength,
  257. sizeof(UCHAR));
  258. } except(EXCEPTION_EXECUTE_HANDLER) {
  259. DebugTrace(TRACE_ERROR,("USDeviceControl: Read/Write registers buffer pointer is invalid\n"));
  260. DEBUG_BREAKPOINT();
  261. Status = GetExceptionCode();
  262. pIrp -> IoStatus.Information = 0;
  263. break;
  264. } // except
  265. } // !kernelmode
  266. //
  267. // Now go to worker function
  268. //
  269. Status = USReadWriteRegisters(pDeviceObject,
  270. pIoBlock,
  271. fRead,
  272. InLength);
  273. if (STATUS_SUCCESS != Status) {
  274. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! USReadWriteRegisters failed\n"));
  275. DEBUG_BREAKPOINT();
  276. pIrp -> IoStatus.Information = 0;
  277. }
  278. break;
  279. } // case IOCTL_WRITE_REGISTERS:
  280. case IOCTL_GET_CHANNEL_ALIGN_RQST:
  281. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_CHANNEL_ALIGN_REQUEST\n"));
  282. if (OutLength < sizeof(CHANNEL_INFO) ) {
  283. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Buffer(0x%x) too small(<0x%x)\n"
  284. , OutLength
  285. ,sizeof(CHANNEL_INFO)));
  286. Status = STATUS_INVALID_PARAMETER;
  287. break;
  288. }
  289. pIoBlock = (PIO_BLOCK)pBuffer;
  290. RtlZeroMemory((PCHANNEL_INFO)pIoBlock, sizeof(CHANNEL_INFO));
  291. for (i = 0; i < pde -> NumberOfPipes; i++) {
  292. //
  293. // Have to check which pipe to use
  294. //
  295. ULONG Index;
  296. Index = USGetPipeIndexToUse(pDeviceObject,
  297. pIrp,
  298. i);
  299. switch (pde -> PipeInfo[Index].PipeType) {
  300. case USB_ENDPOINT_TYPE_INTERRUPT:
  301. ((PCHANNEL_INFO)pIoBlock)->EventChannelSize = pde -> PipeInfo[Index].MaximumPacketSize;
  302. break;
  303. case USB_ENDPOINT_TYPE_BULK:
  304. if (pde -> pEndpointDescriptor[Index].bEndpointAddress & BULKIN_FLAG) {
  305. ((PCHANNEL_INFO)pIoBlock) -> uReadDataAlignment = pde -> PipeInfo[Index].MaximumPacketSize;
  306. } else {
  307. ((PCHANNEL_INFO)pIoBlock) -> uWriteDataAlignment = pde -> PipeInfo[Index].MaximumPacketSize;
  308. }
  309. break;
  310. }
  311. }
  312. pIrp -> IoStatus.Information = sizeof(CHANNEL_INFO);
  313. Status = STATUS_SUCCESS;
  314. break;
  315. case IOCTL_GET_DEVICE_DESCRIPTOR:
  316. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_DEVICE_DESCRIPTOR\n"));
  317. if (OutLength < sizeof(DEVICE_DESCRIPTOR)) {
  318. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Out buffer(0x%x) is too small(<0x%x)\n"
  319. , OutLength
  320. , sizeof(DEVICE_DESCRIPTOR)));
  321. Status = STATUS_INVALID_PARAMETER_6;
  322. break;
  323. }
  324. pDesc = (PDEVICE_DESCRIPTOR)pBuffer;
  325. pDesc -> usVendorId = pde -> pDeviceDescriptor -> idVendor;
  326. pDesc -> usProductId = pde -> pDeviceDescriptor -> idProduct;
  327. pDesc -> usBcdDevice = pde -> pDeviceDescriptor -> bcdDevice;
  328. DebugTrace(TRACE_STATUS,("USDeviceControl: Vendor ID:%d\n", pDesc -> usVendorId));
  329. DebugTrace(TRACE_STATUS,("USDeviceControl: Product ID:%d\n", pDesc -> usProductId));
  330. DebugTrace(TRACE_STATUS,("USDeviceControl: BcdDevice:%d\n", pDesc -> usBcdDevice));
  331. pIrp -> IoStatus.Information = sizeof(DEVICE_DESCRIPTOR);
  332. Status = STATUS_SUCCESS;
  333. break;
  334. case IOCTL_GET_USB_DESCRIPTOR:
  335. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_USB_DESCRIPTOR\n"));
  336. if (OutLength < sizeof(USBSCAN_GET_DESCRIPTOR)) {
  337. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Out buffer(0x%x) is too small(<0x%x)\n"
  338. , OutLength
  339. , sizeof(USBSCAN_GET_DESCRIPTOR)));
  340. Status = STATUS_INVALID_PARAMETER_6;
  341. break;
  342. }
  343. pGetDesc = (PUSBSCAN_GET_DESCRIPTOR)pBuffer;
  344. pUrb = USAllocatePool(NonPagedPool,
  345. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  346. if (NULL == pUrb) {
  347. DebugTrace(TRACE_CRITICAL,("USDeviceControl: ERROR!! Can't allocate control descriptor URB.\n"));
  348. DEBUG_BREAKPOINT();
  349. Status = STATUS_INSUFFICIENT_RESOURCES;
  350. break;
  351. }
  352. #ifdef DEBUG
  353. switch(pGetDesc -> DescriptorType){
  354. case USB_DEVICE_DESCRIPTOR_TYPE:
  355. DebugTrace(TRACE_STATUS,("USDeviceControl: USB_DEVICE_DESCRIPTOR_TYPE\n"));
  356. break;
  357. case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  358. DebugTrace(TRACE_STATUS,("USDeviceControl: USB_CONFIGURATION_DESCRIPTOR_TYPE\n"));
  359. break;
  360. case USB_STRING_DESCRIPTOR_TYPE:
  361. DebugTrace(TRACE_STATUS,("USDeviceControl: USB_STRING_DESCRIPTOR_TYPE\n"));
  362. break;
  363. default:
  364. DebugTrace(TRACE_WARNING,("USDeviceControl: WARNING!! 0x%x = Undefined.\n", pGetDesc -> DescriptorType));
  365. Status = STATUS_INVALID_PARAMETER_3;
  366. USFreePool(pUrb);
  367. pUrb = NULL;
  368. pIrp -> IoStatus.Information = 0;
  369. goto USDeviceControl_return;
  370. }
  371. DebugTrace(TRACE_STATUS, ("USDeviceControl: Index :%d\n",pGetDesc -> Index));
  372. DebugTrace(TRACE_STATUS, ("USDeviceControl: LanguageID :%d\n", pGetDesc -> LanguageId));
  373. #endif //DEBUG
  374. UsbBuildGetDescriptorRequest(pUrb,
  375. (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  376. pGetDesc -> DescriptorType,
  377. pGetDesc -> Index,
  378. pGetDesc -> LanguageId,
  379. pBuffer,
  380. NULL,
  381. OutLength,
  382. NULL);
  383. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  384. #ifdef DEBUG
  385. if ( (STATUS_SUCCESS == Status)
  386. // && (USB_DEVICE_DESCRIPTOR_TYPE == pGetDesc -> DescriptorType)
  387. )
  388. {
  389. PUSB_DEVICE_DESCRIPTOR pDeviceDescriptor;
  390. pDeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)pBuffer;
  391. DebugTrace(TRACE_STATUS,("USDeviceControl: Device Descriptor = %x, len %x\n",
  392. pDeviceDescriptor,
  393. pUrb->UrbControlDescriptorRequest.TransferBufferLength));
  394. DebugTrace(TRACE_STATUS,("USDeviceControl: USBSCAN Device Descriptor:\n"));
  395. DebugTrace(TRACE_STATUS,("USDeviceControl: -------------------------\n"));
  396. DebugTrace(TRACE_STATUS,("USDeviceControl: bLength %d\n", pDeviceDescriptor->bLength));
  397. DebugTrace(TRACE_STATUS,("USDeviceControl: bDescriptorType 0x%x\n", pDeviceDescriptor->bDescriptorType));
  398. DebugTrace(TRACE_STATUS,("USDeviceControl: bcdUSB 0x%x\n", pDeviceDescriptor->bcdUSB));
  399. DebugTrace(TRACE_STATUS,("USDeviceControl: bDeviceClass 0x%x\n", pDeviceDescriptor->bDeviceClass));
  400. DebugTrace(TRACE_STATUS,("USDeviceControl: bDeviceSubClass 0x%x\n", pDeviceDescriptor->bDeviceSubClass));
  401. DebugTrace(TRACE_STATUS,("USDeviceControl: bDeviceProtocol 0x%x\n", pDeviceDescriptor->bDeviceProtocol));
  402. DebugTrace(TRACE_STATUS,("USDeviceControl: bMaxPacketSize0 0x%x\n", pDeviceDescriptor->bMaxPacketSize0));
  403. DebugTrace(TRACE_STATUS,("USDeviceControl: idVendor 0x%x\n", pDeviceDescriptor->idVendor));
  404. DebugTrace(TRACE_STATUS,("USDeviceControl: idProduct 0x%x\n", pDeviceDescriptor->idProduct));
  405. DebugTrace(TRACE_STATUS,("USDeviceControl: bcdDevice 0x%x\n", pDeviceDescriptor->bcdDevice));
  406. DebugTrace(TRACE_STATUS,("USDeviceControl: iManufacturer 0x%x\n", pDeviceDescriptor->iManufacturer));
  407. DebugTrace(TRACE_STATUS,("USDeviceControl: iProduct 0x%x\n", pDeviceDescriptor->iProduct));
  408. DebugTrace(TRACE_STATUS,("USDeviceControl: iSerialNumber 0x%x\n", pDeviceDescriptor->iSerialNumber));
  409. DebugTrace(TRACE_STATUS,("USDeviceControl: bNumConfigurations 0x%x\n", pDeviceDescriptor->bNumConfigurations));
  410. } else {
  411. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR! Status = %d\n", Status));
  412. }
  413. #endif //DEBUG
  414. USFreePool(pUrb);
  415. pUrb = NULL;
  416. pIrp -> IoStatus.Information = ((PUSB_DEVICE_DESCRIPTOR)pBuffer)->bLength;
  417. break;
  418. case IOCTL_SEND_USB_REQUEST:
  419. {
  420. //
  421. // Generic pass-through mechanism for USB vendor requests.
  422. //
  423. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_SEND_USB_REQUEST\n"));
  424. //
  425. // Validate length parameters.
  426. //
  427. #ifdef _WIN64
  428. if(IoIs32bitProcess(pIrp)){
  429. PIO_BLOCK_EX_32 pIoBlockEx32;
  430. if (InLength < sizeof(IO_BLOCK_EX_32) ) {
  431. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input 32bit buffer size(0x%x<0x%x)\n"
  432. , InLength,
  433. sizeof(IO_BLOCK_EX_32)));
  434. Status = STATUS_INVALID_PARAMETER;
  435. break;
  436. }
  437. //
  438. // Copy all parameters from 32bit structure.
  439. //
  440. pIoBlockEx32 = (PIO_BLOCK_EX_32)pBuffer;
  441. pIoBlockEx = &LocalIoBlockEx;
  442. pIoBlockEx -> uOffset = pIoBlockEx32 -> uOffset;
  443. pIoBlockEx -> uLength = pIoBlockEx32 -> uLength;
  444. pIoBlockEx -> pbyData = pIoBlockEx32 -> pbyData;
  445. pIoBlockEx -> uIndex = pIoBlockEx32 -> uIndex;
  446. pIoBlockEx -> bRequest = pIoBlockEx32 -> bRequest;
  447. pIoBlockEx -> bmRequestType = pIoBlockEx32 -> bmRequestType;
  448. pIoBlockEx -> fTransferDirectionIn = pIoBlockEx32 -> fTransferDirectionIn;
  449. } else { // if(IoIs32bitProcess(pIrp))
  450. #endif // _WIN64
  451. if (InLength < sizeof(IO_BLOCK_EX) ) {
  452. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! I/O buffer(0x%x) too small(<0x%x)\n"
  453. , InLength
  454. , sizeof(IO_BLOCK_EX)));
  455. Status = STATUS_INVALID_PARAMETER;
  456. break;
  457. }
  458. pIoBlockEx = (PIO_BLOCK_EX)pBuffer;
  459. #ifdef _WIN64
  460. } // if(IoIs32bitProcess(pIrp))
  461. #endif // _WIN64
  462. if (pIoBlockEx->fTransferDirectionIn) {
  463. //
  464. // Check output buffer length is valid.
  465. //
  466. if (OutLength < pIoBlockEx -> uLength) {
  467. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! OutLength too small\n"));
  468. DEBUG_BREAKPOINT();
  469. Status = STATUS_INVALID_PARAMETER;
  470. pIrp -> IoStatus.Information = 0;
  471. break;
  472. }
  473. pIrp -> IoStatus.Information = pIoBlockEx -> uLength;
  474. } else {
  475. //
  476. // No output to the caller.
  477. //
  478. pIrp -> IoStatus.Information = 0;
  479. }
  480. //
  481. // Validate user buffer.
  482. //
  483. if (pIrp->RequestorMode != KernelMode) {
  484. try {
  485. ProbeForRead(pIoBlockEx->pbyData,
  486. pIoBlockEx->uLength,
  487. sizeof(UCHAR));
  488. } except(EXCEPTION_EXECUTE_HANDLER) {
  489. DebugTrace(TRACE_ERROR,("USDeviceControl: User buffer pointer is invalid\n"));
  490. Status = GetExceptionCode();
  491. pIrp -> IoStatus.Information = 0;
  492. break;
  493. } // except
  494. } // !kernelmode
  495. //
  496. // Now go to worker function
  497. //
  498. Status = USPassThruUSBRequest(pDeviceObject,
  499. (PIO_BLOCK_EX)pBuffer,
  500. InLength,
  501. OutLength
  502. );
  503. if (STATUS_SUCCESS != Status) {
  504. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! USPassThruUSBRequest failed\n"));
  505. DEBUG_BREAKPOINT();
  506. pIrp -> IoStatus.Information = 0;
  507. }
  508. break;
  509. } // case IOCTL_SEND_USB_REQUEST:
  510. case IOCTL_SEND_USB_REQUEST_PTP:
  511. {
  512. //
  513. // Generic pass-through mechanism for USB vendor requests.
  514. //
  515. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_SEND_USB_REQUEST_PTP\n"));
  516. //
  517. // Validate length parameters.
  518. //
  519. #ifdef _WIN64
  520. if(IoIs32bitProcess(pIrp)){
  521. PIO_BLOCK_EX_32 pIoBlockEx32;
  522. if (InLength < sizeof(IO_BLOCK_EX_32) ) {
  523. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input 32bit buffer size(0x%x<0x%x)\n"
  524. , InLength,
  525. sizeof(IO_BLOCK_EX_32)));
  526. Status = STATUS_INVALID_PARAMETER;
  527. break;
  528. }
  529. //
  530. // Copy all parameters from 32bit structure.
  531. //
  532. pIoBlockEx32 = (PIO_BLOCK_EX_32)pBuffer;
  533. pIoBlockEx = &LocalIoBlockEx;
  534. pIoBlockEx -> uOffset = pIoBlockEx32 -> uOffset;
  535. pIoBlockEx -> uLength = pIoBlockEx32 -> uLength;
  536. pIoBlockEx -> pbyData = pIoBlockEx32 -> pbyData;
  537. pIoBlockEx -> uIndex = pIoBlockEx32 -> uIndex;
  538. pIoBlockEx -> bRequest = pIoBlockEx32 -> bRequest;
  539. pIoBlockEx -> bmRequestType = pIoBlockEx32 -> bmRequestType;
  540. pIoBlockEx -> fTransferDirectionIn = pIoBlockEx32 -> fTransferDirectionIn;
  541. } else { // if(IoIs32bitProcess(pIrp))
  542. #endif // _WIN64
  543. if (InLength < sizeof(IO_BLOCK_EX) ) {
  544. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! I/O buffer(0x%x) too small(<0x%x)\n"
  545. , InLength
  546. , sizeof(IO_BLOCK_EX)));
  547. Status = STATUS_INVALID_PARAMETER;
  548. break;
  549. }
  550. pIoBlockEx = (PIO_BLOCK_EX)pBuffer;
  551. #ifdef _WIN64
  552. } // if(IoIs32bitProcess(pIrp))
  553. #endif // _WIN64
  554. if (pIoBlockEx->fTransferDirectionIn) {
  555. //
  556. // Check output buffer length is valid.
  557. //
  558. if (OutLength < pIoBlockEx -> uLength) {
  559. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! OutLength too small\n"));
  560. DEBUG_BREAKPOINT();
  561. Status = STATUS_INVALID_PARAMETER;
  562. pIrp -> IoStatus.Information = 0;
  563. break;
  564. }
  565. pIrp -> IoStatus.Information = pIoBlockEx -> uLength;
  566. } else {
  567. //
  568. // No output to the caller.
  569. //
  570. pIrp -> IoStatus.Information = 0;
  571. }
  572. //
  573. // Validate user buffer.
  574. //
  575. if (pIrp->RequestorMode != KernelMode) {
  576. try {
  577. ProbeForRead(pIoBlockEx->pbyData,
  578. pIoBlockEx->uLength,
  579. sizeof(UCHAR));
  580. } except(EXCEPTION_EXECUTE_HANDLER) {
  581. DebugTrace(TRACE_ERROR,("USDeviceControl: User buffer pointer is invalid\n"));
  582. Status = GetExceptionCode();
  583. pIrp -> IoStatus.Information = 0;
  584. break;
  585. } // except
  586. } // !kernelmode
  587. //
  588. // Now go to worker function
  589. //
  590. Status = USPassThruUSBRequestPTP(pDeviceObject,
  591. (PIO_BLOCK_EX)pBuffer,
  592. InLength,
  593. OutLength);
  594. if (STATUS_SUCCESS != Status) {
  595. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! USPassThruUSBRequestPTP failed\n"));
  596. DEBUG_BREAKPOINT();
  597. pIrp -> IoStatus.Information = 0;
  598. }
  599. break;
  600. } // case IOCTL_SEND_USB_REQUEST_PTP:
  601. case IOCTL_GET_PIPE_CONFIGURATION:
  602. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_PIPE_CONFIGURATION\n"));
  603. //
  604. // Check output buffer length
  605. //
  606. if (OutLength < sizeof(USBSCAN_PIPE_CONFIGURATION)) {
  607. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! GetPipeConfig buffer(0x%x) too small(<0x%x)\n"
  608. , OutLength
  609. , sizeof(USBSCAN_PIPE_CONFIGURATION)));
  610. Status = STATUS_INVALID_PARAMETER_6;
  611. break;
  612. }
  613. //
  614. // Copy Pipe configuration to user buffer.
  615. //
  616. pPipeConfig = (PUSBSCAN_PIPE_CONFIGURATION)pBuffer;
  617. RtlZeroMemory(pPipeConfig, sizeof(USBSCAN_PIPE_CONFIGURATION));
  618. pPipeConfig->NumberOfPipes = pde->NumberOfPipes;
  619. for(i=0; i < pPipeConfig->NumberOfPipes; i++){
  620. pPipeConfig->PipeInfo[i].MaximumPacketSize = pde->PipeInfo[i].MaximumPacketSize;
  621. pPipeConfig->PipeInfo[i].EndpointAddress = pde->PipeInfo[i].EndpointAddress;
  622. pPipeConfig->PipeInfo[i].Interval = pde->PipeInfo[i].Interval;
  623. pPipeConfig->PipeInfo[i].PipeType = pde->PipeInfo[i].PipeType;
  624. }
  625. pIrp -> IoStatus.Information = sizeof(USBSCAN_PIPE_CONFIGURATION);
  626. Status = STATUS_SUCCESS;
  627. break;
  628. case IOCTL_SET_TIMEOUT:
  629. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_SET_TIMEOUT\n"));
  630. //
  631. // Make sure input buffer size is big enough.
  632. //
  633. if(sizeof(USBSCAN_TIMEOUT) > InLength){
  634. //
  635. // Incorrect Input buffer size.
  636. //
  637. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input buffer size\n"));
  638. Status = STATUS_INVALID_PARAMETER;
  639. break;
  640. }
  641. //
  642. // Copy timeout value.
  643. //
  644. pFileContext -> TimeoutRead = ((PUSBSCAN_TIMEOUT)pBuffer) -> TimeoutRead;
  645. pFileContext -> TimeoutWrite = ((PUSBSCAN_TIMEOUT)pBuffer) -> TimeoutWrite;
  646. pFileContext -> TimeoutEvent = ((PUSBSCAN_TIMEOUT)pBuffer) -> TimeoutEvent;
  647. pIrp -> IoStatus.Information = 0;
  648. Status = STATUS_SUCCESS;
  649. break;
  650. default:
  651. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Unsupported IOCTL\n"));
  652. Status = STATUS_NOT_SUPPORTED;
  653. break;
  654. }
  655. pIrp -> IoStatus.Status = Status;
  656. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  657. USDeviceControl_return:
  658. USDecrementIoCount(pDeviceObject);
  659. DebugTrace(TRACE_PROC_LEAVE,("USDeviceControl: Leaving.. Status = 0x%x\n", Status));
  660. return Status;
  661. } // end USDeviceControl()
  662. NTSTATUS
  663. USReadWriteRegisters(
  664. IN PDEVICE_OBJECT pDeviceObject,
  665. IN PIO_BLOCK pIoBlock,
  666. IN BOOLEAN fRead,
  667. IN ULONG IoBlockSize
  668. )
  669. /*++
  670. Routine Description:
  671. Arguments:
  672. Return Value:
  673. --*/
  674. {
  675. NTSTATUS Status;
  676. PUSBSCAN_DEVICE_EXTENSION pde;
  677. PURB pUrb;
  678. ULONG siz;
  679. UCHAR Request;
  680. PVOID pBuffer = NULL;
  681. //USHORT uIndex;
  682. unsigned uIndex;
  683. PAGED_CODE();
  684. DebugTrace(TRACE_PROC_ENTER,("USReadWriteRegisters: Enter..\n"));
  685. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  686. //
  687. // Allocate URB
  688. //
  689. siz = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  690. pUrb = USAllocatePool(NonPagedPool, siz);
  691. if (NULL == pUrb) {
  692. DebugTrace(TRACE_CRITICAL,("USReadWriteRegisters: ERROR!! cannot allocated URB\n"));
  693. DEBUG_BREAKPOINT();
  694. Status = STATUS_INSUFFICIENT_RESOURCES;
  695. goto USReadWriteRegisters_return;
  696. }
  697. RtlZeroMemory(pUrb, siz);
  698. //
  699. // Setup URB
  700. //
  701. Request = REGISTER_AREA;
  702. if (pIoBlock -> uLength > 1) {
  703. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: ULength > 1, turning on automatic increment\n"));
  704. Request |= OPCODE_SEQ_TRANSFER; // automatic address increment after the read
  705. } else {
  706. Request |= OPCODE_SINGLE_ADDR_TRANSFER; // no address increment after the read
  707. }
  708. //
  709. // Reading registers will read into pIoBlock itself.
  710. //
  711. pBuffer = pIoBlock;
  712. //
  713. // If we are writing registers, then we need to make a copy of the
  714. // register block into a non-paged block of memory before handing it off
  715. // to usbd.
  716. //
  717. if (!fRead) {
  718. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: Write request, allocating non-paged reg buffer, len = %d\n",pIoBlock->uLength));
  719. pBuffer = USAllocatePool(NonPagedPool, pIoBlock->uLength);
  720. if (NULL == pBuffer) {
  721. DebugTrace(TRACE_CRITICAL,("USReadWriteRegisters: ERROR!! cannot allocate write reg buffer\n"));
  722. DEBUG_BREAKPOINT();
  723. USFreePool(pUrb);
  724. pUrb = NULL;
  725. Status = STATUS_INSUFFICIENT_RESOURCES;
  726. goto USReadWriteRegisters_return;
  727. }
  728. //
  729. // Caller gives us a pointer, embedded into IOCTL buffer. We need to
  730. // validate that given pointer is readable.
  731. //
  732. try{
  733. RtlCopyMemory(pBuffer,
  734. pIoBlock->pbyData,
  735. pIoBlock->uLength);
  736. } except(EXCEPTION_EXECUTE_HANDLER) {
  737. //
  738. // Caller buffer is not valid, or worse..
  739. //
  740. DebugTrace(TRACE_ERROR,("USReadWriteRegisters: ERROR!! Copying caller buffer failed.\n"));
  741. DEBUG_BREAKPOINT();
  742. Status = GetExceptionCode();
  743. //
  744. // Clear allocated pool
  745. //
  746. USFreePool(pUrb);
  747. USFreePool(pBuffer);
  748. pUrb = NULL;
  749. pBuffer = NULL;
  750. goto USReadWriteRegisters_return;
  751. }
  752. }
  753. //
  754. // If the IoBlock is new style (Intel has added a uIndex field to the end of it),
  755. // then make sure we pass the corrected uIndex value to usbd.
  756. //
  757. uIndex = 0;
  758. if (IoBlockSize == sizeof(IO_BLOCK)) {
  759. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: New (intel) style IoBlock -- setting uIndex to pIoBlock -> uIndex\n"));
  760. uIndex = pIoBlock -> uIndex;
  761. }
  762. UsbBuildVendorClassSpecificCommand(pUrb,
  763. fRead ? USBD_TRANSFER_DIRECTION_IN : 0,
  764. pIoBlock->uLength,
  765. pBuffer,
  766. NULL,
  767. fRead ? 0xc0 : 0x40,
  768. Request,
  769. (SHORT)pIoBlock->uOffset,
  770. (USHORT)uIndex);
  771. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  772. if (!fRead) {
  773. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: freeing temp reg buffer\n"));
  774. USFreePool(pBuffer);
  775. pBuffer = NULL;
  776. }
  777. USFreePool(pUrb);
  778. pUrb = NULL;
  779. USReadWriteRegisters_return:
  780. if(!NT_SUCCESS(Status)){
  781. DebugTrace(TRACE_ERROR,("USReadWriteRegisters: ERROR!! Still had unfreed pointer. Free it...\n"));
  782. if(pUrb){
  783. USFreePool(pUrb);
  784. }
  785. if( (pBuffer)
  786. && (!fRead ) )
  787. {
  788. USFreePool(pBuffer);
  789. }
  790. }
  791. DebugTrace(TRACE_PROC_LEAVE,("USReadWriteRegisters: Leaving.. Status = 0x%x\n", Status));
  792. return Status;
  793. }
  794. NTSTATUS
  795. USCancelPipe(
  796. IN PDEVICE_OBJECT pDeviceObject,
  797. IN PIRP pIrp,
  798. IN PIPE_TYPE PipeType,
  799. IN BOOLEAN fAbort // TRUE = Abort, FALSE = Reset
  800. )
  801. /*++
  802. Routine Description:
  803. Cansel URB or reset pipe. If PipeType is PIPE_ALL, it applies to every pipes a device has.
  804. If not, it applies to only one default pipe even if a device supports multipul same type of pipes.
  805. Arguments:
  806. pDeviceObject - Pointer to Device Object
  807. pIrp - Can be NULL if PipeType is ALL_PIPE
  808. PipeType - Specifies type of pipe
  809. fAbort - Specifies type of operation
  810. Return Value:
  811. Returns status
  812. --*/
  813. {
  814. NTSTATUS Status, temp;
  815. PUSBSCAN_DEVICE_EXTENSION pde;
  816. PAGED_CODE();
  817. // DebugTrace(TRACE_PROC_ENTER,("USCancelPipe: Enter.. - "));
  818. Status = STATUS_SUCCESS;
  819. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  820. switch (PipeType) {
  821. case EVENT_PIPE:
  822. DebugTrace(TRACE_STATUS,("USCancelPipe: EVENT_PIPE\n"));
  823. if(NULL == pIrp){
  824. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! pIrp not valid\n"));
  825. break;
  826. }
  827. if (-1 == pde -> IndexInterrupt) {
  828. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! Interrupt pipe not valid\n"));
  829. DEBUG_BREAKPOINT();
  830. Status = STATUS_NOT_SUPPORTED;
  831. break;
  832. }
  833. Status = USAbortResetPipe(pDeviceObject,
  834. USGetPipeIndexToUse(pDeviceObject, pIrp, pde -> IndexInterrupt),
  835. fAbort);
  836. DebugTrace(TRACE_STATUS,("Event Pipe aborted/reset, Status = 0x%x\n",Status));
  837. break;
  838. case READ_DATA_PIPE:
  839. DebugTrace(TRACE_STATUS,("USCancelPipe: READ_DATA_PIPE\n"));
  840. if(NULL == pIrp){
  841. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! pIrp not valid\n"));
  842. break;
  843. }
  844. if (-1 == pde -> IndexBulkIn) {
  845. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! bulk-in pipe not valid\n"));
  846. DEBUG_BREAKPOINT();
  847. Status = STATUS_NOT_SUPPORTED;
  848. break;
  849. }
  850. Status = USAbortResetPipe(pDeviceObject,
  851. USGetPipeIndexToUse(pDeviceObject, pIrp, pde -> IndexBulkIn),
  852. fAbort);
  853. DebugTrace(TRACE_STATUS,("USCancelPipe: Read Pipe aborted/reset, Status = 0x%x\n",Status));
  854. break;
  855. case WRITE_DATA_PIPE:
  856. DebugTrace(TRACE_STATUS,("USCancelPipe: WRITE_DATA_PIPE\n"));
  857. if(NULL == pIrp){
  858. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! pIrp not valid\n"));
  859. break;
  860. }
  861. if (-1 == pde -> IndexBulkOut) {
  862. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! bulk-out pipe not valid\n"));
  863. DEBUG_BREAKPOINT();
  864. Status = STATUS_NOT_SUPPORTED;
  865. break;
  866. }
  867. Status = USAbortResetPipe(pDeviceObject,
  868. USGetPipeIndexToUse(pDeviceObject, pIrp, pde -> IndexBulkOut),
  869. fAbort);
  870. DebugTrace(TRACE_STATUS,("Write Pipe aborted/reset, Status = 0x%x\n",Status));
  871. break;
  872. case ALL_PIPE:
  873. {
  874. ULONG i;
  875. DebugTrace(TRACE_STATUS,("USCancelPipe: ALL_PIPE\n"));
  876. for(i=0; i < pde -> NumberOfPipes; i++){
  877. temp = USAbortResetPipe(pDeviceObject, i, fAbort);
  878. // DebugTrace(TRACE_STATUS,("USCancelPipe: pipe[%d] aborted/reset, Status = 0x%x\n", i, temp));
  879. if(STATUS_SUCCESS != temp){
  880. Status = temp;
  881. }
  882. }
  883. break;
  884. }
  885. default:
  886. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! INVALID_PIPE\n"));
  887. Status = STATUS_INVALID_PARAMETER;
  888. break;
  889. }
  890. DebugTrace(TRACE_PROC_LEAVE,("USCancelPipe: Leaving.. Status = 0x%x\n", Status));
  891. return Status;
  892. }
  893. NTSTATUS
  894. USAbortResetPipe(
  895. IN PDEVICE_OBJECT pDeviceObject,
  896. IN ULONG uIndex,
  897. IN BOOLEAN fAbort // TRUE = Abort, FALSE = Reset
  898. )
  899. /*++
  900. Routine Description:
  901. Arguments:
  902. Return Value:
  903. --*/
  904. {
  905. NTSTATUS Status = STATUS_SUCCESS;
  906. NTSTATUS StatusReset = STATUS_SUCCESS;
  907. PUSBSCAN_DEVICE_EXTENSION pde;
  908. PURB pUrb;
  909. ULONG siz;
  910. PAGED_CODE();
  911. DebugTrace(TRACE_PROC_ENTER,("USAbortResetPipe: Enter... \n"));
  912. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  913. pUrb = NULL;
  914. //
  915. // Allocate URB
  916. //
  917. siz = sizeof(struct _URB_PIPE_REQUEST);
  918. pUrb = USAllocatePool(NonPagedPool, siz);
  919. if (NULL == pUrb) {
  920. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! cannot allocated URB\n"));
  921. DEBUG_BREAKPOINT();
  922. Status = STATUS_INSUFFICIENT_RESOURCES;
  923. goto USAbortResetPipe_return;
  924. }
  925. RtlZeroMemory(pUrb, siz);
  926. if (fAbort) {
  927. DebugTrace(TRACE_STATUS,("USAbortResetPipe: Aborting pipe[%d]\n", uIndex));
  928. //
  929. // Issue abort pipe call to USBD.
  930. //
  931. UsbBuildAbortPipeRequest(pUrb,
  932. siz,
  933. pde -> PipeInfo[uIndex].PipeHandle);
  934. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  935. if (STATUS_SUCCESS != Status) {
  936. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! Abort pipe failed. Status = 0x%x\n",Status));
  937. goto USAbortResetPipe_return;
  938. }
  939. UsbBuildResetPipeRequest(pUrb,
  940. siz,
  941. pde -> PipeInfo[uIndex].PipeHandle);
  942. StatusReset = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  943. if (STATUS_SUCCESS != StatusReset) {
  944. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! resetting pipe. Status = 0x%x\n",StatusReset));
  945. goto USAbortResetPipe_return;
  946. }
  947. } else {
  948. DebugTrace(TRACE_STATUS,("Reseting pipe[%d]\n", uIndex));
  949. //
  950. // Issue reset pipe call to USBD.
  951. //
  952. UsbBuildResetPipeRequest(pUrb,
  953. siz,
  954. pde -> PipeInfo[uIndex].PipeHandle);
  955. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  956. if (STATUS_SUCCESS != Status) {
  957. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! Reset pipe failed. Status = 0x%x\n",Status));
  958. goto USAbortResetPipe_return;
  959. }
  960. }
  961. USAbortResetPipe_return:
  962. //
  963. // Clean up.
  964. //
  965. if(pUrb){
  966. USFreePool(pUrb);
  967. }
  968. DebugTrace(TRACE_PROC_LEAVE,("USAbortResetPipe: Leaving.. Status = 0x%x\n", Status));
  969. return Status;
  970. }
  971. NTSTATUS
  972. USPassThruUSBRequest(
  973. IN PDEVICE_OBJECT pDeviceObject,
  974. IN PIO_BLOCK_EX pIoBlockEx,
  975. IN ULONG InLength,
  976. IN ULONG OutLength
  977. )
  978. /*++
  979. Routine Description:
  980. Implements generic pass-thru for vendor request to USBD
  981. Arguments:
  982. pDeviceObject - Device object
  983. pIoBlockEx - Pointer to I/O block as described in USBSCAN.H, passed from user mode client
  984. InLength - In length from IRP
  985. OutLength - Out length from IRP
  986. Return Value:
  987. NTSTATUS type
  988. --*/
  989. {
  990. NTSTATUS Status;
  991. PUSBSCAN_DEVICE_EXTENSION pde;
  992. PURB pUrb;
  993. ULONG siz;
  994. PVOID pBuffer;
  995. BOOLEAN fDirectionIn;
  996. PAGED_CODE();
  997. DebugTrace(TRACE_PROC_ENTER,("USPassThruUSBRequest: Enter..\n"));
  998. //
  999. // Initialize local variable.
  1000. //
  1001. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  1002. Status = STATUS_SUCCESS;
  1003. pUrb = NULL;
  1004. pBuffer = NULL;
  1005. fDirectionIn = TRUE;
  1006. //
  1007. // Allocate memory for URB
  1008. //
  1009. siz = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  1010. pUrb = USAllocatePool(NonPagedPool, siz);
  1011. if (NULL == pUrb) {
  1012. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocated URB\n"));
  1013. DEBUG_BREAKPOINT();
  1014. Status = STATUS_INSUFFICIENT_RESOURCES;
  1015. goto USPassThruUSBRequest_return;
  1016. }
  1017. RtlZeroMemory(pUrb, siz);
  1018. //
  1019. // Setup URB
  1020. //
  1021. pBuffer = pIoBlockEx;
  1022. //
  1023. // If we are writing data, then we need to make a copy of the
  1024. // register block into a non-paged block of memory before handing it off
  1025. // to usbd.
  1026. //
  1027. if (!pIoBlockEx->fTransferDirectionIn) {
  1028. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Write request, allocating non-paged buffer, len = %d\n",pIoBlockEx->uLength));
  1029. fDirectionIn = FALSE;
  1030. if ( pIoBlockEx->uLength ) {
  1031. pBuffer = USAllocatePool(NonPagedPool, pIoBlockEx->uLength);
  1032. if (NULL == pBuffer) {
  1033. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocate write buffer"));
  1034. DEBUG_BREAKPOINT();
  1035. Status = STATUS_INSUFFICIENT_RESOURCES;
  1036. goto USPassThruUSBRequest_return;
  1037. }
  1038. //
  1039. // Caller gives us a pointer, embedded into IOCTL buffer. We need to
  1040. // validate that given pointer is readable.
  1041. //
  1042. try{
  1043. RtlCopyMemory(pBuffer,
  1044. pIoBlockEx->pbyData,
  1045. pIoBlockEx->uLength);
  1046. } except(EXCEPTION_EXECUTE_HANDLER) {
  1047. //
  1048. // Caller buffer is not valid, or worse..
  1049. //
  1050. DebugTrace(TRACE_ERROR,("USPassThruUSBRequest: ERROR!! Copying caller buffer failed.\n"));
  1051. DEBUG_BREAKPOINT();
  1052. Status = GetExceptionCode();
  1053. goto USPassThruUSBRequest_return;
  1054. }
  1055. } else {
  1056. //
  1057. // Zero length buffer used for Write , IHV claim that's useful.
  1058. //
  1059. pBuffer = NULL;
  1060. } // if ( pIoBlockEx->uLength )
  1061. }
  1062. UsbBuildVendorClassSpecificCommand(pUrb,
  1063. pIoBlockEx->fTransferDirectionIn ? USBD_TRANSFER_DIRECTION_IN : 0,
  1064. pIoBlockEx->uLength,
  1065. pBuffer,
  1066. NULL,
  1067. pIoBlockEx->bmRequestType,
  1068. pIoBlockEx->bRequest,
  1069. (SHORT)pIoBlockEx->uOffset,
  1070. (USHORT)pIoBlockEx -> uIndex
  1071. );
  1072. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  1073. USPassThruUSBRequest_return:
  1074. //
  1075. // Clean up.
  1076. //
  1077. if(NULL != pUrb){
  1078. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free USB Request Block.\n"));
  1079. USFreePool(pUrb);
  1080. }
  1081. if( (!fDirectionIn)
  1082. && (NULL != pBuffer) )
  1083. {
  1084. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free temp buffer.\n"));
  1085. USFreePool(pBuffer);
  1086. }
  1087. DebugTrace(TRACE_PROC_LEAVE,("USPassThruUSBRequest: Leaving.. Status = 0x%x\n", Status));
  1088. return Status;
  1089. }
  1090. NTSTATUS
  1091. USPassThruUSBRequestPTP(
  1092. IN PDEVICE_OBJECT pDeviceObject,
  1093. IN PIO_BLOCK_EX pIoBlockEx,
  1094. IN ULONG InLength,
  1095. IN ULONG OutLength
  1096. )
  1097. /*++
  1098. Routine Description:
  1099. Implements generic pass-thru for vendor request to USBD
  1100. Arguments:
  1101. pDeviceObject - Device object
  1102. pIoBlockEx - Pointer to I/O block as described in USBSCAN.H, passed from user mode client
  1103. InLength - In length from IRP
  1104. OutLength - Out length from IRP
  1105. Return Value:
  1106. NTSTATUS type
  1107. --*/
  1108. {
  1109. NTSTATUS Status;
  1110. PUSBSCAN_DEVICE_EXTENSION pde;
  1111. PURB pUrb;
  1112. ULONG siz;
  1113. PVOID pBuffer;
  1114. BOOLEAN fDirectionIn;
  1115. USHORT usUsbFunction;
  1116. PAGED_CODE();
  1117. DebugTrace(TRACE_PROC_ENTER,("USPassThruUSBRequest: Enter..\n"));
  1118. //
  1119. // Initialize local variable.
  1120. //
  1121. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  1122. Status = STATUS_SUCCESS;
  1123. pUrb = NULL;
  1124. pBuffer = NULL;
  1125. fDirectionIn = TRUE;
  1126. usUsbFunction = 0;
  1127. //
  1128. // Allocate memory for URB
  1129. //
  1130. siz = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  1131. pUrb = USAllocatePool(NonPagedPool, siz);
  1132. if (NULL == pUrb) {
  1133. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocated URB\n"));
  1134. DEBUG_BREAKPOINT();
  1135. Status = STATUS_INSUFFICIENT_RESOURCES;
  1136. goto USPassThruUSBRequest_return;
  1137. }
  1138. RtlZeroMemory(pUrb, siz);
  1139. //
  1140. // Setup URB
  1141. //
  1142. pBuffer = pIoBlockEx;
  1143. //
  1144. // If we are writing data, then we need to make a copy of the
  1145. // register block into a non-paged block of memory before handing it off
  1146. // to usbd.
  1147. //
  1148. if (!pIoBlockEx->fTransferDirectionIn) {
  1149. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Write request, allocating non-paged buffer, len = %d\n",pIoBlockEx->uLength));
  1150. fDirectionIn = FALSE;
  1151. if ( pIoBlockEx->uLength ) {
  1152. pBuffer = USAllocatePool(NonPagedPool, pIoBlockEx->uLength);
  1153. if (NULL == pBuffer) {
  1154. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocate write buffer"));
  1155. DEBUG_BREAKPOINT();
  1156. Status = STATUS_INSUFFICIENT_RESOURCES;
  1157. goto USPassThruUSBRequest_return;
  1158. }
  1159. //
  1160. // Caller gives us a pointer, embedded into IOCTL buffer. We need to
  1161. // validate that given pointer is readable.
  1162. //
  1163. try{
  1164. RtlCopyMemory(pBuffer,
  1165. pIoBlockEx->pbyData,
  1166. pIoBlockEx->uLength);
  1167. } except(EXCEPTION_EXECUTE_HANDLER) {
  1168. //
  1169. // Caller buffer is not valid, or worse..
  1170. //
  1171. DebugTrace(TRACE_ERROR,("USPassThruUSBRequest: ERROR!! Copying caller buffer failed.\n"));
  1172. DEBUG_BREAKPOINT();
  1173. Status = GetExceptionCode();
  1174. goto USPassThruUSBRequest_return;
  1175. }
  1176. } else {
  1177. //
  1178. // Zero length buffer used for Write , IHV claim that's useful.
  1179. //
  1180. pBuffer = NULL;
  1181. } // if ( pIoBlockEx->uLength )
  1182. }
  1183. //
  1184. // Set proper USB funtion depends on bmRequestType.
  1185. //
  1186. if(0xa1 == pIoBlockEx->bmRequestType){ // USB_PTPREQUEST_TYPE_IN: Class/Interface Device to Host.
  1187. usUsbFunction = URB_FUNCTION_CLASS_INTERFACE;
  1188. } else if(0x21 == pIoBlockEx->bmRequestType){ // USB_PTPREQUEST_TYPE_OUT: Class/Interface Host to Device.
  1189. usUsbFunction = URB_FUNCTION_CLASS_INTERFACE;
  1190. } else { // Default.
  1191. usUsbFunction = URB_FUNCTION_VENDOR_DEVICE;
  1192. }
  1193. UsbBuildVendorClassSpecificCommandPTP(usUsbFunction,
  1194. pUrb,
  1195. pIoBlockEx->fTransferDirectionIn ? USBD_TRANSFER_DIRECTION_IN : 0,
  1196. pIoBlockEx->uLength,
  1197. pBuffer,
  1198. NULL,
  1199. pIoBlockEx->bmRequestType,
  1200. pIoBlockEx->bRequest,
  1201. (SHORT)pIoBlockEx->uOffset,
  1202. (USHORT)pIoBlockEx -> uIndex);
  1203. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  1204. USPassThruUSBRequest_return:
  1205. //
  1206. // Clean up.
  1207. //
  1208. if(NULL != pUrb){
  1209. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free USB Request Block.\n"));
  1210. USFreePool(pUrb);
  1211. }
  1212. if( (!fDirectionIn)
  1213. && (NULL != pBuffer) )
  1214. {
  1215. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free temp buffer.\n"));
  1216. USFreePool(pBuffer);
  1217. }
  1218. DebugTrace(TRACE_PROC_LEAVE,("USPassThruUSBRequest: Leaving.. Status = 0x%x\n", Status));
  1219. return Status;
  1220. } // USPassThruUSBRequestPTP()