?? winuart.c
字號(hào):
/* winuart.c
Copyright 1991-1996 by NetPort Software
Copyright 1997-2001 by InterNIche Technologies Inc.
This implements a UART driver for PPP on Windows. The underlying
microsoft drivers are pretty bad, but hopefully good enough for a
demo.
*/
/* Microsoft Can't even get their sad-sack C code includes to compile
* cleanly, even with their own compiler. Disable the warnings here
* so that we can include windows.h without problems.
*/
#pragma warning(disable: 4244 4310 4115)
#include <windows.h>
#undef FAR
#include "ipport.h"
#ifdef USE_COMPORT
#include "winuart.h"
#include "nvparms.h"
int comport; /* the "default" com port (for ..\modem\mdmport.c) */
/* table for mapping logical UART units to PC Com ports */
int comport_map[MAXUNITS]; /* map logical units to PC com ports */
struct com_win com_ports[MAXCOMMS];
/* uart_init() - PC UART init entry point. Fully installs & enables
the UART, including exit_hook() for closing.
Returns 0 if OK, else non-zero.
*/
char comfile[] = {"//./COM1" }; /* COM device name for CreateFile() */
int
uart_init(int unit)
{
int comport; /* com1, com2, etc. - get from NV parms */
int err;
struct com_win * com; /* our window comm manager struct */
COMMTIMEOUTS timeouts; /* more crusty windows stuff */
DCB dcb; /* ... */
/* sanity check parameters */
if(unit < 0 || unit > MAXUNITS)
return -1;
comport = comportcfg.comport+'0'; /* convert 0x01 to '1' */
if(comport < '1' || comport > (MAXCOMMS+'0') )
{
dprintf("pcuart: bad comport: %c\n", comport);
return ENP_LOGIC;
}
comfile[7] = (char)comport; /* patch "COMX" device name */
comport -= '1'; /* make comport into comport_map index */
/* On windows the first unit to set up gets the comport from nvparms,
* the next unit (if any) gets the other com port. We only use the
* two standard ones on this port.
*/
if(unit == 0)
comport_map[unit] = comport;
else /* second unit, use other comport */
{
if(comport == 0)
comport_map[unit] = comport = 1;
else
comport_map[unit] = comport = 0;
}
com = &com_ports[comport];
if(com->uart_open == unit - 1) /* it's open, nothing to do */
{
dtrap(); /* shouldn't happen anymore */
return 0; /* return "up" code */
}
/* Windozey UART API prentends it's a file (it seems they
* only borrow the stupid ideas from UNIX) - so call
* CreateFile() with no share, no security:
*/
com->dev = CreateFile(comfile, GENERIC_READ|GENERIC_WRITE,
0, 0, OPEN_EXISTING, 0, NULL);
if(com->dev == INVALID_HANDLE_VALUE)
{
err = GetLastError();
dprintf("Error %d opening windows serial device\n", err);
return ENP_LOGIC;
}
err = GetCommState(com->dev, &dcb);
if(err == FALSE) /* check boolean return */
{
dtrap(); /* Can this happen? */
return ENP_LOGIC;
}
/* usually defaults to baud 1200, no parity, 8 data bits, 1 stop bit
* DTR ENABLE. Set up what modems generally work well with:
*/
dcb.BaudRate = CBR_57600;
dcb.ByteSize = 8;
dcb.fBinary = TRUE;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
err = SetCommState(com->dev, &dcb);
if(err == FALSE) /* check boolean return */
{
dtrap(); /* Comm port setup failed... */
err = GetLastError();
return ENP_LOGIC;
}
err = GetCommTimeouts(com->dev, &timeouts);
if(err == FALSE) /* check boolean return */
{
dtrap(); /* Can this happen? */
return ENP_LOGIC;
}
com->baudrate = dcb.BaudRate; /* record baud in local struct */
timeouts.ReadIntervalTimeout = MAXDWORD; /* immediate read return */
err = SetCommTimeouts(com->dev, &timeouts);
if(err == FALSE) /* check boolean return */
{
dtrap(); /* Can this happen? */
return ENP_LOGIC;
}
com->uart_open = unit - 1;
exit_hook(uart_closehook);
return 0; /* OK return */
}
/* void uart_putc(unit, char) - puts a byte out serial port.
Returns 0 in AX if OK, else -1 if RDY timeout.
*/
int
uart_putc(int unit, u_char outchar)
{
struct com_win * com;
u_long done;
int err;
if(unit < 0 || unit > MAXUNITS)
return -1;
com = &com_ports[comport_map[unit]];
/* punt if the uart is not initialized. This means we have
* to consider 0 an invalid handle value, although technically
* it seems to be legal.
*/
if((com->dev == INVALID_HANDLE_VALUE) ||
(com->dev == 0))
{
return -1;
}
err = WriteFile(com->dev, &outchar, 1, &done, NULL);
if((err == 0) || (done != 1))
{
dtrap()
return -1;
}
com->uart_out++;
return 0;
}
/* uart_getc() - get the next character from the uart input buffer.
Returns a 16 or 32 bit value. If a char is ready, the upper bits are zero
and the lower 8 bits have the byte value. If no char is ready, all bits
are SET (ie, 16 bit value is 0xFFFF)
*/
int
uart_getc(int unit)
{
int err;
int retchar;
u_long rlen;
struct com_win * com;
if(unit < 0 || unit > MAXUNITS)
return -1;
com = &com_ports[comport_map[unit]];
if(com->dev == INVALID_HANDLE_VALUE)
{
return -1;
}
rlen = 0;
err = ReadFile(com->dev, &retchar, 1, &rlen, NULL);
if(err == 0) /* test boolean return */
{
err = GetLastError();
if(rlen != 0)
{
dtrap();
}
switch (err)
{
case 0x03e4: /* Overlapped I/O event is not in a signaled state */
case 0x03e5: /* Overlapped I/O operation is in progress. */
case 0x0006: /* Bad Handle */
break;
default:
dprintf("UART ReadFile error %d\n", err);
break;
}
return -1;
}
if(rlen != 1)
{
return -1;
}
com->uart_gets++;
return (retchar & 0x000000FF);
}
/* uart_ready() - Returns true (0xFFFF) if UART is ready to send
a character, FALSE (0) if not. This allows a non-blocking UART send
routine to be written in C.
*/
int
uart_ready(int unit)
{
struct com_win * com;
if(unit < 0 || unit > MAXUNITS)
return -1;
com = &com_ports[comport_map[unit]];
if(com->dev == INVALID_HANDLE_VALUE)
return FALSE;
else
return TRUE;
}
/* void uart_close(void) - shut down UART
*/
void uart_close(int unit)
{
struct com_win * com;
if(unit < 0 || unit > MAXUNITS)
{
dtrap();
return;
}
com = &com_ports[comport_map[unit]];
CloseHandle(com->dev); /* best effort */
/* clean up com_port struct */
com->uart_open = unit;
com->dev = INVALID_HANDLE_VALUE;
}
/* exit_hook to close all uarts. We close them all becasue we have no
mechanism to pass a unit parameter through exit_hook
*/
void
uart_closehook()
{
int unit;
struct com_win * com;
dprintf("uart: closing com ports\n");
for(unit = 0; unit < MAXUNITS; unit++)
{
com = &com_ports[comport_map[unit]];
if(com->uart_open != unit - 1)
continue;
uart_close(unit);
dprintf("uart: closed com%d\n", comport_map[unit] + 1);
}
}
#ifdef NET_STATS
int
uart_stats(void * pio, int unit)
{
int comport;
int err;
struct com_win * com;
DCB dcb;
char * sbits; /* stop bits string */
char ptypes[5] = { 'N', 'O', 'E', 'M', 'S' }; /* parity types */
comport = comport_map[unit];
com = &com_ports[comport];
if(com->uart_unit != unit)
{
dtrap();
}
ns_printf(pio, " Win32 COM device status; handle:%x unit:%d:\n",
com->dev, unit);
ns_printf(pio,"Com port is Com%d\n", comport+1);
ns_printf(pio, "uart_gets: %ld, uart_puts:%ld, set baud: %ld\n",
com->uart_gets, com->uart_out, com->baudrate);
ns_printf(pio,"send timeouts: %u\n", com->uart_tmo);
err = GetCommState(com->dev, &dcb);
switch(dcb.StopBits) /* set string for stop bits */
{
case 0:
sbits = "1";
break;
case 1:
sbits = "1.5";
break;
case 2:
sbits = "2";
break;
default:
sbits = "foo";
};
ns_printf(pio, "actual Baudrate:%d, Parity %c, data bits %d, stop bits %s\n",
dcb.BaudRate, ptypes[dcb.Parity], dcb.ByteSize, sbits);
ns_printf(pio, "FLAGS: Binary Mode %d, parity enable %d, handshaking: CTS %d, DSR %d\n",
dcb.fBinary, dcb.fParity, dcb.fOutxCtsFlow, dcb.fOutxDsrFlow);
ns_printf(pio, "FLAGS: DTR Flow %d, DSR Sensitivity %d, TX when Xoff %d, Err Replacement %d\n",
dcb.fDtrControl, dcb.fDsrSensitivity, dcb.fTXContinueOnXoff, dcb.fErrorChar);
ns_printf(pio, "FLAGS: Null stripping %d, Rts Flow control %d, Abort on Error %d\n",
dcb.fNull, dcb.fRtsControl, dcb.fAbortOnError);
if(dcb.fOutX ||dcb.fInX)
{
ns_printf(pio, "fOutX:%d, fInX:%d\n", dcb.fOutX, dcb.fInX);
ns_printf(pio, "X-ON char:0x%x, X-OFF char:0x%x, Thresholds, XON %d, XOFF %d\n",
dcb.XonLim, dcb.XoffLim, dcb.XonChar, dcb.XoffChar);
}
return 0;
}
#endif /* NET_STATS */
#endif /* USE_COMPORT */
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -