|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: ioctl.c
8:
9: Abstract:
10:
11: This module contains the ioctl dispatcher as well as a couple
12: of routines that are generally just called in response to
13: ioctl calls.
14:
15: Author:
16:
17: Anthony V. Ercolano 26-Sep-1991
18:
19: Environment:
20:
21: Kernel mode
22:
23: Revision History :
24:
25: --*/
26:
27: #include <stddef.h>
28: #include "ntddk.h"
29: #include "ntddser.h"
30: #include "serial.h"
31: #include "serialp.h"
32:
33: BOOLEAN
34: SerialGetModemUpdate(
35: IN PVOID Context
36: );
37:
38: BOOLEAN
39: SerialGetCommStatus(
40: IN PVOID Context
41: );
42:
43: VOID
44: SerialGetProperties(
45: IN PSERIAL_DEVICE_EXTENSION Extension,
46: IN PSERIAL_COMMPROP Properties
47: );
48:
49: BOOLEAN
50: SerialSetEscapeChar(
51: IN PVOID Context
52: );
53:
54:
55: BOOLEAN
56: SerialSetChars(
57: IN PVOID Context
58: )
59:
60: /*++
61:
62: Routine Description:
63:
64: This routine is used to set the special characters for the
65: driver.
66:
67: Arguments:
68:
69: Context - Pointer to a structure that contains a pointer to
70: the device extension and a pointer to a special characters
71: structure.
72:
73: Return Value:
74:
75: This routine always returns FALSE.
76:
77: --*/
78:
79: {
80:
81: ((PSERIAL_IOCTL_SYNC)Context)->Extension->SpecialChars =
82: *((PSERIAL_CHARS)(((PSERIAL_IOCTL_SYNC)Context)->Data));
83:
84: return FALSE;
85:
86: }
87:
88: BOOLEAN
89: SerialSetBaud(
90: IN PVOID Context
91: )
92:
93: /*++
94:
95: Routine Description:
96:
97: This routine is used to set the buad rate of the device.
98:
99: Arguments:
100:
101: Context - Pointer to a structure that contains a pointer to
102: the device extension and what should be the current
103: baud rate.
104:
105: Return Value:
106:
107: This routine always returns FALSE.
108:
109: --*/
110:
111: {
112:
113: PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension;
114: USHORT Appropriate = (USHORT)(((PSERIAL_IOCTL_SYNC)Context)->Data);
115:
116: WRITE_DIVISOR_LATCH(
117: Extension->Controller,
118: Appropriate
119: );
120:
121: return FALSE;
122:
123: }
124:
125: BOOLEAN
126: SerialSetLineControl(
127: IN PVOID Context
128: )
129:
130: /*++
131:
132: Routine Description:
133:
134: This routine is used to set the buad rate of the device.
135:
136: Arguments:
137:
138: Context - Pointer to the device extension.
139:
140: Return Value:
141:
142: This routine always returns FALSE.
143:
144: --*/
145:
146: {
147:
148: PSERIAL_DEVICE_EXTENSION Extension = Context;
149:
150: WRITE_LINE_CONTROL(
151: Extension->Controller,
152: Extension->LineControl
153: );
154:
155: return FALSE;
156:
157: }
158:
159: BOOLEAN
160: SerialGetModemUpdate(
161: IN PVOID Context
162: )
163:
164: /*++
165:
166: Routine Description:
167:
168: This routine is simply used to call the interrupt level routine
169: that handles modem status update.
170:
171: Arguments:
172:
173: Context - Pointer to a structure that contains a pointer to
174: the device extension and a pointer to a ulong.
175:
176: Return Value:
177:
178: This routine always returns FALSE.
179:
180: --*/
181:
182: {
183:
184: PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension;
185: ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data);
186:
187: *Result = SerialHandleModemUpdate(
188: Extension,
189: FALSE
190: );
191:
192: return FALSE;
193:
194: }
195:
196: BOOLEAN
197: SerialGetCommStatus(
198: IN PVOID Context
199: )
200:
201: /*++
202:
203: Routine Description:
204:
205: This is used to get the current state of the serial driver.
206:
207: Arguments:
208:
209: Context - Pointer to a structure that contains a pointer to
210: the device extension and a pointer to a serial status
211: record.
212:
213: Return Value:
214:
215: This routine always returns FALSE.
216:
217: --*/
218:
219: {
220:
221: PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension;
222: PSERIAL_STATUS Stat = ((PSERIAL_IOCTL_SYNC)Context)->Data;
223:
224: Stat->Errors = Extension->ErrorWord;
225: Extension->ErrorWord = 0;
226:
227: //
228: // BUG BUG We need to do something about eof (binary mode).
229: //
230: Stat->EofReceived = FALSE;
231:
232: Stat->AmountInInQueue = Extension->CharsInInterruptBuffer;
233:
234: Stat->AmountInOutQueue = Extension->TotalCharsQueued;
235:
236: if (Extension->WriteLength) {
237:
238: //
239: // By definition if we have a writelength the we have
240: // a current write irp.
241: //
242:
243: ASSERT(Extension->CurrentWriteIrp);
244: ASSERT(Stat->AmountInOutQueue >= Extension->WriteLength);
245: ASSERT((IoGetCurrentIrpStackLocation(Extension->CurrentWriteIrp)->
246: Parameters.Write.Length) >=
247: Extension->WriteLength);
248:
249: Stat->AmountInOutQueue -=
250: IoGetCurrentIrpStackLocation(Extension->CurrentWriteIrp)
251: ->Parameters.Write.Length - (Extension->WriteLength);
252:
253: }
254:
255: Stat->WaitForImmediate = Extension->TransmitImmediate;
256:
257: Stat->HoldReasons = 0;
258: if (Extension->TXHolding) {
259:
260: if (Extension->TXHolding & SERIAL_TX_CTS) {
261:
262: Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS;
263:
264: }
265:
266: if (Extension->TXHolding & SERIAL_TX_DSR) {
267:
268: Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DSR;
269:
270: }
271:
272: if (Extension->TXHolding & SERIAL_TX_DCD) {
273:
274: Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DCD;
275:
276: }
277:
278: if (Extension->TXHolding & SERIAL_TX_XOFF) {
279:
280: Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_XON;
281:
282: }
283:
284: if (Extension->TXHolding & SERIAL_TX_BREAK) {
285:
286: Stat->HoldReasons |= SERIAL_TX_WAITING_ON_BREAK;
287:
288: }
289:
290: }
291:
292: if (Extension->RXHolding & SERIAL_RX_DSR) {
293:
294: Stat->HoldReasons |= SERIAL_RX_WAITING_FOR_DSR;
295:
296: }
297:
298: if (Extension->RXHolding & SERIAL_RX_XOFF) {
299:
300: Stat->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;
301:
302: }
303:
304: return FALSE;
305:
306: }
307:
308: BOOLEAN
309: SerialSetEscapeChar(
310: IN PVOID Context
311: )
312:
313: /*++
314:
315: Routine Description:
316:
317: This is used to set the character that will be used to escape
318: line status and modem status information when the application
319: has set up that line status and modem status should be passed
320: back in the data stream.
321:
322: Arguments:
323:
324: Context - Pointer to the irp that is specify the escape character.
325: Implicitly - An escape character of 0 means no escaping
326: will occur.
327:
328: Return Value:
329:
330: This routine always returns FALSE.
331:
332: --*/
333:
334: {
335:
336: PSERIAL_DEVICE_EXTENSION extension =
337: IoGetCurrentIrpStackLocation((PIRP)Context)
338: ->DeviceObject->DeviceExtension;
339:
340: extension->EscapeChar =
341: *(PUCHAR)((PIRP)Context)->AssociatedIrp.SystemBuffer;
342:
343: return FALSE;
344:
345: }
346:
347: NTSTATUS
348: SerialIoControl(
349: IN PDEVICE_OBJECT DeviceObject,
350: IN PIRP Irp
351: )
352:
353: /*++
354:
355: Routine Description:
356:
357: This routine provides the initial processing for all of the
358: Ioctrls for the serial device.
359:
360: Arguments:
361:
362: DeviceObject - Pointer to the device object for this device
363:
364: Irp - Pointer to the IRP for the current request
365:
366: Return Value:
367:
368: The function value is the final status of the call
369:
370: --*/
371:
372: {
373: //
374: // The status that gets returned to the caller and
375: // set in the Irp.
376: //
377: NTSTATUS Status;
378:
379: //
380: // The current stack location. This contains all of the
381: // information we need to process this particular request.
382: //
383: PIO_STACK_LOCATION IrpSp;
384:
385: //
386: // Just what it says. This is the serial specific device
387: // extension of the device object create for the serial driver.
388: //
389: PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
390:
391: //
392: // A temporary to hold the old IRQL so that it can be
393: // restored once we complete/validate this request.
394: //
395: KIRQL OldIrql;
396:
397: SerialDump(
398: SERIRPPATH,
399: ("SERIAL: Dispatch entry for: %x\n",Irp)
400: );
401: if (SerialCompleteIfError(
402: DeviceObject,
403: Irp
404: ) != STATUS_SUCCESS) {
405:
406: return STATUS_CANCELLED;
407:
408: }
409: IrpSp = IoGetCurrentIrpStackLocation(Irp);
410: Irp->IoStatus.Information = 0L;
411: Status = STATUS_SUCCESS;
412: switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
413:
414: case IOCTL_SERIAL_SET_BAUD_RATE : {
415:
416: ULONG BaudRate;
417: //
418: // Will hold the value of the appropriate divisor for
419: // the requested baud rate. If the baudrate is invalid
420: // (because the device won't support that baud rate) then
421: // this value is undefined.
422: //
423: // Note: in one sense the concept of a valid baud rate
424: // is cloudy. We could allow the user to request any
425: // baud rate. We could then calculate the divisor needed
426: // for that baud rate. As long as the divisor wasn't less
427: // than one we would be "ok". (The percentage difference
428: // between the "true" divisor and the "rounded" value given
429: // to the hardware might make it unusable, but... ) It would
430: // really be up to the user to "Know" whether the baud rate
431: // is suitable. So much for theory, *We* only support a given
432: // set of baud rates.
433: //
434: SHORT AppropriateDivisor;
435:
436: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
437: sizeof(SERIAL_BAUD_RATE)) {
438:
439: Status = STATUS_BUFFER_TOO_SMALL;
440: break;
441:
442: } else {
443:
444: BaudRate = ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate;
445:
446: }
447:
448: //
449: // Get the baud rate from the irp. We pass it
450: // to a routine which will set the correct divisor.
451: //
452:
453: Status = SerialGetDivisorFromBaud(
454: Extension->ClockRate,
455: BaudRate,
456: &AppropriateDivisor
457: );
458:
459: KeAcquireSpinLock(
460: &Extension->ControlLock,
461: &OldIrql
462: );
463:
464: if (NT_SUCCESS(Status)) {
465:
466: SERIAL_IOCTL_SYNC S;
467:
468: Extension->CurrentBaud = BaudRate;
469:
470: S.Extension = Extension;
471: S.Data = (PVOID)AppropriateDivisor;
472: KeSynchronizeExecution(
473: Extension->Interrupt,
474: SerialSetBaud,
475: &S
476: );
477:
478: }
479:
480: KeReleaseSpinLock(
481: &Extension->ControlLock,
482: OldIrql
483: );
484:
485: break;
486: }
487: case IOCTL_SERIAL_GET_BAUD_RATE: {
488:
489: PSERIAL_BAUD_RATE Br = (PSERIAL_BAUD_RATE)Irp->AssociatedIrp.SystemBuffer;
490: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
491: sizeof(SERIAL_BAUD_RATE)) {
492:
493: Status = STATUS_BUFFER_TOO_SMALL;
494: break;
495:
496: }
497:
498: KeAcquireSpinLock(
499: &Extension->ControlLock,
500: &OldIrql
501: );
502:
503: Br->BaudRate = Extension->CurrentBaud;
504:
505: KeReleaseSpinLock(
506: &Extension->ControlLock,
507: OldIrql
508: );
509:
510: Irp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);
511:
512: break;
513:
514: }
515: case IOCTL_SERIAL_SET_LINE_CONTROL: {
516:
517: //
518: // Points to the line control record in the Irp.
519: //
520: PSERIAL_LINE_CONTROL Lc =
521: ((PSERIAL_LINE_CONTROL)(Irp->AssociatedIrp.SystemBuffer));
522:
523: UCHAR LData;
524: UCHAR LStop;
525: UCHAR LParity;
526: UCHAR Mask = 0xff;
527:
528: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
529: sizeof(SERIAL_LINE_CONTROL)) {
530:
531: Status = STATUS_BUFFER_TOO_SMALL;
532: break;
533:
534: }
535:
536: switch (Lc->WordLength) {
537: case 5: {
538:
539: LData = SERIAL_5_DATA;
540: Mask = 0x1f;
541: break;
542:
543: }
544: case 6: {
545:
546: LData = SERIAL_6_DATA;
547: Mask = 0x3f;
548: break;
549:
550: }
551: case 7: {
552:
553: LData = SERIAL_7_DATA;
554: Mask = 0x7f;
555: break;
556:
557: }
558: case 8: {
559:
560: LData = SERIAL_8_DATA;
561: break;
562:
563: }
564: default: {
565:
566: Status = STATUS_INVALID_PARAMETER;
567: goto DoneWithIoctl;
568:
569: }
570:
571: }
572:
573: switch (Lc->Parity) {
574:
575: case NO_PARITY: {
576:
577: LParity = SERIAL_NONE_PARITY;
578: break;
579:
580: }
581: case EVEN_PARITY: {
582:
583: LParity = SERIAL_EVEN_PARITY;
584: break;
585:
586: }
587: case ODD_PARITY: {
588:
589: LParity = SERIAL_ODD_PARITY;
590: break;
591:
592: }
593: case SPACE_PARITY: {
594:
595: LParity = SERIAL_SPACE_PARITY;
596: break;
597:
598: }
599: case MARK_PARITY: {
600:
601: LParity = SERIAL_MARK_PARITY;
602: break;
603:
604: }
605: default: {
606:
607: Status = STATUS_INVALID_PARAMETER;
608: goto DoneWithIoctl;
609: break;
610: }
611:
612: }
613:
614: switch (Lc->StopBits) {
615:
616: case STOP_BIT_1: {
617:
618: LStop = SERIAL_1_STOP;
619: break;
620: }
621: case STOP_BITS_1_5: {
622:
623: if (LData != SERIAL_5_DATA) {
624:
625: Status = STATUS_INVALID_PARAMETER;
626: goto DoneWithIoctl;
627: }
628: LStop = SERIAL_1_5_STOP;
629: break;
630:
631: }
632: case STOP_BITS_2: {
633:
634: if (LData == SERIAL_5_DATA) {
635:
636: Status = STATUS_INVALID_PARAMETER;
637: goto DoneWithIoctl;
638: }
639: LStop = SERIAL_2_STOP;
640: break;
641:
642: }
643: default: {
644:
645: Status = STATUS_INVALID_PARAMETER;
646: goto DoneWithIoctl;
647: }
648:
649: }
650:
651: KeAcquireSpinLock(
652: &Extension->ControlLock,
653: &OldIrql
654: );
655:
656: Extension->LineControl =
657: (UCHAR)((Extension->LineControl & SERIAL_LCR_BREAK) |
658: (LData | LParity | LStop));
659: Extension->ValidDataMask = Mask;
660:
661: KeSynchronizeExecution(
662: Extension->Interrupt,
663: SerialSetLineControl,
664: Extension
665: );
666:
667: KeReleaseSpinLock(
668: &Extension->ControlLock,
669: OldIrql
670: );
671:
672: break;
673: }
674: case IOCTL_SERIAL_GET_LINE_CONTROL: {
675:
676: PSERIAL_LINE_CONTROL Lc = (PSERIAL_LINE_CONTROL)Irp->AssociatedIrp.SystemBuffer;
677:
678: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
679: sizeof(SERIAL_LINE_CONTROL)) {
680:
681: Status = STATUS_BUFFER_TOO_SMALL;
682: break;
683:
684: }
685:
686: KeAcquireSpinLock(
687: &Extension->ControlLock,
688: &OldIrql
689: );
690:
691: if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) {
692: Lc->WordLength = 5;
693: } else if ((Extension->LineControl & SERIAL_DATA_MASK)
694: == SERIAL_6_DATA) {
695: Lc->WordLength = 6;
696: } else if ((Extension->LineControl & SERIAL_DATA_MASK)
697: == SERIAL_7_DATA) {
698: Lc->WordLength = 7;
699: } else if ((Extension->LineControl & SERIAL_DATA_MASK)
700: == SERIAL_8_DATA) {
701: Lc->WordLength = 8;
702: }
703:
704: if ((Extension->LineControl & SERIAL_PARITY_MASK)
705: == SERIAL_NONE_PARITY) {
706: Lc->Parity = NO_PARITY;
707: } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
708: == SERIAL_ODD_PARITY) {
709: Lc->Parity = ODD_PARITY;
710: } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
711: == SERIAL_EVEN_PARITY) {
712: Lc->Parity = EVEN_PARITY;
713: } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
714: == SERIAL_MARK_PARITY) {
715: Lc->Parity = MARK_PARITY;
716: } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
717: == SERIAL_SPACE_PARITY) {
718: Lc->Parity = SPACE_PARITY;
719: }
720:
721: if (Extension->LineControl & SERIAL_2_STOP) {
722: if (Lc->WordLength == 5) {
723: Lc->StopBits = STOP_BITS_1_5;
724: } else {
725: Lc->StopBits = STOP_BITS_2;
726: }
727: } else {
728: Lc->StopBits = STOP_BIT_1;
729: }
730:
731: Irp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);
732:
733: KeReleaseSpinLock(
734: &Extension->ControlLock,
735: OldIrql
736: );
737:
738: break;
739: }
740: case IOCTL_SERIAL_SET_TIMEOUTS: {
741:
742: PSERIAL_TIMEOUTS NewTimeouts =
743: ((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer));
744:
745:
746: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
747: sizeof(SERIAL_TIMEOUTS)) {
748:
749: Status = STATUS_BUFFER_TOO_SMALL;
750: break;
751:
752: }
753:
754: if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) &&
755: (NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
756: (NewTimeouts->ReadTotalTimeoutConstant == MAXULONG)) {
757:
758: Status = STATUS_INVALID_PARAMETER;
759: break;
760:
761: }
762:
763: KeAcquireSpinLock(
764: &Extension->ControlLock,
765: &OldIrql
766: );
767:
768: Extension->Timeouts.ReadIntervalTimeout =
769: NewTimeouts->ReadIntervalTimeout;
770:
771: Extension->Timeouts.ReadTotalTimeoutMultiplier =
772: NewTimeouts->ReadTotalTimeoutMultiplier;
773:
774: Extension->Timeouts.ReadTotalTimeoutConstant =
775: NewTimeouts->ReadTotalTimeoutConstant;
776:
777: Extension->Timeouts.WriteTotalTimeoutMultiplier =
778: NewTimeouts->WriteTotalTimeoutMultiplier;
779:
780: Extension->Timeouts.WriteTotalTimeoutConstant =
781: NewTimeouts->WriteTotalTimeoutConstant;
782:
783: KeReleaseSpinLock(
784: &Extension->ControlLock,
785: OldIrql
786: );
787:
788: break;
789: }
790: case IOCTL_SERIAL_GET_TIMEOUTS: {
791:
792: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
793: sizeof(SERIAL_TIMEOUTS)) {
794:
795: Status = STATUS_BUFFER_TOO_SMALL;
796: break;
797:
798: }
799:
800: KeAcquireSpinLock(
801: &Extension->ControlLock,
802: &OldIrql
803: );
804:
805: *((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) = Extension->Timeouts;
806: Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
807:
808: KeReleaseSpinLock(
809: &Extension->ControlLock,
810: OldIrql
811: );
812:
813: break;
814: }
815: case IOCTL_SERIAL_SET_CHARS: {
816:
817: SERIAL_IOCTL_SYNC S;
818: PSERIAL_CHARS NewChars =
819: ((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
820:
821:
822: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
823: sizeof(SERIAL_CHARS)) {
824:
825: Status = STATUS_BUFFER_TOO_SMALL;
826: break;
827:
828: }
829:
830: //
831: // The only thing that can be wrong with the chars
832: // is that the xon and xoff characters are the
833: // same.
834: //
835:
836: if (NewChars->XonChar == NewChars->XoffChar) {
837:
838: Status = STATUS_INVALID_PARAMETER;
839: break;
840:
841: }
842:
843: //
844: // We acquire the control lock so that only
845: // one request can GET or SET the characters
846: // at a time. The sets could be synchronized
847: // by the interrupt spinlock, but that wouldn't
848: // prevent multiple gets at the same time.
849: //
850:
851: S.Extension = Extension;
852: S.Data = NewChars;
853:
854: KeAcquireSpinLock(
855: &Extension->ControlLock,
856: &OldIrql
857: );
858:
859: //
860: // Under the protection of the lock, make sure that
861: // the xon and xoff characters aren't the same as
862: // the escape character.
863: //
864:
865: if (Extension->EscapeChar) {
866:
867: if ((Extension->EscapeChar == NewChars->XonChar) ||
868: (Extension->EscapeChar == NewChars->XoffChar)) {
869:
870: Status = STATUS_INVALID_PARAMETER;
871: KeReleaseSpinLock(
872: &Extension->ControlLock,
873: OldIrql
874: );
875: break;
876:
877: }
878:
879: }
880:
881: KeSynchronizeExecution(
882: Extension->Interrupt,
883: SerialSetChars,
884: &S
885: );
886:
887: KeReleaseSpinLock(
888: &Extension->ControlLock,
889: OldIrql
890: );
891:
892: break;
893:
894: }
895: case IOCTL_SERIAL_GET_CHARS: {
896:
897: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
898: sizeof(SERIAL_CHARS)) {
899:
900: Status = STATUS_BUFFER_TOO_SMALL;
901: break;
902:
903: }
904:
905: KeAcquireSpinLock(
906: &Extension->ControlLock,
907: &OldIrql
908: );
909:
910: *((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer) = Extension->SpecialChars;
911: Irp->IoStatus.Information = sizeof(SERIAL_CHARS);
912:
913: KeReleaseSpinLock(
914: &Extension->ControlLock,
915: OldIrql
916: );
917:
918: break;
919: }
920: case IOCTL_SERIAL_SET_DTR:
921: case IOCTL_SERIAL_CLR_DTR: {
922:
923: //
924: // We acquire the lock so that we can check whether
925: // automatic dtr flow control is enabled. If it is
926: // then we return an error since the app is not allowed
927: // to touch this if it is automatic.
928: //
929:
930: KeAcquireSpinLock(
931: &Extension->ControlLock,
932: &OldIrql
933: );
934:
935: if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK)
936: == SERIAL_DTR_HANDSHAKE) {
937:
938: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
939:
940: } else {
941:
942: KeSynchronizeExecution(
943: Extension->Interrupt,
944: ((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
945: IOCTL_SERIAL_SET_DTR)?
946: (SerialSetDTR):(SerialClrDTR)),
947: Extension
948: );
949:
950: }
951:
952: KeReleaseSpinLock(
953: &Extension->ControlLock,
954: OldIrql
955: );
956:
957: break;
958: }
959: case IOCTL_SERIAL_RESET_DEVICE: {
960:
961: break;
962: }
963: case IOCTL_SERIAL_SET_RTS:
964: case IOCTL_SERIAL_CLR_RTS: {
965: //
966: // We acquire the lock so that we can check whether
967: // automatic rts flow control or transmit toggleing
968: // is enabled. If it is then we return an error since
969: // the app is not allowed to touch this if it is automatic
970: // or toggling.
971: //
972:
973: KeAcquireSpinLock(
974: &Extension->ControlLock,
975: &OldIrql
976: );
977:
978: if (((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
979: == SERIAL_RTS_HANDSHAKE) ||
980: ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
981: == SERIAL_TRANSMIT_TOGGLE)) {
982:
983: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
984:
985: } else {
986:
987: KeSynchronizeExecution(
988: Extension->Interrupt,
989: ((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
990: IOCTL_SERIAL_SET_RTS)?
991: (SerialSetRTS):(SerialClrRTS)),
992: Extension
993: );
994:
995: }
996:
997: KeReleaseSpinLock(
998: &Extension->ControlLock,
999: OldIrql
1000: );
1001:
1002: break;
1003:
1004: }
1005: case IOCTL_SERIAL_SET_XOFF: {
1006:
1007: KeSynchronizeExecution(
1008: Extension->Interrupt,
1009: SerialPretendXoff,
1010: Extension
1011: );
1012:
1013: break;
1014:
1015: }
1016: case IOCTL_SERIAL_SET_XON: {
1017:
1018: KeSynchronizeExecution(
1019: Extension->Interrupt,
1020: SerialPretendXon,
1021: Extension
1022: );
1023:
1024: break;
1025:
1026: }
1027: case IOCTL_SERIAL_SET_BREAK_ON: {
1028:
1029: KeSynchronizeExecution(
1030: Extension->Interrupt,
1031: SerialTurnOnBreak,
1032: Extension
1033: );
1034:
1035: break;
1036: }
1037: case IOCTL_SERIAL_SET_BREAK_OFF: {
1038:
1039: KeSynchronizeExecution(
1040: Extension->Interrupt,
1041: SerialTurnOffBreak,
1042: Extension
1043: );
1044:
1045: break;
1046: }
1047: case IOCTL_SERIAL_SET_QUEUE_SIZE: {
1048:
1049: //
1050: // Type ahead buffer is fixed, so we just validate
1051: // the the users request is not bigger that our
1052: // own internal buffer size.
1053: //
1054:
1055: PSERIAL_QUEUE_SIZE Rs =
1056: ((PSERIAL_QUEUE_SIZE)(Irp->AssociatedIrp.SystemBuffer));
1057:
1058: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
1059: sizeof(SERIAL_QUEUE_SIZE)) {
1060:
1061: Status = STATUS_BUFFER_TOO_SMALL;
1062: break;
1063:
1064: }
1065:
1066: //
1067: // We have to allocate the memory for the new
1068: // buffer while we're still in the context of the
1069: // caller. We don't even try to protect this
1070: // with a lock because the value could be stale
1071: // as soon as we release the lock - The only time
1072: // we will know for sure is when we actually try
1073: // to do the resize.
1074: //
1075:
1076: if (Rs->InSize <= Extension->BufferSize) {
1077:
1078: Status = STATUS_SUCCESS;
1079: break;
1080:
1081: }
1082:
1083: try {
1084:
1085: IrpSp->Parameters.DeviceIoControl.Type3InputBuffer =
1086: ExAllocatePoolWithQuota(
1087: NonPagedPool,
1088: Rs->InSize
1089: );
1090:
1091: } except (EXCEPTION_EXECUTE_HANDLER) {
1092:
1093: IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
1094: Status = GetExceptionCode();
1095:
1096: }
1097:
1098: if (!IrpSp->Parameters.DeviceIoControl.Type3InputBuffer) {
1099:
1100: break;
1101:
1102: }
1103:
1104: //
1105: // Well the data passed was big enough. Do the request.
1106: //
1107: // There are two reason we place it in the read queue:
1108: //
1109: // 1) We want to serialize these resize requests so that
1110: // they don't contend with each other.
1111: //
1112: // 2) We want to serialize these requests with reads since
1113: // we don't want reads and resizes contending over the
1114: // read buffer.
1115: //
1116:
1117: return SerialStartOrQueue(
1118: Extension,
1119: Irp,
1120: &Extension->ReadQueue,
1121: &Extension->CurrentReadIrp,
1122: SerialStartRead
1123: );
1124:
1125: break;
1126:
1127: }
1128: case IOCTL_SERIAL_GET_WAIT_MASK: {
1129:
1130: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
1131: sizeof(ULONG)) {
1132:
1133: Status = STATUS_BUFFER_TOO_SMALL;
1134: break;
1135:
1136: }
1137:
1138: //
1139: // Simple scalar read. No reason to acquire a lock.
1140: //
1141:
1142: Irp->IoStatus.Information = sizeof(ULONG);
1143:
1144: *((ULONG *)Irp->AssociatedIrp.SystemBuffer) = Extension->IsrWaitMask;
1145:
1146: break;
1147:
1148: }
1149: case IOCTL_SERIAL_SET_WAIT_MASK: {
1150:
1151: ULONG NewMask;
1152:
1153: SerialDump(
1154: SERDIAG3 | SERIRPPATH,
1155: ("SERIAL: In Ioctl processing for set mask\n")
1156: );
1157: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
1158: sizeof(ULONG)) {
1159:
1160: SerialDump(
1161: SERDIAG3,
1162: ("SERIAL: Invalid size fo the buffer %d\n",
1163: IrpSp->Parameters.DeviceIoControl.InputBufferLength)
1164: );
1165: Status = STATUS_BUFFER_TOO_SMALL;
1166: break;
1167:
1168: } else {
1169:
1170: NewMask = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
1171:
1172: }
1173:
1174: //
1175: // Make sure that the mask only contains valid
1176: // waitable events.
1177: //
1178:
1179: if (NewMask & ~(SERIAL_EV_RXCHAR |
1180: SERIAL_EV_RXFLAG |
1181: SERIAL_EV_TXEMPTY |
1182: SERIAL_EV_CTS |
1183: SERIAL_EV_DSR |
1184: SERIAL_EV_RLSD |
1185: SERIAL_EV_BREAK |
1186: SERIAL_EV_ERR |
1187: SERIAL_EV_RING |
1188: SERIAL_EV_PERR |
1189: SERIAL_EV_RX80FULL |
1190: SERIAL_EV_EVENT1 |
1191: SERIAL_EV_EVENT2)) {
1192:
1193: SerialDump(
1194: SERDIAG3,
1195: ("SERIAL: Unknown mask %x\n",NewMask)
1196: );
1197: Status = STATUS_INVALID_PARAMETER;
1198: break;
1199:
1200: }
1201:
1202: //
1203: // Either start this irp or put it on the
1204: // queue.
1205: //
1206:
1207: SerialDump(
1208: SERDIAG3 | SERIRPPATH,
1209: ("SERIAL: Starting or queuing set mask irp %x\n",Irp)
1210: );
1211: return SerialStartOrQueue(
1212: Extension,
1213: Irp,
1214: &Extension->MaskQueue,
1215: &Extension->CurrentMaskIrp,
1216: SerialStartMask
1217: );
1218:
1219: }
1220: case IOCTL_SERIAL_WAIT_ON_MASK: {
1221:
1222: SerialDump(
1223: SERDIAG3 | SERIRPPATH,
1224: ("SERIAL: In Ioctl processing for wait mask\n")
1225: );
1226: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
1227: sizeof(ULONG)) {
1228:
1229: SerialDump(
1230: SERDIAG3,
1231: ("SERIAL: Invalid size fo the buffer %d\n",
1232: IrpSp->Parameters.DeviceIoControl.InputBufferLength)
1233: );
1234: Status = STATUS_BUFFER_TOO_SMALL;
1235: break;
1236:
1237: }
1238:
1239: //
1240: // Either start this irp or put it on the
1241: // queue.
1242: //
1243:
1244: SerialDump(
1245: SERDIAG3 | SERIRPPATH,
1246: ("SERIAL: Starting or queuing wait mask irp %x\n",Irp)
1247: );
1248: return SerialStartOrQueue(
1249: Extension,
1250: Irp,
1251: &Extension->MaskQueue,
1252: &Extension->CurrentMaskIrp,
1253: SerialStartMask
1254: );
1255:
1256: }
1257: case IOCTL_SERIAL_IMMEDIATE_CHAR: {
1258:
1259: KIRQL OldIrql;
1260: BOOLEAN FailRequest;
1261:
1262: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
1263: sizeof(UCHAR)) {
1264:
1265: Status = STATUS_BUFFER_TOO_SMALL;
1266: break;
1267:
1268: }
1269:
1270: IoAcquireCancelSpinLock(&OldIrql);
1271: if (Extension->CurrentImmediateIrp) {
1272:
1273: FailRequest = TRUE;
1274: Status = STATUS_INVALID_PARAMETER;
1275: Irp->IoStatus.Status = Status;
1276: IoReleaseCancelSpinLock(OldIrql);
1277:
1278: } else {
1279:
1280: //
1281: // We can queue the char. We need to set
1282: // a cancel routine because flow control could
1283: // keep the char from transmitting. Make sure
1284: // that the irp hasn't already been canceled.
1285: //
1286:
1287: if (Irp->Cancel) {
1288:
1289: IoReleaseCancelSpinLock(OldIrql);
1290: Irp->IoStatus.Status = STATUS_CANCELLED;
1291: Status = STATUS_CANCELLED;
1292:
1293: } else {
1294:
1295: Extension->CurrentImmediateIrp = Irp;
1296: Extension->TotalCharsQueued++;
1297: IoReleaseCancelSpinLock(OldIrql);
1298: SerialStartImmediate(Extension);
1299:
1300: return STATUS_PENDING;
1301:
1302: }
1303:
1304: }
1305:
1306: }
1307: case IOCTL_SERIAL_PURGE: {
1308:
1309: ULONG Mask;
1310:
1311: //
1312: // Check to make sure that the mask only has
1313: // 0 or the other appropriate values.
1314: //
1315:
1316: Mask = *((ULONG *)(Irp->AssociatedIrp.SystemBuffer));
1317:
1318: if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT |
1319: SERIAL_PURGE_RXABORT |
1320: SERIAL_PURGE_TXCLEAR |
1321: SERIAL_PURGE_RXCLEAR
1322: )
1323: )
1324: )) {
1325:
1326: Status = STATUS_INVALID_PARAMETER;
1327: break;
1328:
1329: }
1330:
1331: //
1332: // Either start this irp or put it on the
1333: // queue.
1334: //
1335:
1336: return SerialStartOrQueue(
1337: Extension,
1338: Irp,
1339: &Extension->PurgeQueue,
1340: &Extension->CurrentPurgeIrp,
1341: SerialStartPurge
1342: );
1343:
1344: }
1345: case IOCTL_SERIAL_GET_HANDFLOW: {
1346:
1347: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
1348: sizeof(SERIAL_HANDFLOW)) {
1349:
1350: Status = STATUS_BUFFER_TOO_SMALL;
1351: break;
1352:
1353: }
1354:
1355: Irp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
1356:
1357: KeAcquireSpinLock(
1358: &Extension->ControlLock,
1359: &OldIrql
1360: );
1361:
1362: *((PSERIAL_HANDFLOW)Irp->AssociatedIrp.SystemBuffer) =
1363: Extension->HandFlow;
1364:
1365: KeReleaseSpinLock(
1366: &Extension->ControlLock,
1367: OldIrql
1368: );
1369:
1370: break;
1371:
1372: }
1373: case IOCTL_SERIAL_SET_HANDFLOW: {
1374:
1375: SERIAL_IOCTL_SYNC S;
1376: PSERIAL_HANDFLOW HandFlow = Irp->AssociatedIrp.SystemBuffer;
1377:
1378: //
1379: // Make sure that the hand shake and control is the
1380: // right size.
1381: //
1382:
1383: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
1384: sizeof(SERIAL_HANDFLOW)) {
1385:
1386: Status = STATUS_BUFFER_TOO_SMALL;
1387: break;
1388:
1389: }
1390:
1391: //
1392: // Make sure that there are no invalid bits set in
1393: // the control and handshake.
1394: //
1395:
1396: if (HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID) {
1397:
1398: Status = STATUS_INVALID_PARAMETER;
1399: break;
1400:
1401: }
1402:
1403: if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID) {
1404:
1405: Status = STATUS_INVALID_PARAMETER;
1406: break;
1407:
1408: }
1409:
1410: //
1411: // Make sure that the app hasn't set an invlid DTR mode.
1412: //
1413:
1414: if ((HandFlow->ControlHandShake & SERIAL_DTR_MASK) ==
1415: SERIAL_DTR_MASK) {
1416:
1417: Status = STATUS_INVALID_PARAMETER;
1418: break;
1419:
1420: }
1421:
1422: //
1423: // Make sure that haven't set totally invalid xon/xoff
1424: // limits.
1425: //
1426:
1427: if ((HandFlow->XonLimit < 0) ||
1428: ((ULONG)HandFlow->XonLimit > Extension->BufferSize)) {
1429:
1430: Status = STATUS_INVALID_PARAMETER;
1431: break;
1432:
1433: }
1434:
1435: if ((HandFlow->XoffLimit < 0) ||
1436: ((ULONG)HandFlow->XoffLimit > Extension->BufferSize)) {
1437:
1438: Status = STATUS_INVALID_PARAMETER;
1439: break;
1440:
1441: }
1442:
1443: S.Extension = Extension;
1444: S.Data = HandFlow;
1445:
1446: KeAcquireSpinLock(
1447: &Extension->ControlLock,
1448: &OldIrql
1449: );
1450:
1451: //
1452: // Under the protection of the lock, make sure that
1453: // we aren't turning on error replacement when we
1454: // are doing line status/modem status insertion.
1455: //
1456:
1457: if (Extension->EscapeChar) {
1458:
1459: if (HandFlow->FlowReplace & SERIAL_ERROR_CHAR) {
1460:
1461: Status = STATUS_INVALID_PARAMETER;
1462: KeReleaseSpinLock(
1463: &Extension->ControlLock,
1464: OldIrql
1465: );
1466: break;
1467:
1468: }
1469:
1470: }
1471:
1472: KeSynchronizeExecution(
1473: Extension->Interrupt,
1474: SerialSetHandFlow,
1475: &S
1476: );
1477:
1478: KeReleaseSpinLock(
1479: &Extension->ControlLock,
1480: OldIrql
1481: );
1482:
1483: break;
1484:
1485: }
1486: case IOCTL_SERIAL_GET_MODEMSTATUS: {
1487:
1488: SERIAL_IOCTL_SYNC S;
1489:
1490: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
1491: sizeof(ULONG)) {
1492:
1493: Status = STATUS_BUFFER_TOO_SMALL;
1494: break;
1495:
1496: }
1497:
1498: Irp->IoStatus.Information = sizeof(ULONG);
1499:
1500: S.Extension = Extension;
1501: S.Data = Irp->AssociatedIrp.SystemBuffer;
1502:
1503: KeAcquireSpinLock(
1504: &Extension->ControlLock,
1505: &OldIrql
1506: );
1507:
1508: KeSynchronizeExecution(
1509: Extension->Interrupt,
1510: SerialGetModemUpdate,
1511: &S
1512: );
1513:
1514: KeReleaseSpinLock(
1515: &Extension->ControlLock,
1516: OldIrql
1517: );
1518:
1519: break;
1520:
1521: }
1522: case IOCTL_SERIAL_GET_DTRRTS: {
1523:
1524: ULONG ModemControl;
1525: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
1526: sizeof(ULONG)) {
1527:
1528: Status = STATUS_BUFFER_TOO_SMALL;
1529: break;
1530:
1531: }
1532:
1533: Irp->IoStatus.Information = sizeof(ULONG);
1534: Irp->IoStatus.Status = STATUS_SUCCESS;
1535:
1536: //
1537: // Reading this hardware has no effect on the device.
1538: //
1539:
1540: ModemControl = READ_MODEM_CONTROL(Extension->Controller);
1541:
1542: ModemControl &= SERIAL_DTR_STATE | SERIAL_RTS_STATE;
1543:
1544: *(PULONG)Irp->AssociatedIrp.SystemBuffer = ModemControl;
1545:
1546: break;
1547:
1548: }
1549: case IOCTL_SERIAL_GET_COMMSTATUS: {
1550:
1551: SERIAL_IOCTL_SYNC S;
1552:
1553: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
1554: sizeof(SERIAL_STATUS)) {
1555:
1556: Status = STATUS_BUFFER_TOO_SMALL;
1557: break;
1558:
1559: }
1560:
1561: Irp->IoStatus.Information = sizeof(SERIAL_STATUS);
1562:
1563: S.Extension = Extension;
1564: S.Data = Irp->AssociatedIrp.SystemBuffer;
1565:
1566: //
1567: // Acquire the cancel spin lock so nothing much
1568: // changes while were getting the state.
1569: //
1570:
1571: IoAcquireCancelSpinLock(&OldIrql);
1572:
1573: KeSynchronizeExecution(
1574: Extension->Interrupt,
1575: SerialGetCommStatus,
1576: &S
1577: );
1578:
1579: IoReleaseCancelSpinLock(OldIrql);
1580:
1581: break;
1582:
1583: }
1584: case IOCTL_SERIAL_GET_PROPERTIES: {
1585:
1586:
1587: if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
1588: sizeof(SERIAL_COMMPROP)) {
1589:
1590: Status = STATUS_BUFFER_TOO_SMALL;
1591: break;
1592:
1593: }
1594:
1595: //
1596: // No synchronization is required since this information
1597: // is "static".
1598: //
1599:
1600: SerialGetProperties(
1601: Extension,
1602: Irp->AssociatedIrp.SystemBuffer
1603: );
1604:
1605: Irp->IoStatus.Information = sizeof(SERIAL_COMMPROP);
1606: Irp->IoStatus.Status = STATUS_SUCCESS;
1607:
1608: break;
1609: }
1610: case IOCTL_SERIAL_XOFF_COUNTER: {
1611:
1612: PSERIAL_XOFF_COUNTER Xc = Irp->AssociatedIrp.SystemBuffer;
1613:
1614: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
1615: sizeof(SERIAL_XOFF_COUNTER)) {
1616:
1617: Status = STATUS_BUFFER_TOO_SMALL;
1618: break;
1619:
1620: }
1621:
1622: if (Xc->Counter <= 0) {
1623:
1624: Status = STATUS_INVALID_PARAMETER;
1625: break;
1626:
1627: }
1628:
1629: //
1630: // So far so good. Put the irp onto the write queue.
1631: //
1632:
1633: return SerialStartOrQueue(
1634: Extension,
1635: Irp,
1636: &Extension->WriteQueue,
1637: &Extension->CurrentWriteIrp,
1638: SerialStartWrite
1639: );
1640:
1641: }
1642: case IOCTL_SERIAL_LSRMST_INSERT: {
1643:
1644: PUCHAR escapeChar = Irp->AssociatedIrp.SystemBuffer;
1645:
1646: //
1647: // Make sure we get a byte.
1648: //
1649:
1650: if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
1651: sizeof(UCHAR)) {
1652:
1653: Status = STATUS_BUFFER_TOO_SMALL;
1654: break;
1655:
1656: }
1657:
1658: KeAcquireSpinLock(
1659: &Extension->ControlLock,
1660: &OldIrql
1661: );
1662:
1663: if (*escapeChar) {
1664:
1665: //
1666: // We've got some escape work to do. We will make sure that
1667: // the character is not the same as the Xon or Xoff character,
1668: // or that we are already doing error replacement.
1669: //
1670:
1671: if ((*escapeChar == Extension->SpecialChars.XoffChar) ||
1672: (*escapeChar == Extension->SpecialChars.XonChar) ||
1673: (Extension->HandFlow.FlowReplace & SERIAL_ERROR_CHAR)) {
1674:
1675: Status = STATUS_INVALID_PARAMETER;
1676:
1677: KeReleaseSpinLock(
1678: &Extension->ControlLock,
1679: OldIrql
1680: );
1681: break;
1682:
1683: }
1684:
1685: }
1686:
1687: KeSynchronizeExecution(
1688: Extension->Interrupt,
1689: SerialSetEscapeChar,
1690: Irp
1691: );
1692:
1693: KeReleaseSpinLock(
1694: &Extension->ControlLock,
1695: OldIrql
1696: );
1697:
1698: break;
1699:
1700: }
1701: default: {
1702:
1703: Status = STATUS_INVALID_PARAMETER;
1704: break;
1705: }
1706: }
1707:
1708: DoneWithIoctl:;
1709:
1710: Irp->IoStatus.Status = Status;
1711:
1712: SerialDump(
1713: SERIRPPATH,
1714: ("SERIAL: Complete Irp: %x\n",Irp)
1715: );
1716: IoCompleteRequest(
1717: Irp,
1718: 0
1719: );
1720:
1721: return Status;
1722:
1723: }
1724:
1725: VOID
1726: SerialGetProperties(
1727: IN PSERIAL_DEVICE_EXTENSION Extension,
1728: IN PSERIAL_COMMPROP Properties
1729: )
1730:
1731: /*++
1732:
1733: Routine Description:
1734:
1735: This function returns the capabilities of this particular
1736: serial device.
1737:
1738: Arguments:
1739:
1740: Extension - The serial device extension.
1741:
1742: Properties - The structure used to return the properties
1743:
1744: Return Value:
1745:
1746: None.
1747:
1748: --*/
1749:
1750: {
1751:
1752: RtlZeroMemory(
1753: Properties,
1754: sizeof(SERIAL_COMMPROP)
1755: );
1756:
1757: Properties->PacketLength = sizeof(SERIAL_COMMPROP);
1758: Properties->PacketVersion = 2;
1759: Properties->ServiceMask = SERIAL_SP_SERIALCOMM;
1760: Properties->MaxTxQueue = 0;
1761: Properties->MaxRxQueue = 0;
1762:
1763: Properties->MaxBaud = SERIAL_BAUD_USER;
1764: Properties->SettableBaud = Extension->SupportedBauds;
1765:
1766: Properties->ProvSubType = SERIAL_SP_RS232;
1767: Properties->ProvCapabilities = SERIAL_PCF_DTRDSR |
1768: SERIAL_PCF_RTSCTS |
1769: SERIAL_PCF_CD |
1770: SERIAL_PCF_PARITY_CHECK |
1771: SERIAL_PCF_XONXOFF |
1772: SERIAL_PCF_SETXCHAR |
1773: SERIAL_PCF_TOTALTIMEOUTS |
1774: SERIAL_PCF_INTTIMEOUTS;
1775: Properties->SettableParams = SERIAL_SP_PARITY |
1776: SERIAL_SP_BAUD |
1777: SERIAL_SP_DATABITS |
1778: SERIAL_SP_STOPBITS |
1779: SERIAL_SP_HANDSHAKING |
1780: SERIAL_SP_PARITY_CHECK |
1781: SERIAL_SP_CARRIER_DETECT;
1782:
1783:
1784: Properties->SettableData = SERIAL_DATABITS_5 |
1785: SERIAL_DATABITS_6 |
1786: SERIAL_DATABITS_7 |
1787: SERIAL_DATABITS_8;
1788: Properties->SettableStopParity = SERIAL_STOPBITS_10 |
1789: SERIAL_STOPBITS_15 |
1790: SERIAL_STOPBITS_20 |
1791: SERIAL_PARITY_NONE |
1792: SERIAL_PARITY_ODD |
1793: SERIAL_PARITY_EVEN |
1794: SERIAL_PARITY_MARK |
1795: SERIAL_PARITY_SPACE;
1796: Properties->CurrentTxQueue = 0;
1797: Properties->CurrentRxQueue = Extension->BufferSize;
1798:
1799: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.