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.

1243 lines
38 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. Device driver for USB printers
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 5-4-96 : created
  17. --*/
  18. #define DRIVER
  19. #include "wdm.h"
  20. #include "stdarg.h"
  21. #include "stdio.h"
  22. #include <usb.h>
  23. #include <usbdrivr.h>
  24. #include "usbdlib.h"
  25. #include "usbprint.h"
  26. #include "ioctl.h"
  27. #include "usbdlib.h"
  28. #include "ntddpar.h"
  29. int USBPRINT_GetLptStatus(IN PDEVICE_OBJECT DeviceObject);
  30. NTSTATUS HPUsbIOCTLVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
  31. NTSTATUS HPUsbIOCTLVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
  32. NTSTATUS HPUsbVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,IN PUCHAR buffer,IN ULONG length);
  33. NTSTATUS HPUsbVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,IN PUCHAR buffer,IN ULONG length,OUT PULONG pBytesRead);
  34. NTSTATUS USBPRINT_SoftReset(IN PDEVICE_OBJECT DeviceObject)
  35. /*++
  36. Routine Description:
  37. Issues the class specific "Soft reset" command to the printer
  38. Arguments:
  39. DeviceObject - pointer to the device object for this instance of the printer device.
  40. Return Value:
  41. ntStatus of the URB
  42. --*/
  43. {
  44. NTSTATUS ntStatus;
  45. PURB urb;
  46. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  47. PDEVICE_EXTENSION deviceExtension;
  48. LARGE_INTEGER timeOut;
  49. USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_SoftReset\n"));
  50. deviceExtension = DeviceObject->DeviceExtension;
  51. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), USBP_TAG);
  52. if (urb) {
  53. UsbBuildVendorRequest(urb, //urb
  54. URB_FUNCTION_CLASS_INTERFACE, //request target
  55. sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), //request len
  56. USBD_TRANSFER_DIRECTION_OUT|USBD_SHORT_TRANSFER_OK, //flags
  57. 0, //reserved bits
  58. 2, //request code
  59. 0, //wValue
  60. deviceExtension->Interface->InterfaceNumber<<8, //wIndex
  61. NULL, //return buffer address
  62. NULL, //mdl
  63. 0, //return length
  64. NULL); //link param
  65. timeOut.QuadPart = FAILURE_TIMEOUT;
  66. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  67. USBPRINT_KdPrint3 (("'USBPRINT.SYS: urb->Hdr.Status=%d\n",((struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *)urb)->Hdr.Status));
  68. if (NT_SUCCESS(ntStatus) &&
  69. urb->UrbControlVendorClassRequest.TransferBufferLength > 2)
  70. {
  71. USBPRINT_KdPrint3 (("'USBPRINT.SYS: CallUSBD succeeded\n"));
  72. }
  73. else
  74. {
  75. USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; CallUSBD failed"));
  76. }
  77. ExFreePool(urb);
  78. } /*end if URB OK*/
  79. else
  80. {
  81. USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; urb allocation failed"));
  82. ntStatus=STATUS_NO_MEMORY;
  83. }
  84. return ntStatus;
  85. } /*end function Get1284_Id*/
  86. int USBPRINT_Get1284Id(IN PDEVICE_OBJECT DeviceObject,PVOID pIoBuffer,int iLen)
  87. /*++
  88. Routine Description:
  89. Requests and returns Printer 1284 Device ID
  90. Arguments:
  91. DeviceObject - pointer to the device object for this instance of the printer device.
  92. pIoBuffer - pointer to IO buffer from user mode
  93. iLen - Length of *pIoBuffer;
  94. Return Value:
  95. Success: Length of data written to *pIoBuffer (icluding lenght field in first two bytes of data)
  96. Failure: -1
  97. --*/
  98. {
  99. NTSTATUS ntStatus;
  100. PURB urb;
  101. ULONG siz;
  102. int iReturn = -1;
  103. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  104. PDEVICE_EXTENSION deviceExtension;
  105. LARGE_INTEGER timeOut;
  106. USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_Get1284\n"));
  107. deviceExtension = DeviceObject->DeviceExtension;
  108. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), USBP_TAG);
  109. if (urb) {
  110. siz = iLen;
  111. UsbBuildVendorRequest(urb, //urb
  112. URB_FUNCTION_CLASS_INTERFACE, //request target
  113. sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), //request len
  114. USBD_TRANSFER_DIRECTION_IN|USBD_SHORT_TRANSFER_OK, //flags
  115. 0, //reserved bits
  116. 0, //request code
  117. 0, //wValue
  118. deviceExtension->Interface->InterfaceNumber<<8, //wIndex
  119. pIoBuffer, //return buffer address
  120. NULL, //mdl
  121. iLen, //return length
  122. NULL); //link param
  123. timeOut.QuadPart = FAILURE_TIMEOUT;
  124. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  125. USBPRINT_KdPrint3 (("'USBPRINT.SYS: urb->Hdr.Status=%d\n",((struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *)urb)->Hdr.Status));
  126. if (NT_SUCCESS(ntStatus) &&
  127. urb->UrbControlVendorClassRequest.TransferBufferLength > 2)
  128. {
  129. USBPRINT_KdPrint3 (("'USBPRINT.SYS: CallUSBD succeeded\n"));
  130. iReturn= *((unsigned char *)pIoBuffer);
  131. iReturn<<=8;
  132. iReturn+=*(((unsigned char *)pIoBuffer)+1);
  133. if ( iReturn > 0 && iReturn < iLen )
  134. {
  135. *(((char *)pIoBuffer)+iReturn)='\0';
  136. USBPRINT_KdPrint3 (("'USBPRINT.SYS: return size ==%d\n",iReturn));
  137. }
  138. else
  139. {
  140. iReturn = -1;
  141. }
  142. }
  143. else
  144. {
  145. USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; CallUSBD failed\n"));
  146. iReturn=-1;
  147. }
  148. ExFreePool(urb);
  149. } /*end if URB OK*/
  150. else
  151. {
  152. USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; urb allocation failed"));
  153. iReturn=-1;
  154. }
  155. return iReturn;
  156. } /*end function Get1284_Id*/
  157. int USBPRINT_GetLptStatus(IN PDEVICE_OBJECT DeviceObject)
  158. /*++
  159. Routine Description:
  160. Requests and returns Printer status byte from USB printer
  161. Arguments:
  162. DeviceObject - pointer to the device object for this instance of the printer device.
  163. Return Value:
  164. Success: status value 0-255
  165. Failure: -1
  166. --*/
  167. {
  168. NTSTATUS ntStatus;
  169. PURB urb;
  170. ULONG siz;
  171. unsigned char RETURN_BUFF[1];
  172. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  173. PDEVICE_EXTENSION deviceExtension;
  174. LARGE_INTEGER timeOut;
  175. RETURN_BUFF[0] = 0;
  176. timeOut.QuadPart = FAILURE_TIMEOUT;
  177. deviceExtension = DeviceObject->DeviceExtension;
  178. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), USBP_TAG);
  179. if (urb) {
  180. siz = sizeof(RETURN_BUFF);
  181. UsbBuildVendorRequest(urb,
  182. URB_FUNCTION_CLASS_INTERFACE,
  183. sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
  184. USBD_TRANSFER_DIRECTION_IN|USBD_SHORT_TRANSFER_OK,
  185. 0, //reserved bits
  186. 1, //request code
  187. 0,
  188. deviceExtension->Interface->InterfaceNumber,
  189. RETURN_BUFF, //return buffer address
  190. NULL, //mdl
  191. sizeof(RETURN_BUFF), //return length
  192. NULL); //link param
  193. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  194. USBPRINT_KdPrint3 (("'USBPRINT.SYS: urb->Hdr.Status=%d\n",((struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *)urb)->Hdr.Status));
  195. ExFreePool(urb);
  196. if (NT_SUCCESS(ntStatus))
  197. {
  198. USBPRINT_KdPrint3 (("'USBPRINT.SYS: CallUSBD succeeded\n"));
  199. return (int) RETURN_BUFF[0];
  200. }
  201. else
  202. {
  203. USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; CallUSBD failed"));
  204. return -1;
  205. }
  206. } /*end if URB OK*/
  207. else {
  208. return -1;
  209. }
  210. } /*end function GetLptStatus*/
  211. PUSB_CONFIGURATION_DESCRIPTOR
  212. USBPRINT_GetConfigDescriptor(
  213. IN PDEVICE_OBJECT DeviceObject
  214. )
  215. /*++
  216. Routine Description:
  217. Arguments:
  218. DeviceObject - pointer to the device object for this printer
  219. Return Value:
  220. NT status code
  221. --*/
  222. {
  223. PDEVICE_EXTENSION deviceExtension;
  224. NTSTATUS ntStatus;
  225. PURB urb;
  226. ULONG siz;
  227. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  228. LARGE_INTEGER timeOut;
  229. timeOut.QuadPart = FAILURE_TIMEOUT;
  230. USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_GetConfigDescriptor\n"));
  231. deviceExtension = DeviceObject->DeviceExtension;
  232. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBP_TAG);
  233. if (urb) {
  234. siz = sizeof(USB_CONFIGURATION_DESCRIPTOR)+256;
  235. get_config_descriptor_retry2:
  236. configurationDescriptor = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
  237. if (configurationDescriptor) {
  238. UsbBuildGetDescriptorRequest(urb,
  239. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  240. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  241. 0,
  242. 0,
  243. configurationDescriptor,
  244. NULL,
  245. siz,
  246. NULL);
  247. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  248. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Configuration Descriptor = %x, len %x\n",
  249. configurationDescriptor,
  250. urb->UrbControlDescriptorRequest.TransferBufferLength));
  251. } else {
  252. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  253. }
  254. if (NT_SUCCESS(ntStatus) &&
  255. (urb->UrbControlDescriptorRequest.TransferBufferLength >=
  256. sizeof(USB_CONFIGURATION_DESCRIPTOR)) &&
  257. (configurationDescriptor->wTotalLength >=
  258. sizeof(USB_CONFIGURATION_DESCRIPTOR)))
  259. {
  260. //
  261. // The Get Config Descriptor request did not return an error
  262. // AND at least enough data was transferred to fill a Config
  263. // Descriptor AND the Config Descriptor wLength is at least the
  264. // size of a Config Descriptor
  265. //
  266. if (configurationDescriptor->wTotalLength > siz)
  267. {
  268. //
  269. // The request buffer is not big enough to hold the
  270. // entire set of descriptors. Free the current buffer
  271. // and retry with a buffer which should be big enough.
  272. //
  273. siz = configurationDescriptor->wTotalLength;
  274. ExFreePool(configurationDescriptor);
  275. configurationDescriptor = NULL;
  276. goto get_config_descriptor_retry2;
  277. }
  278. else if (configurationDescriptor->wTotalLength >
  279. urb->UrbControlDescriptorRequest.TransferBufferLength)
  280. {
  281. //
  282. // The request buffer is greater than or equal to the
  283. // Config Descriptor wLength, but less data was transferred
  284. // than wLength. Return NULL to indicate a device error.
  285. //
  286. ExFreePool(configurationDescriptor);
  287. configurationDescriptor = NULL;
  288. }
  289. //
  290. // else everything is OK with the Config Descriptor, return it.
  291. //
  292. }
  293. else
  294. {
  295. //
  296. // The Get Config Descriptor request returned an error OR
  297. // not enough data was transferred to fill a Config Descriptor
  298. // OR the Config Descriptor wLength is less than the size of
  299. // a Config Descriptor. Return NULL to indicate a device error.
  300. //
  301. ExFreePool(configurationDescriptor);
  302. configurationDescriptor = NULL;
  303. }
  304. ExFreePool(urb);
  305. } else {
  306. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  307. }
  308. USBPRINT_KdPrint2 (("'USBPRINT.SYS: exit USBPRINT_GetConfigDescriptor\n"));
  309. return configurationDescriptor;
  310. }
  311. typedef enum _CLOCKMASTER_OP {
  312. TakeControl,
  313. FreeControl,
  314. ChangeClock,
  315. GetClock
  316. } CLOCKMASTER_OP;
  317. NTSTATUS
  318. USBPRINT_ClockMaster(
  319. IN PDEVICE_OBJECT DeviceObject,
  320. IN CLOCKMASTER_OP Op
  321. )
  322. /*++
  323. Routine Description:
  324. modifies the USB SOF clock
  325. Arguments:
  326. Return Value:
  327. STATUS_SUCCESS if successful,
  328. STATUS_UNSUCCESSFUL otherwise
  329. --*/
  330. {
  331. NTSTATUS ntStatus;
  332. PURB urb;
  333. USHORT siz;
  334. USHORT func;
  335. USBPRINT_KdPrint2 (("'USBPRINT.SYS: ClockMaster\n"));
  336. switch(Op) {
  337. case TakeControl:
  338. func = URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL;
  339. siz = sizeof(struct _URB_FRAME_LENGTH_CONTROL);
  340. break;
  341. case FreeControl:
  342. func = URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL;
  343. siz = sizeof(struct _URB_FRAME_LENGTH_CONTROL);
  344. break;
  345. case ChangeClock:
  346. siz = sizeof(struct _URB_SET_FRAME_LENGTH);
  347. func = URB_FUNCTION_SET_FRAME_LENGTH;
  348. break;
  349. case GetClock:
  350. siz = sizeof(struct _URB_GET_FRAME_LENGTH);
  351. func = URB_FUNCTION_GET_FRAME_LENGTH;
  352. break;
  353. }
  354. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST), USBP_TAG);
  355. if (urb) {
  356. switch(Op) {
  357. case TakeControl:
  358. case FreeControl:
  359. case GetClock:
  360. break;
  361. case ChangeClock:
  362. urb->UrbSetFrameLength.FrameLengthDelta = 1;
  363. break;
  364. }
  365. urb->UrbHeader.Length = siz;
  366. urb->UrbHeader.Function = func;
  367. //
  368. // Do we need a timeout here?
  369. //
  370. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, NULL);
  371. switch(Op) {
  372. case TakeControl:
  373. USBPRINT_KdPrint3 (("'USBPRINT.SYS: TakeControl\n"));
  374. break;
  375. case FreeControl:
  376. USBPRINT_KdPrint3 (("'USBPRINT.SYS: FreeControl\n"));
  377. break;
  378. case GetClock:
  379. USBPRINT_KdPrint3 (("'USBPRINT.SYS: GetClock %d\n", urb->UrbGetFrameLength.FrameLength));
  380. break;
  381. case ChangeClock:
  382. USBPRINT_KdPrint3 (("'USBPRINT.SYS: ChangeClock\n"));
  383. break;
  384. }
  385. USBPRINT_KdPrint3 (("'USBPRINT.SYS: clock op status = %x urb = %x\n", ntStatus,
  386. urb->UrbHeader.Status));
  387. ExFreePool(urb);
  388. } else {
  389. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  390. }
  391. return ntStatus;
  392. }
  393. NTSTATUS
  394. USBPRINT_GetPortStatus(
  395. IN PDEVICE_OBJECT DeviceObject,
  396. IN PULONG PortStatus
  397. )
  398. /*++
  399. Routine Description:
  400. returns the port status for our device
  401. Arguments:
  402. Return Value:
  403. STATUS_SUCCESS if successful,
  404. STATUS_UNSUCCESSFUL otherwise
  405. --*/
  406. {
  407. NTSTATUS ntStatus, status = STATUS_SUCCESS;
  408. PIRP irp;
  409. KEVENT event;
  410. IO_STATUS_BLOCK ioStatus;
  411. PIO_STACK_LOCATION nextStack;
  412. PDEVICE_EXTENSION deviceExtension;
  413. USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_GetPortStatus\n"));
  414. deviceExtension = DeviceObject->DeviceExtension;
  415. *PortStatus = 0;
  416. //
  417. // issue a synchronous request
  418. //
  419. KeInitializeEvent(&event, NotificationEvent, FALSE);
  420. irp = IoBuildDeviceIoControlRequest(
  421. IOCTL_INTERNAL_USB_GET_PORT_STATUS,
  422. deviceExtension->TopOfStackDeviceObject,
  423. NULL,
  424. 0,
  425. NULL,
  426. 0,
  427. TRUE, /* INTERNAL */
  428. &event,
  429. &ioStatus);
  430. //
  431. // Call the class driver to perform the operation. If the returned status
  432. // is PENDING, wait for the request to complete.
  433. //
  434. nextStack = IoGetNextIrpStackLocation(irp);
  435. ASSERT(nextStack != NULL);
  436. nextStack->Parameters.Others.Argument1 = PortStatus;
  437. USBPRINT_KdPrint3 (("'USBPRINT.SYS: calling USBD port status api\n"));
  438. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
  439. irp);
  440. USBPRINT_KdPrint3 (("'USBPRINT.SYS: return from IoCallDriver USBD (in getportstatus)%x\n", ntStatus));
  441. if (ntStatus == STATUS_PENDING) {
  442. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object\n"));
  443. status = KeWaitForSingleObject(
  444. &event,
  445. Suspended,
  446. KernelMode,
  447. FALSE,
  448. NULL);
  449. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object, returned %x\n", status));
  450. } else {
  451. ioStatus.Status = ntStatus;
  452. }
  453. if (!NT_SUCCESS(ntStatus))
  454. {
  455. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Error! IoCallDriver failed\n"));
  456. }
  457. else
  458. {
  459. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success! IoCallDriver did not fail\n"));
  460. }
  461. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Port status = %x\n", *PortStatus));
  462. //
  463. // USBD maps the error code for us
  464. //
  465. ntStatus = ioStatus.Status;
  466. USBPRINT_KdPrint3 (("'USBPRINT.SYS: USBPRINT_GetPortStatus (%x)\n", ntStatus));
  467. return ntStatus;
  468. }
  469. NTSTATUS
  470. USBPRINT_ResetParentPort(
  471. IN IN PDEVICE_OBJECT DeviceObject
  472. )
  473. /*++
  474. Routine Description:
  475. Reset the our parent port
  476. Arguments:
  477. Return Value:
  478. STATUS_SUCCESS if successful,
  479. STATUS_UNSUCCESSFUL otherwise
  480. --*/
  481. {
  482. NTSTATUS ntStatus, status = STATUS_SUCCESS;
  483. PIRP irp;
  484. KEVENT event;
  485. IO_STATUS_BLOCK ioStatus;
  486. PIO_STACK_LOCATION nextStack;
  487. PDEVICE_EXTENSION deviceExtension;
  488. USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_ResetPort\n"));
  489. deviceExtension = DeviceObject->DeviceExtension;
  490. //
  491. // issue a synchronous request
  492. //
  493. KeInitializeEvent(&event, NotificationEvent, FALSE);
  494. irp = IoBuildDeviceIoControlRequest(
  495. IOCTL_INTERNAL_USB_RESET_PORT,
  496. deviceExtension->TopOfStackDeviceObject,
  497. NULL,
  498. 0,
  499. NULL,
  500. 0,
  501. TRUE, /* INTERNAL */
  502. &event,
  503. &ioStatus);
  504. //
  505. // Call the class driver to perform the operation. If the returned status
  506. // is PENDING, wait for the request to complete.
  507. //
  508. nextStack = IoGetNextIrpStackLocation(irp);
  509. ASSERT(nextStack != NULL);
  510. USBPRINT_KdPrint3 (("'USBPRINT.SYS: calling USBD enable port api\n"));
  511. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
  512. irp);
  513. USBPRINT_KdPrint3 (("'USBPRINT.SYS: return from IoCallDriver USBD (in reset parent port)%x\n", ntStatus));
  514. if (ntStatus == STATUS_PENDING) {
  515. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object\n"));
  516. status = KeWaitForSingleObject(
  517. &event,
  518. Suspended,
  519. KernelMode,
  520. FALSE,
  521. NULL);
  522. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object, returned %x\n", status));
  523. } else {
  524. ioStatus.Status = ntStatus;
  525. }
  526. //
  527. // USBD maps the error code for us
  528. //
  529. ntStatus = ioStatus.Status;
  530. USBPRINT_KdPrint3 (("'USBPRINT.SYS: USBPRINT_ResetPort (%x)\n", ntStatus));
  531. return ntStatus;
  532. }
  533. NTSTATUS
  534. USBPRINT_ProcessIOCTL(
  535. IN PDEVICE_OBJECT DeviceObject,
  536. IN PIRP Irp
  537. )
  538. /*++
  539. Routine Description:
  540. Arguments:
  541. DeviceObject - pointer to the device object for this printer
  542. Return Value:
  543. NT status code
  544. --*/
  545. {
  546. PIO_STACK_LOCATION irpStack;
  547. PVOID ioBuffer;
  548. ULONG inputBufferLength;
  549. ULONG outputBufferLength;
  550. PDEVICE_EXTENSION deviceExtension;
  551. ULONG ioControlCode;
  552. NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  553. PUCHAR pch;
  554. USBPRINT_KdPrint2 (("'USBPRINT.SYS: IRP_MJ_DEVICE_CONTROL\n"));
  555. USBPRINT_IncrementIoCount(DeviceObject);
  556. //
  557. // Get a pointer to the current location in the Irp. This is where
  558. // the function codes and parameters are located.
  559. //
  560. deviceExtension = DeviceObject->DeviceExtension;
  561. if (deviceExtension->AcceptingRequests == FALSE) {
  562. ntStatus = STATUS_DEVICE_DATA_ERROR;
  563. Irp->IoStatus.Status = ntStatus;
  564. Irp->IoStatus.Information = 0;
  565. IoCompleteRequest (Irp,
  566. IO_NO_INCREMENT
  567. );
  568. USBPRINT_DecrementIoCount(DeviceObject);
  569. return ntStatus;
  570. }
  571. irpStack = IoGetCurrentIrpStackLocation (Irp);
  572. Irp->IoStatus.Information = 0;
  573. ioBuffer = Irp->AssociatedIrp.SystemBuffer;
  574. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  575. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  576. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  577. //
  578. // Handle Ioctls from User mode
  579. //
  580. switch (ioControlCode) {
  581. case IOCTL_USBPRINT_SET_PIPE_PARAMETER:
  582. ntStatus = STATUS_SUCCESS;
  583. break;
  584. case IOCTL_PAR_QUERY_DEVICE_ID:
  585. {
  586. int iReturn;
  587. char * pTempBuffer;
  588. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Enter in PAR_QUERY_DEVICE_ID\n"));
  589. pTempBuffer=ExAllocatePool(NonPagedPool,outputBufferLength+3); //3 == 2 bytes for the size at the beginning, plus 1 for the null at the end
  590. if(pTempBuffer==NULL)
  591. {
  592. Irp->IoStatus.Information=0;
  593. ntStatus=STATUS_NO_MEMORY;
  594. }
  595. else
  596. {
  597. iReturn=USBPRINT_Get1284Id(DeviceObject,pTempBuffer,outputBufferLength+2);
  598. if(iReturn>0)
  599. {
  600. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success in PAR_QUERY_DEVICE_ID\n"));
  601. Irp->IoStatus.Information=iReturn-1;
  602. *(pTempBuffer+iReturn)='\0';
  603. RtlCopyBytes(ioBuffer,pTempBuffer+2,iReturn-1); //+2 to step past the size bytes at the beginning, -1 is +1 for null -2 for size bytes
  604. ntStatus=STATUS_SUCCESS;
  605. } /*if success*/
  606. else
  607. {
  608. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Failure in PAR_QUERY_DEVICE_ID\n"));
  609. Irp->IoStatus.Information=0;
  610. ntStatus=STATUS_DEVICE_DATA_ERROR;
  611. } /*else failure*/
  612. ExFreePool(pTempBuffer);
  613. } /*end else malloc OK*/
  614. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Exit in PAR_QUERY_DEVICE_ID\n"));
  615. }
  616. break;
  617. case IOCTL_USBPRINT_SOFT_RESET:
  618. ntStatus=USBPRINT_SoftReset(DeviceObject);
  619. Irp->IoStatus.Information=0;
  620. break;
  621. case IOCTL_USBPRINT_GET_1284_ID:
  622. {
  623. int iReturn;
  624. pch = (PUCHAR) ioBuffer;
  625. if(outputBufferLength<sizeof(UCHAR))
  626. {
  627. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Buffer to small in GET_1284_ID\n"));
  628. Irp->IoStatus.Information=0;
  629. ntStatus=STATUS_BUFFER_TOO_SMALL;
  630. }
  631. else
  632. {
  633. iReturn=USBPRINT_Get1284Id(DeviceObject,ioBuffer,outputBufferLength);
  634. if(iReturn>=0)
  635. {
  636. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success in GET_1284_ID\n"));
  637. *pch=(UCHAR)iReturn;
  638. Irp->IoStatus.Information=iReturn;
  639. ntStatus=STATUS_SUCCESS;
  640. } /*if success*/
  641. else
  642. {
  643. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Failure in GET_1284_ID\n"));
  644. Irp->IoStatus.Information=0;
  645. ntStatus=STATUS_DEVICE_DATA_ERROR;
  646. } /*else failure*/
  647. } /*end else buffer len OK*/
  648. }
  649. break; //end case GET_1284_ID
  650. case IOCTL_USBPRINT_GET_LPT_STATUS:
  651. {
  652. int iReturn;
  653. pch = (PUCHAR) ioBuffer;
  654. if(outputBufferLength<sizeof(UCHAR))
  655. {
  656. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Buffer to small in GET_LPT_STATUS\n"));
  657. Irp->IoStatus.Information=0;
  658. ntStatus=STATUS_BUFFER_TOO_SMALL;
  659. }
  660. else
  661. {
  662. iReturn= USBPRINT_GetLptStatus(DeviceObject);
  663. if(iReturn>=0)
  664. {
  665. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success in GET_LPT_STATUS\n"));
  666. *pch=(UCHAR)iReturn;
  667. Irp->IoStatus.Information=1;
  668. ntStatus=STATUS_SUCCESS;
  669. } /*if success*/
  670. else
  671. {
  672. USBPRINT_KdPrint1 (("'USBPRINT.SYS: Failure in GET_LPT_STATUS\n"));
  673. Irp->IoStatus.Information=0;
  674. ntStatus=STATUS_DEVICE_DATA_ERROR;
  675. } /*else failure*/
  676. } /*end else buffer OK*/
  677. }
  678. break;
  679. case IOCTL_USBPRINT_VENDOR_SET_COMMAND:
  680. ntStatus=HPUsbIOCTLVendorSetCommand(DeviceObject,Irp);
  681. break;
  682. case IOCTL_USBPRINT_VENDOR_GET_COMMAND:
  683. ntStatus=HPUsbIOCTLVendorGetCommand(DeviceObject,Irp);
  684. break;
  685. case IOCTL_USBPRINT_RESET_DEVICE:
  686. {
  687. ULONG portStatus;
  688. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Reset Device Test\n"));
  689. TRAP(); // test this
  690. //
  691. // Check the port state, if it is disabled we will need
  692. // to re-enable it
  693. //
  694. ntStatus = USBPRINT_GetPortStatus(DeviceObject, &portStatus);
  695. if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&portStatus & USBD_PORT_CONNECTED)
  696. {
  697. //
  698. // port is disabled, attempt reset
  699. //
  700. //USBPRINT_EnableParentPort(DeviceObject);
  701. USBPRINT_KdPrint2 (("'USBPRINT.SYS: Resetting port\n"));
  702. USBPRINT_ResetParentPort(DeviceObject);
  703. }
  704. }
  705. break;
  706. case IOCTL_USBPRINT_CLOCK_MASTER_TEST:
  707. {
  708. USBPRINT_KdPrint3 (("'USBPRINT.SYS: Clock Master Test\n"));
  709. TRAP(); // test this
  710. // get the clock
  711. USBPRINT_ClockMaster(DeviceObject, GetClock);
  712. // take control to change clock
  713. //ntStatus = USBPRINT_ClockMaster(DeviceObject, TakeControl);
  714. //if (NT_SUCCESS(ntStatus)) {
  715. ntStatus = USBPRINT_ClockMaster(DeviceObject, ChangeClock);
  716. //}
  717. USBPRINT_ClockMaster(DeviceObject, FreeControl);
  718. }
  719. break;
  720. default:
  721. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  722. break;
  723. }
  724. Irp->IoStatus.Status = ntStatus;
  725. IoCompleteRequest (Irp,
  726. IO_NO_INCREMENT
  727. );
  728. USBPRINT_DecrementIoCount(DeviceObject);
  729. return ntStatus;
  730. }
  731. /****************STUFF FROM HP:*************************/
  732. /*-------------------------------------------------------------------------------
  733. * HPUsbIOCTLVendorSetCommand() - Send a vendor defined SET command
  734. *-------------------------------------------------------------------------------
  735. */
  736. NTSTATUS HPUsbIOCTLVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
  737. {
  738. // Local Variables
  739. NTSTATUS ntStatus;
  740. PIO_STACK_LOCATION currentIrpStack;
  741. // Set up a local pointer to the Irp stack
  742. currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  743. // Send the SET command
  744. ntStatus = HPUsbVendorSetCommand(DeviceObject,
  745. (PUCHAR) Irp->AssociatedIrp.SystemBuffer,
  746. currentIrpStack->Parameters.DeviceIoControl.InputBufferLength);
  747. // Set the Irp information values
  748. Irp->IoStatus.Status = ntStatus;
  749. Irp->IoStatus.Information = 0;
  750. // Return
  751. return ntStatus;
  752. }
  753. /*-------------------------------------------------------------------------------
  754. * HPUsbIOCTLVendorGetCommand() - Send a vendor defined GET command
  755. *-------------------------------------------------------------------------------
  756. */
  757. NTSTATUS HPUsbIOCTLVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
  758. {
  759. // Local Variables
  760. NTSTATUS ntStatus;
  761. PIO_STACK_LOCATION currentIrpStack;
  762. ULONG bytesRead = 0;
  763. // Set up a local pointer to the Irp stack
  764. currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  765. // Get the port status
  766. ntStatus = HPUsbVendorGetCommand(DeviceObject,
  767. (PUCHAR) Irp->AssociatedIrp.SystemBuffer,
  768. currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  769. &bytesRead);
  770. // Set the Irp information values
  771. Irp->IoStatus.Status = ntStatus;
  772. Irp->IoStatus.Information = bytesRead;
  773. // Return
  774. return ntStatus;
  775. }
  776. /*-------------------------------------------------------------------------------
  777. * HPUsbVendorSetCommand() - Send a vendor specified SET command
  778. *
  779. * Inputs:
  780. * buffer[0] - Vendor Request Code (bRequest function code)
  781. * buffer[1] - Vendor Request Value Most Significant Byte (wValue MSB)
  782. * buffer[2] - Vendor Request Value Least Significant Byte (wValue LSB)
  783. * buffer[3...] - Any data to be sent as part of the command
  784. *
  785. *-------------------------------------------------------------------------------
  786. */
  787. NTSTATUS HPUsbVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,
  788. IN PUCHAR buffer,
  789. IN ULONG length)
  790. {
  791. // Local variables
  792. NTSTATUS ntStatus;
  793. PDEVICE_EXTENSION deviceExtension;
  794. PUSBD_INTERFACE_INFORMATION interface;
  795. PURB urb;
  796. ULONG size;
  797. UCHAR bRequest;
  798. USHORT wValue;
  799. USHORT wIndex;
  800. if ( buffer == NULL || length < 3 )
  801. return STATUS_INVALID_PARAMETER;
  802. // Set up a local pointer to the device extension
  803. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  804. // Set up a local pointer to the interface
  805. interface = deviceExtension->Interface;
  806. // Determine the size of the URB
  807. size = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  808. // Allocate memory for the USB Request Block (URB)
  809. // urb = (PURB)
  810. // ExAllocatePoolWithTag(NonPagedPool,size,HPUSB_ALLOC_TAG);
  811. urb = ExAllocatePoolWithTag(NonPagedPool,size, USBP_TAG);
  812. // Check for an error
  813. if (urb == NULL)
  814. return STATUS_NO_MEMORY;
  815. // Store the vendor request code
  816. bRequest = buffer[0];
  817. // Store the vendor request parameter
  818. wValue = (buffer[1] << 8) | buffer[2];
  819. // Create the wIndex value (Interface:Alternate)
  820. wIndex = (interface->InterfaceNumber << 8) |
  821. (interface->AlternateSetting);
  822. // Use a macro in the standard USB header files to build the URB
  823. UsbBuildVendorRequest(urb,
  824. URB_FUNCTION_VENDOR_INTERFACE,
  825. (USHORT) size,
  826. 0,
  827. 0,
  828. bRequest,
  829. wValue,
  830. wIndex,
  831. buffer,
  832. NULL,
  833. length,
  834. NULL);
  835. //
  836. // Timeout cancellation should happen from user mode
  837. //
  838. ntStatus = USBPRINT_CallUSBD(DeviceObject,urb, NULL);
  839. // Free allocated memory
  840. ExFreePool(urb);
  841. // Return Success
  842. return ntStatus;
  843. }
  844. /*-------------------------------------------------------------------------------
  845. * HPUsbVendorGetCommand() - Send a vendor specified GET command
  846. *
  847. * Inputs:
  848. * buffer[0] - Vendor Request Code (bRequest function code)
  849. * buffer[1] - Vendor Request Value Most Significant Byte (wValue MSB)
  850. * buffer[2] - Vendor Request Value Least Significant Byte (wValue LSB)
  851. * Outputs:
  852. * buffer[ ] - Response data
  853. *
  854. *-------------------------------------------------------------------------------
  855. */
  856. NTSTATUS HPUsbVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,
  857. IN PUCHAR buffer,
  858. IN ULONG length,
  859. OUT PULONG pBytesRead)
  860. {
  861. // Local variables
  862. NTSTATUS ntStatus;
  863. PDEVICE_EXTENSION deviceExtension;
  864. PUSBD_INTERFACE_INFORMATION interface;
  865. PURB urb;
  866. ULONG size;
  867. UCHAR bRequest;
  868. USHORT wValue;
  869. USHORT wIndex;
  870. if ( buffer == NULL || length < 3 )
  871. return STATUS_INVALID_PARAMETER;
  872. // Initialize the pBytesRead return value
  873. *pBytesRead = 0;
  874. // Set up a local pointer to the device extension
  875. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  876. // Set up a local pointer to the interface
  877. interface = deviceExtension->Interface;
  878. // Determine the size of the URB
  879. size = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  880. // Allocate memory for the USB Request Block (URB)
  881. // urb = (PURB)
  882. // ExAllocatePoolWithTag(NonPagedPool,size,HPUSB_ALLOC_TAG);
  883. urb = ExAllocatePoolWithTag(NonPagedPool,size, USBP_TAG);
  884. // Check for an error
  885. if (urb == NULL)
  886. return STATUS_NO_MEMORY;
  887. // Store the vendor request code
  888. bRequest = buffer[0];
  889. // Store the vendor request parameter
  890. wValue = (buffer[1] << 8) | buffer[2];
  891. // Create the wIndex value (Interface:Alternate)
  892. wIndex = (interface->InterfaceNumber << 8) |
  893. (interface->AlternateSetting);
  894. // Use a macro in the standard USB header files to build the URB
  895. UsbBuildVendorRequest(urb,
  896. URB_FUNCTION_VENDOR_INTERFACE,
  897. (USHORT) size,
  898. USBD_TRANSFER_DIRECTION_IN |
  899. USBD_SHORT_TRANSFER_OK,
  900. 0,
  901. bRequest,
  902. wValue,
  903. wIndex,
  904. buffer,
  905. NULL,
  906. length,
  907. NULL);
  908. //
  909. // Timeout cancellation should happen from user mode
  910. //
  911. ntStatus = USBPRINT_CallUSBD(DeviceObject,urb, NULL);
  912. // Retrieve the number of bytes read
  913. if (NT_SUCCESS(ntStatus))
  914. *pBytesRead = urb->UrbControlVendorClassRequest.TransferBufferLength;
  915. // Free allocated memory
  916. ExFreePool(urb);
  917. // Return Success
  918. return ntStatus;
  919. }
  920. /*
  921. // -----------------------------------------------------------
  922. // Kernel Mode Usage
  923. // -----------------------------------------------------------
  924. // Create the channel change request
  925. Buffer[0] = HP_VENDOR_COMMAND_DO_SOMETHING;
  926. Buffer[1] = HP_PARAMETER_UPPER_BYTE;
  927. Buffer[2] = HP_PARAMETER_LOWER_BYTE;
  928. // Send the request
  929. status = CallDeviceIoControl(
  930. m_pTargetDeviceObject, // the device to send the new irp to
  931. IOCTL_HPUSB_VENDOR_GET_COMMAND, // the ioctl to send to the driver ,
  932. Buffer, // the input buffer for the ioctl
  933. 3, // the length of the input buffer
  934. Buffer, // the output buffer for the ioctl
  935. 1, // the length of the output buffer
  936. FALSE, // create the irp with IRP_MJ_DEVICE_CONTROL
  937. NULL); // use the provided completion routine
  938. */