]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/LibC/Uefi/InteractiveIO/IIO.c
65b61d9bccde4f4c1e5c46a8cc7ea552dfcf37b4
2 Definitions for the Interactive IO library.
4 The functions assume that isatty() is TRUE at the time they are called.
6 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials are licensed and made available
8 under the terms and conditions of the BSD License which accompanies this
9 distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/MemoryAllocationLib.h>
18 #include <LibConfig.h>
22 #include <sys/syslimits.h>
23 #include <sys/termios.h>
24 #include <Device/IIO.h>
26 #include "IIOutilities.h"
27 #include "IIOechoCtrl.h"
29 /** Read from an Interactive IO device.
31 NOTE: If _S_IWTTY is set, the internal buffer contains WIDE characters.
32 They will need to be converted to MBCS when returned.
34 Input is line buffered if ICANON is set,
35 otherwise MIN determines how many characters to input.
36 Currently MIN is always zero, meaning 0 or 1 character is input in
39 @param[in] filp Pointer to the descriptor of the device (file) to be read.
40 @param[in] BufferSize Maximum number of bytes to be returned to the caller.
41 @param[out] Buffer Pointer to the buffer where the input is to be stored.
43 @retval -1 An error occurred. No data is available.
44 @retval 0 No data was available. Try again later.
45 @retval >0 The number of bytes consumed by the returned data.
51 struct __filedes
*filp
,
65 Flags
= This
->Termio
.c_lflag
;
67 NumRead
= IIO_CanonRead(filp
);
70 NumRead
= IIO_NonCanonRead(filp
);
72 // At this point, the input has been accumulated in the input buffer.
73 if(filp
->f_iflags
& _S_IWTTY
) {
74 // Data in InBuf is wide characters. Convert to MBCS
75 // First, convert into a linear buffer
76 NumRead
= This
->InBuf
->Copy(This
->InBuf
, gMD
->UString2
, (INT32
)UNICODE_STRING_MAX
-1);
77 gMD
->UString2
[NumRead
] = 0; // Ensure that the buffer is terminated
78 // Determine the needed space
79 XlateSz
= EstimateWtoM((const wchar_t *)gMD
->UString2
, BufferSize
, &Needed
);
81 // Now translate this into MBCS in Buffer
82 NumRead
= wcstombs((char *)Buffer
, (const wchar_t *)gMD
->UString2
, XlateSz
);
84 // Consume the translated characters
85 (void)This
->InBuf
->Flush(This
->InBuf
, Needed
);
88 // Data in InBuf is narrow characters. Use verbatim.
89 NumRead
= This
->InBuf
->Read(This
->InBuf
, Buffer
, (INT32
)BufferSize
);
95 /** Process characters from buffer buf and write them to the output device
98 @param[in] filp Pointer to a file descriptor structure.
99 @param[in] buf Pointer to the MBCS string to be output.
100 @param[in] N Number of bytes in buf.
102 @retval >=0 Number of bytes sent to the output device.
108 struct __filedes
*filp
,
122 wchar_t OutChar
[2]; // Just in case we run into 4-byte MBCS character
125 errno
= 0; // indicate no error as default
128 /* Determine what the current screen size is. Also validates the output device. */
129 OutMode
= IIO_GetOutputSize(filp
->MyFD
, &MaxColumn
, &MaxRow
);
131 This
= filp
->devdata
;
132 if((This
!= NULL
) && (OutMode
>= 0)) {
133 if(filp
->MyFD
== STDERR_FILENO
) {
134 OutBuf
= This
->ErrBuf
;
135 OutState
= &This
->ErrState
;
138 OutBuf
= This
->OutBuf
;
139 OutState
= &This
->OutState
;
142 /* Set the maximum screen dimensions. */
143 This
->MaxColumn
= MaxColumn
;
144 This
->MaxRow
= MaxRow
;
146 /* Record where the cursor is at the beginning of the Output operation. */
147 (void)IIO_GetCursorPosition(filp
->MyFD
, &This
->InitialXY
.Column
, &This
->InitialXY
.Row
);
148 This
->CurrentXY
.Column
= This
->InitialXY
.Column
;
149 This
->CurrentXY
.Row
= This
->InitialXY
.Row
;
153 OutChar
[0] = (wchar_t)buf
[0];
154 while((OutChar
[0] != 0) && (NumWritten
< N
)) {
155 CharLen
= mbrtowc(OutChar
, (const char *)&buf
[NumWritten
], MB_CUR_MAX
, OutState
);
156 NumProc
= IIO_WriteOne(filp
, OutBuf
, OutChar
[0]);
158 // Successfully processed and buffered one character
159 NumWritten
+= CharLen
; // Index of start of next character
161 else if(NumProc
== -1) {
163 (void)mbrtowc(NULL
, NULL
, 1, OutState
); // Re-Initialize the conversion state
168 // Last character was incomplete
172 // At this point, the characters to write are in OutBuf
173 // First, linearize the buffer
174 NumWritten
= OutBuf
->Copy(OutBuf
, gMD
->UString
, UNICODE_STRING_MAX
-1);
175 gMD
->UString
[NumWritten
] = 0; // Ensure that the buffer is terminated
177 if(filp
->f_iflags
& _S_IWTTY
) {
178 // Output device expects wide characters, Output what we have
179 NumWritten
= filp
->f_ops
->fo_write(filp
, NULL
, NumWritten
, gMD
->UString
);
182 // Output device expects narrow characters, convert to MBCS
183 MbcsPtr
= (char *)gMD
->UString2
;
184 // Determine the needed space
185 NumProc
= (ssize_t
)EstimateWtoM((const wchar_t *)gMD
->UString
, UNICODE_STRING_MAX
* sizeof(wchar_t), &CharLen
);
187 // Now translate this into MBCS in Buffer
188 NumWritten
= wcstombs(MbcsPtr
, (const wchar_t *)gMD
->UString
, NumProc
);
189 MbcsPtr
[NumWritten
] = 0; // Ensure the buffer is terminated
191 // Send the MBCS buffer to Output
192 NumWritten
= filp
->f_ops
->fo_write(filp
, NULL
, NumWritten
, MbcsPtr
);
194 // Consume the translated characters
195 (void)OutBuf
->Flush(OutBuf
, NumWritten
);
201 // Otherwise, errno is already set.
206 /** Echo a character to an output device.
207 Performs translation and edit processing depending upon termios flags.
209 @param[in] filp A pointer to a file descriptor structure.
210 @param[in] EChar The character to echo.
211 @param[in] EchoIsOK TRUE if the caller has determined that characters
212 should be echoed. Otherwise, just buffer.
214 @return Returns the number of characters actually output.
220 struct __filedes
*filp
,
233 This
= filp
->devdata
;
235 OutBuf
= This
->OutBuf
;
236 LFlags
= This
->Termio
.c_lflag
& (ECHOK
| ECHOE
);
238 if((EChar
>= TtyFunKeyMin
) && (EChar
< TtyFunKeyMax
)) {
239 // A special function key was pressed, buffer it, don't echo, and activate.
240 // Process and buffer the character. May produce multiple characters.
241 NumProc
= IIO_EchoOne(filp
, EChar
, FALSE
); // Don't echo this character
242 EChar
= CHAR_LINEFEED
; // Every line must end with '\n' (legacy)
244 // Process and buffer the character. May produce multiple characters.
245 NumProc
= IIO_EchoOne(filp
, EChar
, EchoIsOK
);
247 // At this point, the character(s) to write are in OutBuf
248 // First, linearize the buffer
249 NumWritten
= OutBuf
->Copy(OutBuf
, gMD
->UString
, UNICODE_STRING_MAX
-1);
250 gMD
->UString
[NumWritten
] = 0; // Ensure that the buffer is terminated
252 if((EChar
== IIO_ECHO_KILL
) && (LFlags
& ECHOE
) && EchoIsOK
) {
253 // Position the cursor to the start of input.
254 (void)IIO_SetCursorPosition(filp
, &This
->InitialXY
);
257 if(filp
->f_iflags
& _S_IWTTY
) {
258 // Output device expects wide characters, Output what we have
259 NumWritten
= filp
->f_ops
->fo_write(filp
, NULL
, NumWritten
, gMD
->UString
);
262 // Output device expects narrow characters, convert to MBCS
263 MbcsPtr
= (char *)gMD
->UString2
;
264 // Determine the needed space
265 NumProc
= (ssize_t
)EstimateWtoM((const wchar_t *)gMD
->UString
, UNICODE_STRING_MAX
* sizeof(wchar_t), NULL
);
267 // Now translate this into MBCS in Buffer
268 NumWritten
= wcstombs(MbcsPtr
, (const wchar_t *)gMD
->UString
, NumProc
);
269 MbcsPtr
[NumWritten
] = 0; // Ensure the buffer is terminated
271 // Send the MBCS buffer to Output
272 NumWritten
= filp
->f_ops
->fo_write(filp
, NULL
, NumWritten
, MbcsPtr
);
274 // Consume the echoed characters
275 (void)OutBuf
->Flush(OutBuf
, NumWritten
);
277 if(EChar
== IIO_ECHO_KILL
) {
278 if(LFlags
== ECHOK
) {
279 NumWritten
= IIO_WriteOne(filp
, OutBuf
, CHAR_LINEFEED
);
281 else if((LFlags
& ECHOE
) && EchoIsOK
) {
282 // Position the cursor to the start of input.
283 (void)IIO_SetCursorPosition(filp
, &This
->InitialXY
);
297 FifoDelete(cFIFO
*Member
)
300 Member
->Delete(Member
);
304 /** Destructor for an IIO instance.
306 Releases all resources used by a particular IIO instance.
316 FifoDelete(Self
->ErrBuf
);
317 FifoDelete(Self
->OutBuf
);
318 FifoDelete(Self
->InBuf
);
319 if(Self
->AttrBuf
!= NULL
) {
320 FreePool(Self
->AttrBuf
);
326 /** Constructor for new IIO instances.
328 @return Returns NULL or a pointer to a new IIO instance.
338 IIO
= (cIIO
*)AllocateZeroPool(sizeof(cIIO
));
340 IIO
->InBuf
= New_cFIFO(MAX_INPUT
, sizeof(wchar_t));
341 IIO
->OutBuf
= New_cFIFO(MAX_OUTPUT
, sizeof(wchar_t));
342 IIO
->ErrBuf
= New_cFIFO(MAX_OUTPUT
, sizeof(wchar_t));
343 IIO
->AttrBuf
= (UINT8
*)AllocateZeroPool(MAX_OUTPUT
);
345 if((IIO
->InBuf
== NULL
) || (IIO
->OutBuf
== NULL
) ||
346 (IIO
->ErrBuf
== NULL
) || (IIO
->AttrBuf
== NULL
))
352 IIO
->Delete
= IIO_Delete
;
353 IIO
->Read
= IIO_Read
;
354 IIO
->Write
= IIO_Write
;
355 IIO
->Echo
= IIO_Echo
;
357 // Initialize Termio member
358 TempBuf
= &IIO
->Termio
.c_cc
[0];
359 TempBuf
[0] = 8; // Default length for TABs
360 for(i
=1; i
< NCCS
; ++i
) {
361 TempBuf
[i
] = _POSIX_VDISABLE
;
365 IIO
->Termio
.c_ispeed
= B115200
;
366 IIO
->Termio
.c_ospeed
= B115200
;
367 IIO
->Termio
.c_iflag
= ICRNL
;
368 IIO
->Termio
.c_oflag
= OPOST
| ONLCR
| ONOCR
| ONLRET
;
369 IIO
->Termio
.c_cflag
= 0;
370 IIO
->Termio
.c_lflag
= ECHO
| ECHONL
;