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.

2259 lines
96 KiB

  1. /***************************************************************************
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. SERIOCTL.C
  5. Abstract:
  6. Routines to handle serial IOCTLs for Legacy USB Modem Driver.
  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) 1998 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 12/27/97 : created
  17. Authors:
  18. Tom Green
  19. ****************************************************************************/
  20. #include <wdm.h>
  21. #include <ntddser.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <usb.h>
  25. #include <usbdrivr.h>
  26. #include <usbdlib.h>
  27. #include <usbcomm.h>
  28. #ifdef WMI_SUPPORT
  29. #include <wmilib.h>
  30. #include <wmidata.h>
  31. #include <wmistr.h>
  32. #endif
  33. #include "usbser.h"
  34. #include "serioctl.h"
  35. #include "utils.h"
  36. #include "usbserpw.h"
  37. #include "debugwdm.h"
  38. #ifdef ALLOC_PRAGMA
  39. #pragma alloc_text(PAGEUSBS, SetBaudRate)
  40. #pragma alloc_text(PAGEUSBS, GetBaudRate)
  41. #pragma alloc_text(PAGEUSBS, SetLineControl)
  42. #pragma alloc_text(PAGEUSBS, GetLineControl)
  43. #pragma alloc_text(PAGEUSBS, SetTimeouts)
  44. #pragma alloc_text(PAGEUSBS, GetTimeouts)
  45. #pragma alloc_text(PAGEUSBS, SetChars)
  46. #pragma alloc_text(PAGEUSBS, GetChars)
  47. #pragma alloc_text(PAGEUSBS, SetClrDtr)
  48. #pragma alloc_text(PAGEUSBS, ResetDevice)
  49. #pragma alloc_text(PAGEUSBS, SetRts)
  50. #pragma alloc_text(PAGEUSBS, ClrRts)
  51. #pragma alloc_text(PAGEUSBS, SetBreak)
  52. #pragma alloc_text(PAGEUSBS, SetQueueSize)
  53. #pragma alloc_text(PAGEUSBS, GetWaitMask)
  54. #pragma alloc_text(PAGEUSBS, SetWaitMask)
  55. #pragma alloc_text(PAGEUSBS, WaitOnMask)
  56. #pragma alloc_text(PAGEUSBS, ImmediateChar)
  57. #pragma alloc_text(PAGEUSBS, Purge)
  58. #pragma alloc_text(PAGEUSBS, GetHandflow)
  59. #pragma alloc_text(PAGEUSBS, SetHandflow)
  60. #pragma alloc_text(PAGEUSBS, GetModemStatus)
  61. #pragma alloc_text(PAGEUSBS, GetDtrRts)
  62. #pragma alloc_text(PAGEUSBS, GetCommStatus)
  63. #pragma alloc_text(PAGEUSBS, GetProperties)
  64. #pragma alloc_text(PAGEUSBS, LsrmstInsert)
  65. #pragma alloc_text(PAGEUSBS, ConfigSize)
  66. #pragma alloc_text(PAGEUSBS, GetStats)
  67. #pragma alloc_text(PAGEUSBS, ClearStats)
  68. #pragma alloc_text(PAGEUSBS, SerialGetProperties)
  69. #endif // ALLOC_PRAGMA
  70. LOCAL UCHAR StopBits[] =
  71. {
  72. STOP_BIT_1, // USB_COMM_STOPBITS_10
  73. STOP_BITS_1_5, // USB_COMM_STOPBITS_15
  74. STOP_BITS_2 // USB_COMM_STOPBITS_20
  75. };
  76. LOCAL UCHAR ParityType[] =
  77. {
  78. NO_PARITY, // USB_COMM_PARITY_NONE
  79. ODD_PARITY, // USB_COMM_PARITY_ODD
  80. EVEN_PARITY, // USB_COMM_PARITY_EVEN
  81. MARK_PARITY, // USB_COMM_PARITY_MARK
  82. SPACE_PARITY // USB_COMM_PARITY_SPACE
  83. };
  84. /************************************************************************/
  85. /* SetBaudRate */
  86. /************************************************************************/
  87. /* */
  88. /* Routine Description: */
  89. /* */
  90. /* Handle IOCTL_SERIAL_SET_BAUD_RATE */
  91. /* */
  92. /* Arguments: */
  93. /* */
  94. /* Irp - pointer to an I/O Request Packet */
  95. /* PDevObj - pointer to device object */
  96. /* */
  97. /* Return Value: */
  98. /* */
  99. /* NTSTATUS */
  100. /* */
  101. /************************************************************************/
  102. NTSTATUS
  103. SetBaudRate(IN PIRP Irp, IN PDEVICE_OBJECT PDevObj)
  104. {
  105. PSERIAL_BAUD_RATE Br = (PSERIAL_BAUD_RATE) Irp->AssociatedIrp.SystemBuffer;
  106. NTSTATUS NtStatus = STATUS_SUCCESS;
  107. PIO_STACK_LOCATION IrpStack;
  108. KIRQL OldIrql;
  109. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  110. USBSER_ALWAYS_LOCKED_CODE();
  111. DEBUG_LOG_PATH("enter SetBaudRate");
  112. UsbSerSerialDump(USBSERTRACEIOC, (">SetBaudRate(%08X)\n", Irp));
  113. Irp->IoStatus.Information = 0;
  114. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  115. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength
  116. < sizeof(SERIAL_BAUD_RATE)) {
  117. NtStatus = STATUS_BUFFER_TOO_SMALL;
  118. } else {
  119. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  120. DeviceExtension->CurrentBaud = Br->BaudRate;
  121. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  122. DEBUG_TRACE3(("BaudRate (%08X)\n", Br->BaudRate));
  123. NtStatus = SetLineControlAndBaud(PDevObj);
  124. }
  125. DEBUG_LOG_PATH("exit SetBaudRate");
  126. UsbSerSerialDump(USBSERTRACEIOC, ("<SetBaudRate %08X\n", NtStatus));
  127. return NtStatus;
  128. } // SetBaudRate
  129. /************************************************************************/
  130. /* GetBaudRate */
  131. /************************************************************************/
  132. /* */
  133. /* Routine Description: */
  134. /* */
  135. /* Handle IOCTL_SERIAL_GET_BAUD_RATE */
  136. /* */
  137. /* Arguments: */
  138. /* */
  139. /* Irp - pointer to an I/O Request Packet */
  140. /* PDevObj - pointer to device object */
  141. /* */
  142. /* Return Value: */
  143. /* */
  144. /* NTSTATUS */
  145. /* */
  146. /************************************************************************/
  147. NTSTATUS
  148. GetBaudRate(IN PIRP Irp, IN PDEVICE_OBJECT PDevObj)
  149. {
  150. PSERIAL_BAUD_RATE Br = (PSERIAL_BAUD_RATE) Irp->AssociatedIrp.SystemBuffer;
  151. NTSTATUS NtStatus = STATUS_SUCCESS;
  152. KIRQL OldIrql;
  153. PIO_STACK_LOCATION IrpStack;
  154. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  155. USBSER_ALWAYS_LOCKED_CODE();
  156. DEBUG_LOG_PATH("enter GetBaudRate");
  157. UsbSerSerialDump(USBSERTRACEIOC, (">GetBaudRate(%08X)\n", Irp));
  158. Irp->IoStatus.Information = 0;
  159. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  160. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  161. < sizeof(SERIAL_BAUD_RATE)) {
  162. NtStatus = STATUS_BUFFER_TOO_SMALL;
  163. } else {
  164. GetLineControlAndBaud(PDevObj);
  165. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  166. Br->BaudRate = DeviceExtension->CurrentBaud;
  167. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  168. Irp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);
  169. }
  170. DEBUG_LOG_PATH("exit GetBaudRate");
  171. UsbSerSerialDump(USBSERTRACEIOC, ("<GetBaudRate %08X\n", NtStatus));
  172. return NtStatus;
  173. } // GetBaudRate
  174. /************************************************************************/
  175. /* SetLineControl */
  176. /************************************************************************/
  177. /* */
  178. /* Routine Description: */
  179. /* */
  180. /* Handle IOCTL_SERIAL_SET_LINE_CONTROL */
  181. /* */
  182. /* Arguments: */
  183. /* */
  184. /* Irp - pointer to an I/O Request Packet */
  185. /* PDevObj - pointer to device object */
  186. /* */
  187. /* Return Value: */
  188. /* */
  189. /* NTSTATUS */
  190. /* */
  191. /************************************************************************/
  192. NTSTATUS
  193. SetLineControl(IN PIRP Irp, IN PDEVICE_OBJECT PDevObj)
  194. {
  195. PSERIAL_LINE_CONTROL LineControl
  196. = (PSERIAL_LINE_CONTROL) Irp->AssociatedIrp.SystemBuffer;
  197. NTSTATUS NtStatus = STATUS_SUCCESS;
  198. KIRQL OldIrql;
  199. PIO_STACK_LOCATION IrpStack;
  200. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  201. USBSER_ALWAYS_LOCKED_CODE();
  202. DEBUG_LOG_PATH("enter SetLineControl");
  203. UsbSerSerialDump(USBSERTRACEIOC, (">SetLineControl(%08X)\n", Irp));
  204. Irp->IoStatus.Information = 0;
  205. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  206. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength
  207. < sizeof(SERIAL_LINE_CONTROL)) {
  208. NtStatus = STATUS_BUFFER_TOO_SMALL;
  209. } else {
  210. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  211. DeviceExtension->LineControl = *LineControl;
  212. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  213. // set line control for USB modem
  214. NtStatus = SetLineControlAndBaud(PDevObj);
  215. }
  216. DEBUG_LOG_PATH("exit SetLineControl");
  217. UsbSerSerialDump(USBSERTRACEIOC, ("<SetLineControl %08X\n", NtStatus));
  218. return NtStatus;
  219. } // SetLineControl
  220. /************************************************************************/
  221. /* GetLineControl */
  222. /************************************************************************/
  223. /* */
  224. /* Routine Description: */
  225. /* */
  226. /* Handle IOCTL_SERIAL_GET_LINE_CONTROL */
  227. /* */
  228. /* Arguments: */
  229. /* */
  230. /* Irp - pointer to an I/O Request Packet */
  231. /* PDevObj - pointer to device object */
  232. /* */
  233. /* Return Value: */
  234. /* */
  235. /* NTSTATUS */
  236. /* */
  237. /************************************************************************/
  238. NTSTATUS
  239. GetLineControl(IN PIRP Irp, IN PDEVICE_OBJECT PDevObj)
  240. {
  241. PSERIAL_LINE_CONTROL LineControl =
  242. (PSERIAL_LINE_CONTROL) Irp->AssociatedIrp.SystemBuffer;
  243. NTSTATUS NtStatus = STATUS_SUCCESS;
  244. KIRQL OldIrql;
  245. PIO_STACK_LOCATION IrpStack;
  246. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  247. USBSER_ALWAYS_LOCKED_CODE();
  248. DEBUG_LOG_PATH("enter GetLineControl");
  249. UsbSerSerialDump(USBSERTRACEIOC, (">GetLineControl(%08X)\n", Irp));
  250. Irp->IoStatus.Information = 0;
  251. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  252. if(IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  253. < sizeof(SERIAL_LINE_CONTROL))
  254. {
  255. NtStatus = STATUS_BUFFER_TOO_SMALL;
  256. }
  257. else
  258. {
  259. GetLineControlAndBaud(PDevObj);
  260. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  261. *LineControl = DeviceExtension->LineControl;
  262. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  263. Irp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);
  264. }
  265. DEBUG_LOG_PATH("exit GetLineControl");
  266. UsbSerSerialDump(USBSERTRACEIOC, ("<GetLineControl %08X\n", NtStatus));
  267. return NtStatus;
  268. } // GetLineControl
  269. /************************************************************************/
  270. /* SetTimeouts */
  271. /************************************************************************/
  272. /* */
  273. /* Routine Description: */
  274. /* */
  275. /* Handle IOCTL_SERIAL_SET_TIMEOUTS */
  276. /* */
  277. /* Arguments: */
  278. /* */
  279. /* Irp - pointer to an I/O Request Packet */
  280. /* DeviceExtension - pointer to device extension */
  281. /* */
  282. /* Return Value: */
  283. /* */
  284. /* NTSTATUS */
  285. /* */
  286. /************************************************************************/
  287. NTSTATUS
  288. SetTimeouts(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  289. {
  290. PSERIAL_TIMEOUTS Timeouts =
  291. (PSERIAL_TIMEOUTS) Irp->AssociatedIrp.SystemBuffer;
  292. NTSTATUS NtStatus = STATUS_SUCCESS;
  293. KIRQL OldIrql;
  294. PIO_STACK_LOCATION IrpStack;
  295. USBSER_ALWAYS_LOCKED_CODE();
  296. DEBUG_LOG_PATH("enter SetTimeouts");
  297. UsbSerSerialDump(USBSERTRACEIOC | USBSERTRACETM,
  298. (">SetTimeouts(%08X)\n", Irp));
  299. Irp->IoStatus.Information = 0;
  300. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  301. if(IrpStack->Parameters.DeviceIoControl.InputBufferLength
  302. < sizeof(SERIAL_TIMEOUTS))
  303. {
  304. NtStatus = STATUS_BUFFER_TOO_SMALL;
  305. }
  306. else
  307. {
  308. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  309. DeviceExtension->Timeouts = *Timeouts;
  310. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  311. }
  312. DEBUG_LOG_PATH("exit SetTimeouts");
  313. UsbSerSerialDump(USBSERTRACEIOC | USBSERTRACETM, ("<SetTimeouts %08X\n",
  314. NtStatus));
  315. return NtStatus;
  316. } // SetTimeouts
  317. /************************************************************************/
  318. /* GetTimeouts */
  319. /************************************************************************/
  320. /* */
  321. /* Routine Description: */
  322. /* */
  323. /* Handle IOCTL_SERIAL_GET_TIMEOUTS */
  324. /* */
  325. /* Arguments: */
  326. /* */
  327. /* Irp - pointer to an I/O Request Packet */
  328. /* DeviceExtension - pointer to device extension */
  329. /* */
  330. /* Return Value: */
  331. /* */
  332. /* NTSTATUS */
  333. /* */
  334. /************************************************************************/
  335. NTSTATUS
  336. GetTimeouts(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  337. {
  338. PSERIAL_TIMEOUTS Timeouts =
  339. (PSERIAL_TIMEOUTS) Irp->AssociatedIrp.SystemBuffer;
  340. NTSTATUS NtStatus = STATUS_SUCCESS;
  341. KIRQL OldIrql;
  342. PIO_STACK_LOCATION IrpStack;
  343. USBSER_ALWAYS_LOCKED_CODE();
  344. DEBUG_LOG_PATH("enter GetTimeouts");
  345. UsbSerSerialDump(USBSERTRACEIOC | USBSERTRACETM,
  346. (">GetTimeouts(%08X)\n", Irp));
  347. Irp->IoStatus.Information = 0;
  348. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  349. if(IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  350. < sizeof(SERIAL_TIMEOUTS))
  351. {
  352. NtStatus = STATUS_BUFFER_TOO_SMALL;
  353. }
  354. else
  355. {
  356. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  357. *Timeouts = DeviceExtension->Timeouts;
  358. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  359. Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
  360. }
  361. DEBUG_LOG_PATH("exit GetTimeouts");
  362. UsbSerSerialDump(USBSERTRACEIOC | USBSERTRACETM, ("<GetTimeouts %08X\n",
  363. NtStatus));
  364. return NtStatus;
  365. } // GetTimeouts
  366. /************************************************************************/
  367. /* SetChars */
  368. /************************************************************************/
  369. /* */
  370. /* Routine Description: */
  371. /* */
  372. /* Handle IOCTL_SERIAL_SET_CHARS */
  373. /* */
  374. /* Arguments: */
  375. /* */
  376. /* Irp - pointer to an I/O Request Packet */
  377. /* DeviceExtension - pointer to device extension */
  378. /* */
  379. /* Return Value: */
  380. /* */
  381. /* NTSTATUS */
  382. /* */
  383. /************************************************************************/
  384. NTSTATUS
  385. SetChars(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  386. {
  387. PSERIAL_CHARS SpecialChars =
  388. (PSERIAL_CHARS) Irp->AssociatedIrp.SystemBuffer;
  389. NTSTATUS NtStatus = STATUS_SUCCESS;
  390. KIRQL OldIrql;
  391. PIO_STACK_LOCATION IrpStack;
  392. USBSER_ALWAYS_LOCKED_CODE();
  393. DEBUG_LOG_PATH("enter SetChars");
  394. UsbSerSerialDump(USBSERTRACEIOC, (">SetChars(%08X)\n", Irp));
  395. Irp->IoStatus.Information = 0;
  396. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  397. if(IrpStack->Parameters.DeviceIoControl.InputBufferLength
  398. < sizeof(SERIAL_CHARS))
  399. {
  400. NtStatus = STATUS_BUFFER_TOO_SMALL;
  401. }
  402. else
  403. {
  404. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  405. DeviceExtension->SpecialChars = *SpecialChars;
  406. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  407. }
  408. DEBUG_LOG_PATH("exit SetChars");
  409. UsbSerSerialDump(USBSERTRACEIOC, ("<SetChars %08X\n"));
  410. return NtStatus;
  411. } // SetChars
  412. /************************************************************************/
  413. /* GetChars */
  414. /************************************************************************/
  415. /* */
  416. /* Routine Description: */
  417. /* */
  418. /* Handle IOCTL_SERIAL_GET_CHARS */
  419. /* */
  420. /* Arguments: */
  421. /* */
  422. /* Irp - pointer to an I/O Request Packet */
  423. /* DeviceExtension - pointer to device extension */
  424. /* */
  425. /* Return Value: */
  426. /* */
  427. /* NTSTATUS */
  428. /* */
  429. /************************************************************************/
  430. NTSTATUS
  431. GetChars(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  432. {
  433. PSERIAL_CHARS SpecialChars =
  434. (PSERIAL_CHARS) Irp->AssociatedIrp.SystemBuffer;
  435. NTSTATUS NtStatus = STATUS_SUCCESS;
  436. KIRQL OldIrql;
  437. PIO_STACK_LOCATION IrpStack;
  438. USBSER_ALWAYS_LOCKED_CODE();
  439. DEBUG_LOG_PATH("enter GetChars");
  440. UsbSerSerialDump(USBSERTRACEIOC, (">GetChars(%08X)\n", Irp));
  441. Irp->IoStatus.Information = 0;
  442. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  443. if(IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  444. < sizeof(SERIAL_CHARS))
  445. {
  446. NtStatus = STATUS_BUFFER_TOO_SMALL;
  447. }
  448. else
  449. {
  450. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  451. *SpecialChars = DeviceExtension->SpecialChars;
  452. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  453. Irp->IoStatus.Information = sizeof(SERIAL_CHARS);
  454. }
  455. DEBUG_LOG_PATH("exit GetChars");
  456. UsbSerSerialDump(USBSERTRACEIOC, ("<GetChars %08X\n", NtStatus));
  457. return NtStatus;
  458. } // GetChars
  459. /************************************************************************/
  460. /* SetClrDtr */
  461. /************************************************************************/
  462. /* */
  463. /* Routine Description: */
  464. /* */
  465. /* Handle IOCTL_SERIAL_SET_DTR and IOCTL_SERIAL_CLR_DTR */
  466. /* */
  467. /* Arguments: */
  468. /* */
  469. /* PDevObj - pointer to device object */
  470. /* Set - TRUE if setting DTR, FALSE if clearing DTR */
  471. /* */
  472. /* Return Value: */
  473. /* */
  474. /* NTSTATUS */
  475. /* */
  476. /************************************************************************/
  477. NTSTATUS
  478. SetClrDtr(IN PDEVICE_OBJECT PDevObj, IN BOOLEAN Set)
  479. {
  480. NTSTATUS NtStatus = STATUS_SUCCESS;
  481. KIRQL OldIrql;
  482. USHORT State = 0;
  483. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  484. USBSER_ALWAYS_LOCKED_CODE();
  485. DEBUG_LOG_PATH("enter SetClrDtr");
  486. UsbSerSerialDump(USBSERTRACEIOC, (">SetClrDtr\n"));
  487. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  488. if(DeviceExtension->DTRRTSState & SERIAL_RTS_STATE)
  489. State |= USB_COMM_RTS;
  490. if (Set) {
  491. DeviceExtension->DTRRTSState |= SERIAL_DTR_STATE;
  492. State |= USB_COMM_DTR;
  493. } else {
  494. DeviceExtension->DTRRTSState &= ~SERIAL_DTR_STATE;
  495. }
  496. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  497. if(DeviceExtension->DTRRTSState & SERIAL_RTS_STATE)
  498. State |= USB_COMM_RTS;
  499. NtStatus = ClassVendorCommand(PDevObj, USB_COMM_SET_CONTROL_LINE_STATE,
  500. State, DeviceExtension->CommInterface,
  501. NULL, NULL, FALSE, USBSER_CLASS_COMMAND);
  502. if(!NT_SUCCESS(NtStatus)) {
  503. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  504. DeviceExtension->DTRRTSState &= ~SERIAL_DTR_STATE;
  505. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  506. }
  507. DEBUG_LOG_PATH("exit SetClrDtr");
  508. UsbSerSerialDump(USBSERTRACEIOC, ("<SetClrDtr %08X\n", NtStatus));
  509. return NtStatus;
  510. } // SetClrDtr
  511. /************************************************************************/
  512. /* ResetDevice */
  513. /************************************************************************/
  514. /* */
  515. /* Routine Description: */
  516. /* */
  517. /* Handle IOCTL_SERIAL_RESET_DEVICE */
  518. /* */
  519. /* Arguments: */
  520. /* */
  521. /* Irp - pointer to an I/O Request Packet */
  522. /* PDevObj - pointer to device object */
  523. /* */
  524. /* Return Value: */
  525. /* */
  526. /* NTSTATUS */
  527. /* */
  528. /************************************************************************/
  529. NTSTATUS
  530. ResetDevice(IN PIRP Irp, IN PDEVICE_OBJECT PDevObj)
  531. {
  532. NTSTATUS NtStatus = STATUS_SUCCESS;
  533. KIRQL OldIrql;
  534. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  535. USBSER_ALWAYS_LOCKED_CODE();
  536. DEBUG_LOG_PATH("enter ResetDevice");
  537. UsbSerSerialDump(USBSERTRACEIOC, (">ResetDevice(%08X)\n", Irp));
  538. // get line control and baud rate info
  539. GetLineControlAndBaud(PDevObj);
  540. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  541. // do device extension device specific stuff here
  542. DeviceExtension->SupportedBauds = SERIAL_BAUD_300 | SERIAL_BAUD_600
  543. | SERIAL_BAUD_1200 | SERIAL_BAUD_2400 | SERIAL_BAUD_4800
  544. | SERIAL_BAUD_9600 | SERIAL_BAUD_19200 | SERIAL_BAUD_38400
  545. | SERIAL_BAUD_57600 | SERIAL_BAUD_115200;
  546. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  547. DEBUG_LOG_PATH("exit ResetDevice");
  548. UsbSerSerialDump(USBSERTRACEIOC, ("<ResetDevice %08X\n"));
  549. return NtStatus;
  550. } // ResetDevice
  551. /************************************************************************/
  552. /* SetRts */
  553. /************************************************************************/
  554. /* */
  555. /* Routine Description: */
  556. /* */
  557. /* Handle IOCTL_SERIAL_SET_RTS */
  558. /* */
  559. /* Arguments: */
  560. /* */
  561. /* Irp - pointer to an I/O Request Packet */
  562. /* DeviceExtension - pointer to device extension */
  563. /* */
  564. /* Return Value: */
  565. /* */
  566. /* NTSTATUS */
  567. /* */
  568. /************************************************************************/
  569. NTSTATUS
  570. SetRts(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  571. {
  572. NTSTATUS NtStatus = STATUS_SUCCESS;
  573. KIRQL OldIrql;
  574. USHORT State = 0;
  575. USBSER_ALWAYS_LOCKED_CODE();
  576. DEBUG_LOG_PATH("enter SetRts");
  577. UsbSerSerialDump(USBSERTRACEIOC, (">SetRts(%08X)\n", Irp));
  578. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  579. DeviceExtension->DTRRTSState |= SERIAL_RTS_STATE;
  580. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  581. DEBUG_LOG_PATH("exit SetRts");
  582. UsbSerSerialDump(USBSERTRACEIOC, ("<SetRts %08X\n", NtStatus));
  583. return NtStatus;
  584. } // SetRts
  585. /************************************************************************/
  586. /* ClrRts */
  587. /************************************************************************/
  588. /* */
  589. /* Routine Description: */
  590. /* */
  591. /* Handle IOCTL_SERIAL_CLR_RTS */
  592. /* */
  593. /* Arguments: */
  594. /* */
  595. /* Irp - pointer to an I/O Request Packet */
  596. /* DeviceExtension - pointer to device extension */
  597. /* */
  598. /* Return Value: */
  599. /* */
  600. /* NTSTATUS */
  601. /* */
  602. /************************************************************************/
  603. NTSTATUS
  604. ClrRts(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  605. {
  606. NTSTATUS NtStatus = STATUS_SUCCESS;
  607. KIRQL OldIrql;
  608. USHORT State = 0;
  609. USBSER_ALWAYS_LOCKED_CODE();
  610. DEBUG_LOG_PATH("enter ClrRts");
  611. UsbSerSerialDump(USBSERTRACEIOC, (">ClrRts(%08X)\n", Irp));
  612. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  613. DeviceExtension->DTRRTSState &= ~SERIAL_RTS_STATE;
  614. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  615. DEBUG_LOG_PATH("exit ClrRts");
  616. UsbSerSerialDump(USBSERTRACEIOC, ("<ClrRts %08X\n", NtStatus));
  617. return NtStatus;
  618. } // ClrRts
  619. /************************************************************************/
  620. /* SetBreak */
  621. /************************************************************************/
  622. /* */
  623. /* Routine Description: */
  624. /* */
  625. /* Handle IOCTL_SERIAL_SET_BREAK_ON & IOCTL_SERIAL_SET_BREAK_OFF */
  626. /* */
  627. /* Arguments: */
  628. /* */
  629. /* Irp - pointer to an I/O Request Packet */
  630. /* PDevObj - pointer to device object */
  631. /* Time - time to assert break in ms */
  632. /* (0xFFFF - on / 0x0000 - off) */
  633. /* */
  634. /* Return Value: */
  635. /* */
  636. /* NTSTATUS */
  637. /* */
  638. /************************************************************************/
  639. NTSTATUS
  640. SetBreak(IN PIRP Irp, IN PDEVICE_OBJECT PDevObj, USHORT Time)
  641. {
  642. NTSTATUS NtStatus = STATUS_SUCCESS;
  643. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  644. USBSER_LOCKED_PAGED_CODE();
  645. DEBUG_LOG_PATH("enter SetBreak");
  646. UsbSerSerialDump(USBSERTRACEIOC, (">SetBreak(%08X)\n", Irp));
  647. NtStatus = ClassVendorCommand(PDevObj, USB_COMM_SEND_BREAK, Time,
  648. DeviceExtension->CommInterface, NULL,
  649. NULL, FALSE, USBSER_CLASS_COMMAND);
  650. DEBUG_LOG_PATH("exit SetBreak");
  651. UsbSerSerialDump(USBSERTRACEIOC, ("<SetBreak %08X\n", NtStatus));
  652. return NtStatus;
  653. } // SetBreak
  654. /************************************************************************/
  655. /* SetQueueSize */
  656. /************************************************************************/
  657. /* */
  658. /* Routine Description: */
  659. /* */
  660. /* Handle IOCTL_SERIAL_SET_QUEUE_SIZE */
  661. /* */
  662. /* Arguments: */
  663. /* */
  664. /* Irp - pointer to an I/O Request Packet */
  665. /* DeviceExtension - pointer to device extension */
  666. /* */
  667. /* Return Value: */
  668. /* */
  669. /* NTSTATUS */
  670. /* */
  671. /************************************************************************/
  672. NTSTATUS
  673. SetQueueSize(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  674. {
  675. NTSTATUS NtStatus = STATUS_SUCCESS;
  676. PIO_STACK_LOCATION IrpStack;
  677. PULONG QueueSize = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  678. DEBUG_LOG_PATH("enter SetQueueSize");
  679. UsbSerSerialDump(USBSERTRACEIOC, (">SetQueueSize(%08X)\n", Irp));
  680. USBSER_LOCKED_PAGED_CODE();
  681. Irp->IoStatus.Information = 0;
  682. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  683. if(IrpStack->Parameters.DeviceIoControl.InputBufferLength
  684. < sizeof(ULONG))
  685. {
  686. NtStatus = STATUS_BUFFER_TOO_SMALL;
  687. }
  688. else
  689. {
  690. DEBUG_TRACE1(("SetQueueSize (%08X)\n", *QueueSize));
  691. // we will go ahead and save this, but we don't care.
  692. // DeviceExtension->RxQueueSize = *QueueSize;
  693. }
  694. DEBUG_LOG_PATH("exit SetQueueSize");
  695. UsbSerSerialDump(USBSERTRACEIOC, ("<SetQueueSize %08X\n", NtStatus));
  696. return NtStatus;
  697. } // SetQueueSize
  698. /************************************************************************/
  699. /* GetWaitMask */
  700. /************************************************************************/
  701. /* */
  702. /* Routine Description: */
  703. /* */
  704. /* Handle IOCTL_SERIAL_GET_WAIT_MASK */
  705. /* */
  706. /* Arguments: */
  707. /* */
  708. /* Irp - pointer to an I/O Request Packet */
  709. /* DeviceExtension - pointer to device extension */
  710. /* */
  711. /* Return Value: */
  712. /* */
  713. /* NTSTATUS */
  714. /* */
  715. /************************************************************************/
  716. NTSTATUS
  717. GetWaitMask(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  718. {
  719. PULONG WaitMask = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  720. NTSTATUS NtStatus = STATUS_SUCCESS;
  721. KIRQL OldIrql;
  722. PIO_STACK_LOCATION IrpStack;
  723. USBSER_ALWAYS_LOCKED_CODE();
  724. DEBUG_LOG_PATH("enter GetWaitMask");
  725. UsbSerSerialDump(USBSERTRACEIOC, (">GetWaitMask(%08X)\n", Irp));
  726. Irp->IoStatus.Information = 0;
  727. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  728. if(IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  729. < sizeof(ULONG))
  730. {
  731. NtStatus = STATUS_BUFFER_TOO_SMALL;
  732. }
  733. else
  734. {
  735. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  736. *WaitMask = DeviceExtension->IsrWaitMask;
  737. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  738. Irp->IoStatus.Information = sizeof(ULONG);
  739. }
  740. DEBUG_LOG_PATH("exit GetWaitMask");
  741. UsbSerSerialDump(USBSERTRACEIOC, ("<GetWaitMask %08X\n"));
  742. return NtStatus;
  743. } // GetWaitMask
  744. /************************************************************************/
  745. /* SetWaitMask */
  746. /************************************************************************/
  747. /* */
  748. /* Routine Description: */
  749. /* */
  750. /* Handle IOCTL_SERIAL_SET_WAIT_MASK */
  751. /* */
  752. /* Arguments: */
  753. /* */
  754. /* Irp - pointer to an I/O Request Packet */
  755. /* DeviceExtension - pointer to device extension */
  756. /* */
  757. /* Return Value: */
  758. /* */
  759. /* NTSTATUS */
  760. /* */
  761. /************************************************************************/
  762. NTSTATUS
  763. SetWaitMask(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  764. {
  765. PULONG WaitMask = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  766. NTSTATUS NtStatus = STATUS_SUCCESS;
  767. KIRQL OldIrql;
  768. PIO_STACK_LOCATION IrpStack;
  769. USBSER_ALWAYS_LOCKED_CODE();
  770. DEBUG_LOG_PATH("enter SetWaitMask");
  771. UsbSerSerialDump(USBSERTRACEIOC, (">SetWaitMask(%08X)\n", Irp));
  772. Irp->IoStatus.Information = 0;
  773. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  774. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) {
  775. NtStatus = STATUS_BUFFER_TOO_SMALL;
  776. } else {
  777. // make sure it's a valid request
  778. if (*WaitMask & ~( SERIAL_EV_RXCHAR |
  779. SERIAL_EV_RXFLAG |
  780. SERIAL_EV_TXEMPTY |
  781. SERIAL_EV_CTS |
  782. SERIAL_EV_DSR |
  783. SERIAL_EV_RLSD |
  784. SERIAL_EV_BREAK |
  785. SERIAL_EV_ERR |
  786. SERIAL_EV_RING |
  787. SERIAL_EV_PERR |
  788. SERIAL_EV_RX80FULL |
  789. SERIAL_EV_EVENT1 |
  790. SERIAL_EV_EVENT2)) {
  791. NtStatus = STATUS_INVALID_PARAMETER;
  792. } else {
  793. UsbSerCompletePendingWaitMasks(DeviceExtension);
  794. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  795. DeviceExtension->HistoryMask = 0;
  796. DeviceExtension->IsrWaitMask = *WaitMask;
  797. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  798. DEBUG_TRACE3(("SetWaitMask (%08X)\n", *WaitMask));
  799. }
  800. }
  801. DEBUG_LOG_PATH("exit SetWaitMask");
  802. UsbSerSerialDump(USBSERTRACEIOC, ("<SetWaitMask %08X\n", NtStatus));
  803. return NtStatus;
  804. } // SetWaitMask
  805. /************************************************************************/
  806. /* WaitOnMask */
  807. /************************************************************************/
  808. /* */
  809. /* Routine Description: */
  810. /* */
  811. /* Handle IOCTL_SERIAL_WAIT_ON_MASK */
  812. /* */
  813. /* Arguments: */
  814. /* */
  815. /* Irp - pointer to an I/O Request Packet */
  816. /* DeviceExtension - pointer to device extension */
  817. /* */
  818. /* Return Value: */
  819. /* */
  820. /* NTSTATUS */
  821. /* */
  822. /************************************************************************/
  823. NTSTATUS
  824. WaitOnMask(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  825. {
  826. PULONG WaitMask = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  827. NTSTATUS NtStatus = STATUS_SUCCESS;
  828. KIRQL OldIrql;
  829. PIO_STACK_LOCATION IrpStack;
  830. USBSER_ALWAYS_LOCKED_CODE();
  831. DEBUG_LOG_PATH("enter WaitOnMask");
  832. UsbSerSerialDump(USBSERTRACEIOC, (">WaitOnMask(%08X)\n", Irp));
  833. Irp->IoStatus.Information = 0;
  834. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  835. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  836. < sizeof(ULONG)) {
  837. NtStatus = STATUS_BUFFER_TOO_SMALL;
  838. } else {
  839. // if we have an event to report, just go ahead and return it
  840. if (DeviceExtension->HistoryMask) {
  841. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  842. *WaitMask = DeviceExtension->HistoryMask;
  843. DeviceExtension->HistoryMask = 0;
  844. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  845. Irp->IoStatus.Information = sizeof(ULONG);
  846. UsbSerSerialDump(USBSERCOMPEV,
  847. ("Completing maskirp(3) %08x\n",
  848. *WaitMask));
  849. DEBUG_TRACE3(("Signal Event (%08X)\n", *WaitMask));
  850. } else {
  851. KIRQL cancelIrql;
  852. ACQUIRE_CANCEL_SPINLOCK(DeviceExtension, &cancelIrql);
  853. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  854. // just in case something comes in, we'll do a while loop
  855. while (DeviceExtension->CurrentMaskIrp) {
  856. PIRP pOldIrp;
  857. DEBUG_TRACE3(("Completing previous mask\n"));
  858. pOldIrp = DeviceExtension->CurrentMaskIrp;
  859. DeviceExtension->CurrentMaskIrp = NULL;
  860. pOldIrp->IoStatus.Status = STATUS_SUCCESS;
  861. IoSetCancelRoutine(pOldIrp, NULL);
  862. *WaitMask = 0;
  863. UsbSerSerialDump(USBSERCOMPEV,
  864. ("Completing maskirp(4)\n"));
  865. //
  866. // Release locks, complete request, then
  867. // reacquire the locks
  868. //
  869. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock,
  870. OldIrql);
  871. RELEASE_CANCEL_SPINLOCK(DeviceExtension, cancelIrql);
  872. IoCompleteRequest(pOldIrp, IO_SERIAL_INCREMENT);
  873. ACQUIRE_CANCEL_SPINLOCK(DeviceExtension, &cancelIrql);
  874. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock,
  875. &OldIrql);
  876. }
  877. //
  878. // Check to see if it needs to be cancelled
  879. //
  880. if (Irp->Cancel) {
  881. Irp->IoStatus.Status = STATUS_CANCELLED;
  882. Irp->IoStatus.Information = 0;
  883. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  884. RELEASE_CANCEL_SPINLOCK(DeviceExtension, cancelIrql);
  885. } else {
  886. IoSetCancelRoutine(Irp, UsbSerCancelWaitOnMask);
  887. NtStatus = Irp->IoStatus.Status = STATUS_PENDING;
  888. DeviceExtension->CurrentMaskIrp = Irp;
  889. IoMarkIrpPending(Irp);
  890. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  891. RELEASE_CANCEL_SPINLOCK(DeviceExtension, cancelIrql);
  892. }
  893. }
  894. }
  895. DEBUG_LOG_PATH("exit WaitOnMask");
  896. UsbSerSerialDump(USBSERTRACEIOC, ("<WaitOnMask %08X\n", NtStatus));
  897. return NtStatus;
  898. } // WaitOnMask
  899. /************************************************************************/
  900. /* ImmediateChar */
  901. /************************************************************************/
  902. /* */
  903. /* Routine Description: */
  904. /* */
  905. /* Handle IOCTL_SERIAL_IMMEDIATE_CHAR */
  906. /* */
  907. /* Arguments: */
  908. /* */
  909. /* Irp - pointer to an I/O Request Packet */
  910. /* DeviceObject - pointer to device object */
  911. /* */
  912. /* Return Value: */
  913. /* */
  914. /* NTSTATUS */
  915. /* */
  916. /************************************************************************/
  917. NTSTATUS
  918. ImmediateChar(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
  919. {
  920. PUCHAR Char = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
  921. NTSTATUS NtStatus = STATUS_SUCCESS;
  922. PIO_STACK_LOCATION IrpStack;
  923. USBSER_LOCKED_PAGED_CODE();
  924. DEBUG_LOG_PATH("enter ImmediateChar");
  925. UsbSerSerialDump(USBSERTRACEIOC, (">ImmediateChar(%08X)\n", Irp));
  926. Irp->IoStatus.Information = 0;
  927. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  928. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(UCHAR)) {
  929. NtStatus = STATUS_BUFFER_TOO_SMALL;
  930. } else {
  931. //
  932. // We just treat this as a write since we have no internal
  933. // data buffer.
  934. //
  935. IrpStack->Parameters.Write.Length = sizeof(UCHAR);
  936. NtStatus = UsbSer_Write(DeviceObject, Irp);
  937. }
  938. DEBUG_LOG_PATH("exit ImmediateChar");
  939. UsbSerSerialDump(USBSERTRACEIOC, ("<ImmediateChar, %08X\n", NtStatus));
  940. return NtStatus;
  941. } // ImmediateChar
  942. /************************************************************************/
  943. /* Purge */
  944. /************************************************************************/
  945. /* */
  946. /* Routine Description: */
  947. /* */
  948. /* Handle IOCTL_SERIAL_PURGE */
  949. /* */
  950. /* Arguments: */
  951. /* */
  952. /* Irp - pointer to an I/O Request Packet */
  953. /* DeviceExtension - pointer to device extension */
  954. /* */
  955. /* Return Value: */
  956. /* */
  957. /* NTSTATUS */
  958. /* */
  959. /************************************************************************/
  960. NTSTATUS
  961. Purge(IN PDEVICE_OBJECT PDevObj, IN PIRP Irp,
  962. IN PDEVICE_EXTENSION DeviceExtension)
  963. {
  964. ULONG Mask = *((PULONG) Irp->AssociatedIrp.SystemBuffer);
  965. NTSTATUS NtStatus = STATUS_SUCCESS;
  966. PIO_STACK_LOCATION IrpStack;
  967. KIRQL OldIrql;
  968. ULONG Count;
  969. USBSER_ALWAYS_LOCKED_CODE();
  970. DEBUG_LOG_PATH("enter Purge");
  971. UsbSerSerialDump(USBSERTRACEIOC, (">Purge(%08X)\n", Irp));
  972. Irp->IoStatus.Information = 0;
  973. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  974. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) {
  975. NtStatus = STATUS_BUFFER_TOO_SMALL;
  976. } else {
  977. // make sure purge request is valid
  978. if ((!Mask) || (Mask & ( ~( SERIAL_PURGE_TXABORT |
  979. SERIAL_PURGE_RXABORT |
  980. SERIAL_PURGE_TXCLEAR |
  981. SERIAL_PURGE_RXCLEAR)))) {
  982. NtStatus = STATUS_INVALID_PARAMETER;
  983. } else {
  984. if (Mask & SERIAL_PURGE_RXCLEAR) {
  985. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  986. Count = DeviceExtension->CharsInReadBuff;
  987. DeviceExtension->CharsInReadBuff = 0;
  988. DeviceExtension->CurrentReadBuffPtr = 0;
  989. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  990. if(Count)
  991. {
  992. RestartRead(DeviceExtension);
  993. }
  994. }
  995. if (Mask & SERIAL_PURGE_RXABORT) {
  996. UsbSerKillAllReadsOrWrites(PDevObj, &DeviceExtension->ReadQueue,
  997. &DeviceExtension->CurrentReadIrp);
  998. }
  999. if (Mask & SERIAL_PURGE_TXABORT) {
  1000. //
  1001. // DO NOTHING because USB owns the request. However, it may
  1002. // prove in practice that we will have to cancel the IRPs on behalf
  1003. // of the caller.
  1004. }
  1005. }
  1006. }
  1007. DEBUG_LOG_PATH("exit Purge");
  1008. UsbSerSerialDump(USBSERTRACEIOC, ("<Purge %08X\n", NtStatus));
  1009. return NtStatus;
  1010. } // Purge
  1011. /************************************************************************/
  1012. /* GetHandflow */
  1013. /************************************************************************/
  1014. /* */
  1015. /* Routine Description: */
  1016. /* */
  1017. /* Handle IOCTL_SERIAL_GET_HANDFLOW */
  1018. /* */
  1019. /* Arguments: */
  1020. /* */
  1021. /* Irp - pointer to an I/O Request Packet */
  1022. /* DeviceExtension - pointer to device extension */
  1023. /* */
  1024. /* Return Value: */
  1025. /* */
  1026. /* NTSTATUS */
  1027. /* */
  1028. /************************************************************************/
  1029. NTSTATUS
  1030. GetHandflow(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1031. {
  1032. PSERIAL_HANDFLOW HandFlow
  1033. = (PSERIAL_HANDFLOW) Irp->AssociatedIrp.SystemBuffer;
  1034. NTSTATUS NtStatus = STATUS_SUCCESS;
  1035. KIRQL OldIrql;
  1036. PIO_STACK_LOCATION IrpStack;
  1037. USBSER_ALWAYS_LOCKED_CODE();
  1038. DEBUG_LOG_PATH("enter GetHandflow");
  1039. UsbSerSerialDump(USBSERTRACEIOC, (">GetHandFlow(%08X)\n", Irp));
  1040. Irp->IoStatus.Information = 0;
  1041. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1042. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  1043. < sizeof(SERIAL_HANDFLOW)) {
  1044. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1045. } else {
  1046. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1047. *HandFlow = DeviceExtension->HandFlow;
  1048. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1049. Irp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
  1050. }
  1051. DEBUG_LOG_PATH("exit GetHandflow");
  1052. UsbSerSerialDump(USBSERTRACEIOC, ("<GetHandFlow %08X\n", NtStatus));
  1053. return NtStatus;
  1054. } // GetHandflow
  1055. /************************************************************************/
  1056. /* SetHandflow */
  1057. /************************************************************************/
  1058. /* */
  1059. /* Routine Description: */
  1060. /* */
  1061. /* Handle IOCTL_SERIAL_SET_HANDFLOW */
  1062. /* */
  1063. /* Arguments: */
  1064. /* */
  1065. /* Irp - pointer to an I/O Request Packet */
  1066. /* DeviceExtension - pointer to device extension */
  1067. /* */
  1068. /* Return Value: */
  1069. /* */
  1070. /* NTSTATUS */
  1071. /* */
  1072. /************************************************************************/
  1073. NTSTATUS
  1074. SetHandflow(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1075. {
  1076. PSERIAL_HANDFLOW HandFlow
  1077. = (PSERIAL_HANDFLOW) Irp->AssociatedIrp.SystemBuffer;
  1078. NTSTATUS NtStatus = STATUS_SUCCESS;
  1079. KIRQL OldIrql;
  1080. PIO_STACK_LOCATION IrpStack;
  1081. USBSER_ALWAYS_LOCKED_CODE();
  1082. DEBUG_LOG_PATH("enter SetHandflow");
  1083. UsbSerSerialDump(USBSERTRACEIOC, (">SetHandFlow(%08X)\n", Irp));
  1084. Irp->IoStatus.Information = 0;
  1085. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1086. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength
  1087. < sizeof(SERIAL_HANDFLOW)) {
  1088. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1089. } else {
  1090. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1091. DeviceExtension->HandFlow = *HandFlow;
  1092. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1093. DEBUG_TRACE3(("ControlHandShake (%08X)\n",
  1094. DeviceExtension->HandFlow.ControlHandShake));
  1095. }
  1096. DEBUG_LOG_PATH("exit SetHandflow");
  1097. UsbSerSerialDump(USBSERTRACEIOC, ("<SetHandFlow %08X\n", NtStatus));
  1098. return NtStatus;
  1099. } // SetHandflow
  1100. /************************************************************************/
  1101. /* GetModemStatus */
  1102. /************************************************************************/
  1103. /* */
  1104. /* Routine Description: */
  1105. /* */
  1106. /* Handle IOCTL_SERIAL_GET_MODEMSTATUS */
  1107. /* */
  1108. /* Arguments: */
  1109. /* */
  1110. /* Irp - pointer to an I/O Request Packet */
  1111. /* DeviceExtension - pointer to device extension */
  1112. /* */
  1113. /* Return Value: */
  1114. /* */
  1115. /* NTSTATUS */
  1116. /* */
  1117. /************************************************************************/
  1118. NTSTATUS
  1119. GetModemStatus(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1120. {
  1121. PULONG ModemStatus = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  1122. NTSTATUS NtStatus = STATUS_SUCCESS;
  1123. PIO_STACK_LOCATION IrpStack;
  1124. KIRQL OldIrql;
  1125. USBSER_ALWAYS_LOCKED_CODE();
  1126. DEBUG_LOG_PATH("enter GetModemStatus");
  1127. UsbSerSerialDump(USBSERTRACEIOC, (">GetModemStatus(%08X)\n", Irp));
  1128. Irp->IoStatus.Information = 0;
  1129. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1130. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  1131. < sizeof(ULONG)) {
  1132. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1133. } else {
  1134. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1135. *ModemStatus = DeviceExtension->FakeModemStatus;
  1136. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1137. Irp->IoStatus.Information = sizeof(ULONG);
  1138. DEBUG_TRACE3(("ModemStatus (%08X)\n", *ModemStatus));
  1139. }
  1140. DEBUG_LOG_PATH("exit GetModemStatus");
  1141. UsbSerSerialDump(USBSERTRACEIOC, ("<GetModemStatus %08X\n", NtStatus));
  1142. return NtStatus;
  1143. } // GetModemStatus
  1144. /************************************************************************/
  1145. /* GetDtrRts */
  1146. /************************************************************************/
  1147. /* */
  1148. /* Routine Description: */
  1149. /* */
  1150. /* Handle IOCTL_SERIAL_GET_DTRRTS */
  1151. /* */
  1152. /* Arguments: */
  1153. /* */
  1154. /* Irp - pointer to an I/O Request Packet */
  1155. /* DeviceExtension - pointer to device extension */
  1156. /* */
  1157. /* Return Value: */
  1158. /* */
  1159. /* NTSTATUS */
  1160. /* */
  1161. /************************************************************************/
  1162. NTSTATUS
  1163. GetDtrRts(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1164. {
  1165. PULONG ModemControl = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  1166. NTSTATUS NtStatus = STATUS_SUCCESS;
  1167. PIO_STACK_LOCATION IrpStack;
  1168. KIRQL OldIrql;
  1169. USBSER_ALWAYS_LOCKED_CODE();
  1170. DEBUG_LOG_PATH("enter GetDtrRts");
  1171. UsbSerSerialDump(USBSERTRACEIOC, (">GetDtrRts(%08X)\n", Irp));
  1172. Irp->IoStatus.Information = 0;
  1173. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1174. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  1175. < sizeof(ULONG)) {
  1176. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1177. } else {
  1178. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1179. *ModemControl = DeviceExtension->DTRRTSState;
  1180. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1181. Irp->IoStatus.Information = sizeof(ULONG);
  1182. }
  1183. DEBUG_LOG_PATH("exit GetDtrRts");
  1184. UsbSerSerialDump(USBSERTRACEIOC, ("<GetDtrRts %08X\n", NtStatus));
  1185. return NtStatus;
  1186. } // GetDtrRts
  1187. /************************************************************************/
  1188. /* GetCommStatus */
  1189. /************************************************************************/
  1190. /* */
  1191. /* Routine Description: */
  1192. /* */
  1193. /* Handle IOCTL_SERIAL_GET_COMMSTATUS */
  1194. /* */
  1195. /* Arguments: */
  1196. /* */
  1197. /* Irp - pointer to an I/O Request Packet */
  1198. /* DeviceExtension - pointer to device extension */
  1199. /* */
  1200. /* Return Value: */
  1201. /* */
  1202. /* NTSTATUS */
  1203. /* */
  1204. /************************************************************************/
  1205. NTSTATUS
  1206. GetCommStatus(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1207. {
  1208. PSERIAL_STATUS SerialStatus
  1209. = (PSERIAL_STATUS) Irp->AssociatedIrp.SystemBuffer;
  1210. NTSTATUS NtStatus = STATUS_SUCCESS;
  1211. KIRQL OldIrql;
  1212. PIO_STACK_LOCATION IrpStack;
  1213. USBSER_ALWAYS_LOCKED_CODE();
  1214. DEBUG_LOG_PATH("enter GetCommStatus");
  1215. UsbSerSerialDump(USBSERTRACEIOC, (">GetCommStatus(%08X)\n", Irp));
  1216. Irp->IoStatus.Information = 0;
  1217. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1218. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  1219. < sizeof(SERIAL_STATUS)) {
  1220. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1221. } else {
  1222. if (NT_SUCCESS(NtStatus)) {
  1223. RtlZeroMemory(SerialStatus, sizeof(SERIAL_STATUS));
  1224. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1225. SerialStatus->AmountInInQueue = DeviceExtension->CharsInReadBuff;
  1226. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1227. DEBUG_TRACE2(("AmountInInQueue (%08X)\n", SerialStatus->AmountInInQueue));
  1228. SerialStatus->Errors = 0;
  1229. SerialStatus->EofReceived = FALSE;
  1230. SerialStatus->AmountInOutQueue = 0;
  1231. SerialStatus->WaitForImmediate = 0;
  1232. SerialStatus->HoldReasons = 0;
  1233. Irp->IoStatus.Information = sizeof(SERIAL_STATUS);
  1234. }
  1235. }
  1236. DEBUG_LOG_PATH("exit GetCommStatus");
  1237. UsbSerSerialDump(USBSERTRACEIOC, ("<GetCommStatus %08X\n", NtStatus));
  1238. return NtStatus;
  1239. } // GetCommStatus
  1240. /************************************************************************/
  1241. /* GetProperties */
  1242. /************************************************************************/
  1243. /* */
  1244. /* Routine Description: */
  1245. /* */
  1246. /* Handle IOCTL_SERIAL_GET_PROPERTIES */
  1247. /* */
  1248. /* Arguments: */
  1249. /* */
  1250. /* Irp - pointer to an I/O Request Packet */
  1251. /* DeviceExtension - pointer to device extension */
  1252. /* */
  1253. /* Return Value: */
  1254. /* */
  1255. /* NTSTATUS */
  1256. /* */
  1257. /************************************************************************/
  1258. NTSTATUS
  1259. GetProperties(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1260. {
  1261. NTSTATUS NtStatus = STATUS_SUCCESS;
  1262. PIO_STACK_LOCATION IrpStack;
  1263. USBSER_LOCKED_PAGED_CODE();
  1264. DEBUG_LOG_PATH("enter GetProperties");
  1265. UsbSerSerialDump(USBSERTRACEIOC, (">GetProperties(%08X)\n", Irp));
  1266. Irp->IoStatus.Information = 0;
  1267. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1268. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  1269. < sizeof(SERIAL_COMMPROP)) {
  1270. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1271. } else {
  1272. SerialGetProperties(DeviceExtension,
  1273. (PSERIAL_COMMPROP)Irp->AssociatedIrp.SystemBuffer);
  1274. Irp->IoStatus.Information = sizeof(SERIAL_COMMPROP);
  1275. }
  1276. DEBUG_LOG_PATH("exit GetProperties");
  1277. UsbSerSerialDump(USBSERTRACEIOC, ("<GetProperties %08X\n", NtStatus));
  1278. return NtStatus;
  1279. } // GetProperties
  1280. /************************************************************************/
  1281. /* LsrmstInsert */
  1282. /************************************************************************/
  1283. /* */
  1284. /* Routine Description: */
  1285. /* */
  1286. /* Handle IOCTL_SERIAL_LSRMST_INSERT */
  1287. /* */
  1288. /* Arguments: */
  1289. /* */
  1290. /* Irp - pointer to an I/O Request Packet */
  1291. /* DeviceExtension - pointer to device extension */
  1292. /* */
  1293. /* Return Value: */
  1294. /* */
  1295. /* NTSTATUS */
  1296. /* */
  1297. /************************************************************************/
  1298. NTSTATUS
  1299. LsrmstInsert(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1300. {
  1301. USBSER_LOCKED_PAGED_CODE();
  1302. DEBUG_LOG_PATH("enter LsrmstInsert");
  1303. UsbSerSerialDump(USBSERTRACEIOC, (">LsrmstInsert(%08X)\n", Irp));
  1304. UsbSerSerialDump(USBSERTRACEIOC, ("<LsrmstInsert (%08X)\n",
  1305. STATUS_NOT_SUPPORTED));
  1306. return STATUS_NOT_SUPPORTED;
  1307. } // LsrmstInsert
  1308. /************************************************************************/
  1309. /* ConfigSize */
  1310. /************************************************************************/
  1311. /* */
  1312. /* Routine Description: */
  1313. /* */
  1314. /* Handle IOCTL_SERIAL_CONFIG_SIZE */
  1315. /* */
  1316. /* Arguments: */
  1317. /* */
  1318. /* Irp - pointer to an I/O Request Packet */
  1319. /* DeviceExtension - pointer to device extension */
  1320. /* */
  1321. /* Return Value: */
  1322. /* */
  1323. /* NTSTATUS */
  1324. /* */
  1325. /************************************************************************/
  1326. NTSTATUS
  1327. ConfigSize(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1328. {
  1329. PULONG ConfigSize = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  1330. NTSTATUS NtStatus = STATUS_SUCCESS;
  1331. PIO_STACK_LOCATION IrpStack;
  1332. USBSER_LOCKED_PAGED_CODE();
  1333. DEBUG_LOG_PATH("enter ConfigSize");
  1334. UsbSerSerialDump(USBSERTRACEIOC, (">ConfigSize(%08X)\n", Irp));
  1335. Irp->IoStatus.Information = 0;
  1336. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1337. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  1338. < sizeof(ULONG)) {
  1339. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1340. } else {
  1341. *ConfigSize = 0;
  1342. Irp->IoStatus.Information = sizeof(ULONG);
  1343. }
  1344. DEBUG_LOG_PATH("exit ConfigSize");
  1345. UsbSerSerialDump(USBSERTRACEIOC, ("<ConfigSize %08X\n", NtStatus));
  1346. return NtStatus;
  1347. } // ConfigSize
  1348. /************************************************************************/
  1349. /* GetStats */
  1350. /************************************************************************/
  1351. /* */
  1352. /* Routine Description: */
  1353. /* */
  1354. /* Handle IOCTL_SERIAL_GET_STATS */
  1355. /* */
  1356. /* Arguments: */
  1357. /* */
  1358. /* Irp - pointer to an I/O Request Packet */
  1359. /* DeviceExtension - pointer to device extension */
  1360. /* */
  1361. /* Return Value: */
  1362. /* */
  1363. /* NTSTATUS */
  1364. /* */
  1365. /************************************************************************/
  1366. NTSTATUS
  1367. GetStats(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1368. {
  1369. PSERIALPERF_STATS Stats
  1370. = (PSERIALPERF_STATS) Irp->AssociatedIrp.SystemBuffer;
  1371. NTSTATUS NtStatus = STATUS_SUCCESS;
  1372. KIRQL OldIrql;
  1373. PIO_STACK_LOCATION IrpStack;
  1374. USBSER_ALWAYS_LOCKED_CODE();
  1375. DEBUG_LOG_PATH("enter GetStats");
  1376. UsbSerSerialDump(USBSERTRACEIOC, (">GetStats(%08X)\n", Irp));
  1377. Irp->IoStatus.Information = 0;
  1378. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1379. if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength
  1380. < sizeof(SERIALPERF_STATS)) {
  1381. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1382. } else {
  1383. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1384. *Stats = DeviceExtension->PerfStats;
  1385. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1386. Irp->IoStatus.Information = sizeof(SERIALPERF_STATS);
  1387. }
  1388. DEBUG_LOG_PATH("exit GetStats");
  1389. UsbSerSerialDump(USBSERTRACEIOC, ("<GetStats %08X\n", NtStatus));
  1390. return NtStatus;
  1391. } // GetStats
  1392. /************************************************************************/
  1393. /* ClearStats */
  1394. /************************************************************************/
  1395. /* */
  1396. /* Routine Description: */
  1397. /* */
  1398. /* Handle IOCTL_SERIAL_CLEAR_STATS */
  1399. /* */
  1400. /* Arguments: */
  1401. /* */
  1402. /* Irp - pointer to an I/O Request Packet */
  1403. /* DeviceExtension - pointer to device extension */
  1404. /* */
  1405. /* Return Value: */
  1406. /* */
  1407. /* NTSTATUS */
  1408. /* */
  1409. /************************************************************************/
  1410. NTSTATUS
  1411. ClearStats(IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
  1412. {
  1413. NTSTATUS NtStatus = STATUS_SUCCESS;
  1414. KIRQL OldIrql;
  1415. USBSER_ALWAYS_LOCKED_CODE();
  1416. DEBUG_LOG_PATH("enter ClearStats");
  1417. UsbSerSerialDump(USBSERTRACEIOC, (">ClearStats(%08X)\n", Irp));
  1418. Irp->IoStatus.Information = 0;
  1419. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1420. RtlZeroMemory(&DeviceExtension->PerfStats,
  1421. sizeof(SERIALPERF_STATS));
  1422. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1423. DEBUG_LOG_PATH("exit ClearStats");
  1424. UsbSerSerialDump(USBSERTRACEIOC, ("<ClearStats %08X\n", NtStatus));
  1425. return NtStatus;
  1426. } // ClearStats
  1427. /************************************************************************/
  1428. /* SerialGetProperties */
  1429. /************************************************************************/
  1430. /* */
  1431. /* Routine Description: */
  1432. /* */
  1433. /* Get serial device properties */
  1434. /* */
  1435. /* Arguments: */
  1436. /* */
  1437. /* DeviceExtension - pointer to device extension */
  1438. /* Properties - pointer to device properties to fill in */
  1439. /* */
  1440. /* Return Value: */
  1441. /* */
  1442. /* VOID */
  1443. /* */
  1444. /************************************************************************/
  1445. VOID
  1446. SerialGetProperties(IN PDEVICE_EXTENSION DeviceExtension,
  1447. IN PSERIAL_COMMPROP Properties)
  1448. {
  1449. KIRQL OldIrql;
  1450. USBSER_ALWAYS_LOCKED_CODE();
  1451. DEBUG_LOG_PATH("enter SerialGetProperties");
  1452. UsbSerSerialDump(USBSERTRACEIOC, (">SerialGetProperties\n"));
  1453. RtlZeroMemory(Properties, sizeof(SERIAL_COMMPROP));
  1454. Properties->PacketLength = sizeof(SERIAL_COMMPROP);
  1455. Properties->PacketVersion = 2;
  1456. Properties->ServiceMask = SERIAL_SP_SERIALCOMM;
  1457. Properties->MaxTxQueue = 0;
  1458. Properties->MaxRxQueue = 0;
  1459. Properties->MaxBaud = SERIAL_BAUD_USER;
  1460. Properties->ProvSubType = SERIAL_SP_MODEM;
  1461. Properties->ProvCapabilities = SERIAL_PCF_DTRDSR | SERIAL_PCF_CD
  1462. | SERIAL_PCF_PARITY_CHECK | SERIAL_PCF_TOTALTIMEOUTS
  1463. | SERIAL_PCF_INTTIMEOUTS;
  1464. Properties->SettableParams = SERIAL_SP_PARITY | SERIAL_SP_BAUD
  1465. | SERIAL_SP_DATABITS | SERIAL_SP_STOPBITS | SERIAL_SP_HANDSHAKING
  1466. | SERIAL_SP_PARITY_CHECK | SERIAL_SP_CARRIER_DETECT;
  1467. Properties->SettableData = SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
  1468. Properties->SettableStopParity = SERIAL_STOPBITS_10 | SERIAL_PARITY_NONE
  1469. | SERIAL_PARITY_ODD | SERIAL_PARITY_EVEN | SERIAL_PARITY_MARK
  1470. | SERIAL_PARITY_SPACE;
  1471. Properties->CurrentTxQueue = 0;
  1472. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1473. Properties->CurrentRxQueue = DeviceExtension->RxQueueSize;
  1474. Properties->SettableBaud = DeviceExtension->SupportedBauds;
  1475. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1476. DEBUG_LOG_PATH("exit SerialGetProperties");
  1477. UsbSerSerialDump(USBSERTRACEIOC, ("<SerialGetProperties\n"));
  1478. } // SerialGetProperties
  1479. /************************************************************************/
  1480. /* GetLineControlAndBaud */
  1481. /************************************************************************/
  1482. /* */
  1483. /* Routine Description: */
  1484. /* */
  1485. /* CDC command to get line control settings and baud */
  1486. /* */
  1487. /* Arguments: */
  1488. /* */
  1489. /* PDevObj - pointer to device object */
  1490. /* */
  1491. /* Return Value: */
  1492. /* */
  1493. /* NTSTATUS */
  1494. /* */
  1495. /************************************************************************/
  1496. NTSTATUS
  1497. GetLineControlAndBaud(IN PDEVICE_OBJECT PDevObj)
  1498. {
  1499. NTSTATUS NtStatus = STATUS_SUCCESS;
  1500. USB_COMM_LINE_CODING LineCoding;
  1501. ULONG Size = sizeof(LineCoding);
  1502. KIRQL OldIrql;
  1503. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  1504. DEBUG_LOG_PATH("enter GetLineControlAndBaud");
  1505. NtStatus = ClassVendorCommand(PDevObj, USB_COMM_GET_LINE_CODING, 0,
  1506. DeviceExtension->CommInterface,
  1507. &LineCoding, &Size, TRUE,
  1508. USBSER_CLASS_COMMAND);
  1509. if (NT_SUCCESS(NtStatus)) {
  1510. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1511. DeviceExtension->CurrentBaud = LineCoding.DTERate;
  1512. DeviceExtension->LineControl.StopBits = StopBits[LineCoding.CharFormat];
  1513. DeviceExtension->LineControl.Parity = ParityType[LineCoding.ParityType];
  1514. DeviceExtension->LineControl.WordLength = LineCoding.DataBits;
  1515. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1516. DEBUG_TRACE3(("Baud (%08X) StopBits (%08X) DataBits (%08X)\n",
  1517. LineCoding.DTERate, LineCoding.CharFormat,
  1518. LineCoding.DataBits));
  1519. }
  1520. DEBUG_LOG_PATH("exit GetLineControlAndBaud");
  1521. return NtStatus;
  1522. } // GetLineControlAndBaud
  1523. /************************************************************************/
  1524. /* SetLineControlAndBaud */
  1525. /************************************************************************/
  1526. /* */
  1527. /* Routine Description: */
  1528. /* */
  1529. /* CDC command to set line control and baud */
  1530. /* */
  1531. /* Arguments: */
  1532. /* */
  1533. /* PDevObj - pointer to device object */
  1534. /* */
  1535. /* Return Value: */
  1536. /* */
  1537. /* NTSTATUS */
  1538. /* */
  1539. /************************************************************************/
  1540. NTSTATUS
  1541. SetLineControlAndBaud(IN PDEVICE_OBJECT PDevObj)
  1542. {
  1543. NTSTATUS NtStatus = STATUS_SUCCESS;
  1544. USB_COMM_LINE_CODING LineCoding;
  1545. ULONG Size = sizeof(LineCoding);
  1546. PSERIAL_LINE_CONTROL LineControl;
  1547. KIRQL OldIrql;
  1548. PDEVICE_EXTENSION DeviceExtension = PDevObj->DeviceExtension;
  1549. DEBUG_LOG_PATH("enter SetLineControlAndBaud");
  1550. // get pointer to line control in extension
  1551. LineControl = &DeviceExtension->LineControl;
  1552. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1553. // set up the line coding data structure
  1554. LineCoding.DTERate = DeviceExtension->CurrentBaud;
  1555. LineCoding.DataBits = LineControl->WordLength;
  1556. switch (DeviceExtension->LineControl.StopBits) {
  1557. case STOP_BIT_1:
  1558. LineCoding.CharFormat = USB_COMM_STOPBITS_10;
  1559. break;
  1560. case STOP_BITS_1_5:
  1561. LineCoding.CharFormat = USB_COMM_STOPBITS_15;
  1562. break;
  1563. case STOP_BITS_2:
  1564. LineCoding.CharFormat = USB_COMM_STOPBITS_20;
  1565. break;
  1566. default:
  1567. NtStatus = STATUS_INVALID_PARAMETER;
  1568. break;
  1569. }
  1570. switch (DeviceExtension->LineControl.Parity) {
  1571. case NO_PARITY:
  1572. LineCoding.ParityType = USB_COMM_PARITY_NONE;
  1573. break;
  1574. case ODD_PARITY:
  1575. LineCoding.ParityType = USB_COMM_PARITY_ODD;
  1576. break;
  1577. case EVEN_PARITY:
  1578. LineCoding.ParityType = USB_COMM_PARITY_EVEN;
  1579. break;
  1580. case MARK_PARITY:
  1581. LineCoding.ParityType = USB_COMM_PARITY_MARK;
  1582. break;
  1583. case SPACE_PARITY:
  1584. LineCoding.ParityType = USB_COMM_PARITY_SPACE;
  1585. break;
  1586. default:
  1587. NtStatus = STATUS_INVALID_PARAMETER;
  1588. break;
  1589. }
  1590. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1591. // the request must be valid, so send it down to the device
  1592. if (NT_SUCCESS(NtStatus)) {
  1593. NtStatus = ClassVendorCommand(PDevObj, USB_COMM_SET_LINE_CODING, 0,
  1594. DeviceExtension->CommInterface,
  1595. &LineCoding, &Size, FALSE,
  1596. USBSER_CLASS_COMMAND);
  1597. }
  1598. // let's go ahead and just grab this info again in case of an error
  1599. GetLineControlAndBaud(PDevObj);
  1600. DEBUG_LOG_PATH("exit SetLineControlAndBaud");
  1601. return NtStatus;
  1602. } // SetLineControlAndBaud
  1603. /************************************************************************/
  1604. /* NotifyCompletion */
  1605. /************************************************************************/
  1606. /* */
  1607. /* Routine Description: */
  1608. /* */
  1609. /* Notify completion routine. */
  1610. /* */
  1611. /* Arguments: */
  1612. /* */
  1613. /* DeviceObject - pointer to a device object */
  1614. /* Irp - pointer to Irp */
  1615. /* Context - pointer to driver defined context */
  1616. /* */
  1617. /* Return Value: */
  1618. /* */
  1619. /* NTSTATUS */
  1620. /* */
  1621. /************************************************************************/
  1622. NTSTATUS
  1623. NotifyCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
  1624. {
  1625. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Context;
  1626. PURB Urb;
  1627. ULONG Count;
  1628. KIRQL OldIrql;
  1629. KIRQL cancelIrql;
  1630. PUSB_COMM_SERIAL_STATUS SerialState;
  1631. USHORT ModemStatus;
  1632. USHORT OldModemStatus;
  1633. PIRP CurrentMaskIrp = NULL;
  1634. BOOLEAN startRead = FALSE;
  1635. DEBUG_LOG_PATH("enter NotifyCompletion");
  1636. Urb = DeviceExtension->NotifyUrb;
  1637. Count = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  1638. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1639. SerialState = (PUSB_COMM_SERIAL_STATUS) DeviceExtension->NotificationBuff;
  1640. // see if it is our notification
  1641. if (SerialState->Notification == USB_COMM_SERIAL_STATE
  1642. && Count == sizeof(USB_COMM_SERIAL_STATUS)) {
  1643. OldModemStatus = DeviceExtension->FakeModemStatus;
  1644. // cobble up a fake modem status
  1645. DeviceExtension->FakeModemStatus = SERIAL_MSR_CTS;
  1646. DeviceExtension->FakeLineStatus = 0;
  1647. DeviceExtension->HistoryMask = 0;
  1648. ModemStatus = SerialState->SerialState;
  1649. DeviceExtension->FakeLineStatus = 0;
  1650. DEBUG_TRACE1(("CDC Serial State (%08X)\n", ModemStatus));
  1651. if (ModemStatus & USB_COMM_DSR)
  1652. DeviceExtension->FakeModemStatus |= SERIAL_MSR_DSR;
  1653. if (ModemStatus & USB_COMM_DCD)
  1654. DeviceExtension->FakeModemStatus |= SERIAL_MSR_DCD;
  1655. if (ModemStatus & USB_COMM_RING)
  1656. DeviceExtension->FakeModemStatus |= SERIAL_MSR_RI;
  1657. // let's see what has changed in the status register
  1658. ModemStatus = OldModemStatus ^ DeviceExtension->FakeModemStatus;
  1659. if (ModemStatus & SERIAL_MSR_DSR)
  1660. DeviceExtension->HistoryMask |= SERIAL_EV_DSR;
  1661. if (ModemStatus & SERIAL_MSR_DCD)
  1662. DeviceExtension->HistoryMask |= SERIAL_EV_RLSD;
  1663. if (ModemStatus & SERIAL_MSR_RI)
  1664. DeviceExtension->HistoryMask |= SERIAL_EV_RING;
  1665. // see if we have any events we are waiting for
  1666. DeviceExtension->HistoryMask &= DeviceExtension->IsrWaitMask;
  1667. // update perf stats if we had any errors
  1668. if (ModemStatus & USB_COMM_FRAMING_ERROR) {
  1669. DeviceExtension->PerfStats.FrameErrorCount++;
  1670. DeviceExtension->FakeLineStatus |= SERIAL_LSR_FE;
  1671. }
  1672. if (ModemStatus & USB_COMM_OVERRUN) {
  1673. DeviceExtension->PerfStats.BufferOverrunErrorCount++;
  1674. DeviceExtension->FakeLineStatus |= SERIAL_LSR_OE;
  1675. }
  1676. if (ModemStatus & USB_COMM_PARITY_ERROR) {
  1677. DeviceExtension->PerfStats.ParityErrorCount++;
  1678. DeviceExtension->FakeLineStatus |= SERIAL_LSR_PE;
  1679. }
  1680. if (ModemStatus & USB_COMM_BREAK) {
  1681. DeviceExtension->FakeLineStatus |= SERIAL_LSR_BI;
  1682. }
  1683. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1684. ACQUIRE_CANCEL_SPINLOCK(DeviceExtension, &cancelIrql);
  1685. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1686. // let's see if we have any events to signal
  1687. CurrentMaskIrp = DeviceExtension->CurrentMaskIrp;
  1688. if (CurrentMaskIrp && DeviceExtension->HistoryMask) {
  1689. *(PULONG) (CurrentMaskIrp->AssociatedIrp.SystemBuffer) =
  1690. DeviceExtension->HistoryMask;
  1691. CurrentMaskIrp->IoStatus.Status = STATUS_SUCCESS;
  1692. CurrentMaskIrp->IoStatus.Information = sizeof(ULONG);
  1693. DeviceExtension->CurrentMaskIrp = NULL;
  1694. }
  1695. else
  1696. {
  1697. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1698. RELEASE_CANCEL_SPINLOCK(DeviceExtension, cancelIrql);
  1699. }
  1700. DEBUG_TRACE1(("Modem Status (%08X)\n", DeviceExtension->FakeModemStatus));
  1701. }
  1702. else
  1703. {
  1704. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1705. }
  1706. // complete the queued IRP if needed
  1707. if (CurrentMaskIrp && DeviceExtension->HistoryMask
  1708. && Irp->IoStatus.Status == STATUS_SUCCESS)
  1709. {
  1710. //
  1711. // We should still be holding cancel spin lock because
  1712. // of above if()
  1713. UsbSerSerialDump(USBSERCOMPEV, ("Completing maskirp (4) %08X\n",
  1714. DeviceExtension->HistoryMask));
  1715. DeviceExtension->HistoryMask = 0;
  1716. IoSetCancelRoutine(CurrentMaskIrp, NULL);
  1717. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1718. RELEASE_CANCEL_SPINLOCK(DeviceExtension, cancelIrql);
  1719. IoCompleteRequest(CurrentMaskIrp, IO_NO_INCREMENT);
  1720. }
  1721. // check for Irp cancelled or error
  1722. if(Irp->IoStatus.Status == STATUS_CANCELLED)
  1723. {
  1724. goto NotifyCompletionErr;
  1725. }
  1726. else if(!NT_SUCCESS(Irp->IoStatus.Status))
  1727. {
  1728. UsbSerFetchBooleanLocked(&DeviceExtension->AcceptingRequests,
  1729. FALSE, &DeviceExtension->ControlLock);
  1730. goto NotifyCompletionErr;
  1731. }
  1732. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  1733. // kick off another notification request if we still need to
  1734. if (DeviceExtension->AcceptingRequests
  1735. && (DeviceExtension->CurrentDevicePowerState == PowerDeviceD0))
  1736. {
  1737. // see if we have a work item queued already
  1738. if(DeviceExtension->IoWorkItem == NULL)
  1739. {
  1740. startRead = TRUE;
  1741. // kick off another read
  1742. DeviceExtension->IoWorkItem = IoAllocateWorkItem(DeviceExtension->PhysDeviceObject);
  1743. }
  1744. if(startRead && DeviceExtension->IoWorkItem)
  1745. {
  1746. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1747. IoQueueWorkItem(DeviceExtension->IoWorkItem,
  1748. USBSER_RestartNotifyReadWorkItem,
  1749. CriticalWorkQueue,
  1750. DeviceExtension);
  1751. }
  1752. else
  1753. {
  1754. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1755. }
  1756. } else {
  1757. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  1758. }
  1759. NotifyCompletionErr:;
  1760. //
  1761. // Notify everyone if this is the last IRP and we aren't starting another read
  1762. //
  1763. if((InterlockedDecrement(&DeviceExtension->PendingNotifyCount) == 0))
  1764. {
  1765. UsbSerSerialDump(USBSERTRACERD, ("Notify pipe is empty\n"));
  1766. if(!startRead)
  1767. {
  1768. KeSetEvent(&DeviceExtension->PendingNotifyEvent, IO_NO_INCREMENT, FALSE);
  1769. }
  1770. }
  1771. DEBUG_LOG_PATH("exit NotifyCompletion");
  1772. return STATUS_MORE_PROCESSING_REQUIRED;
  1773. } // NotifyCompletion
  1774.