Split UART implementations: POSIX and Windows
It could ease to port to other system like MiKey and it should be easy to track which is the concerned OS while uart driver is modified.
This commit is contained in:
parent
58dcf63e7c
commit
835823809f
4 changed files with 467 additions and 430 deletions
164
libnfc/buses/uart_win32.c
Normal file
164
libnfc/buses/uart_win32.c
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*-
|
||||
* Public platform independent Near Field Communication (NFC) library
|
||||
*
|
||||
* Copyright (C) 2009, 2010, Roel Verdult, Romuald Conty
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file uart.c
|
||||
* @brief Windows UART driver
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
HANDLE hPort; // Serial port handle
|
||||
DCB dcb; // Device control settings
|
||||
COMMTIMEOUTS ct; // Serial port time-out configuration
|
||||
} serial_port_windows;
|
||||
|
||||
serial_port
|
||||
uart_open (const char *pcPortName)
|
||||
{
|
||||
char acPortName[255];
|
||||
serial_port_windows *sp = malloc (sizeof (serial_port_windows));
|
||||
|
||||
// Copy the input "com?" to "\\.\COM?" format
|
||||
sprintf (acPortName, "\\\\.\\%s", pcPortName);
|
||||
_strupr (acPortName);
|
||||
|
||||
// Try to open the serial port
|
||||
sp->hPort = CreateFileA (acPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (sp->hPort == INVALID_HANDLE_VALUE) {
|
||||
uart_close (sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Prepare the device control
|
||||
memset (&sp->dcb, 0, sizeof (DCB));
|
||||
sp->dcb.DCBlength = sizeof (DCB);
|
||||
if (!BuildCommDCBA ("baud=9600 data=8 parity=N stop=1", &sp->dcb)) {
|
||||
uart_close (sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Update the active serial port
|
||||
if (!SetCommState (sp->hPort, &sp->dcb)) {
|
||||
uart_close (sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
sp->ct.ReadIntervalTimeout = 30;
|
||||
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
||||
sp->ct.ReadTotalTimeoutConstant = 30;
|
||||
sp->ct.WriteTotalTimeoutMultiplier = 30;
|
||||
sp->ct.WriteTotalTimeoutConstant = 0;
|
||||
|
||||
if (!SetCommTimeouts (sp->hPort, &sp->ct)) {
|
||||
uart_close (sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
PurgeComm (sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
void
|
||||
uart_close (const serial_port sp)
|
||||
{
|
||||
if (((serial_port_windows *) sp)->hPort != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle (((serial_port_windows *) sp)->hPort);
|
||||
}
|
||||
free (sp);
|
||||
}
|
||||
|
||||
// TODO Remove PN53x related timeout
|
||||
void
|
||||
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
||||
{
|
||||
serial_port_windows *spw;
|
||||
|
||||
DBG ("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
|
||||
// Set port speed (Input and Output)
|
||||
switch (uiPortSpeed) {
|
||||
case 9600:
|
||||
case 19200:
|
||||
case 38400:
|
||||
case 57600:
|
||||
case 115200:
|
||||
case 230400:
|
||||
case 460800:
|
||||
break;
|
||||
default:
|
||||
ERR("Unable to set serial port speed to %d bauds. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed);
|
||||
return;
|
||||
};
|
||||
spw = (serial_port_windows *) sp;
|
||||
|
||||
// Set timeouts
|
||||
//printf ("UART_SPEED_T0_TIME (%d) = %d\n", uiPortSpeed, UART_SPEED_T0_TIME(uiPortSpeed));
|
||||
int iTimeout = 200;
|
||||
spw->ct.ReadIntervalTimeout = 2;
|
||||
spw->ct.ReadTotalTimeoutMultiplier = 0;
|
||||
spw->ct.ReadTotalTimeoutConstant = iTimeout;
|
||||
spw->ct.WriteTotalTimeoutMultiplier = iTimeout;
|
||||
spw->ct.WriteTotalTimeoutConstant = 0;
|
||||
|
||||
if (!SetCommTimeouts (spw->hPort, &spw->ct)) {
|
||||
ERR ("Unable to apply new timeout settings.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set baud rate
|
||||
spw->dcb.BaudRate = uiPortSpeed;
|
||||
if (!SetCommState (spw->hPort, &spw->dcb)) {
|
||||
ERR ("Unable to apply new speed settings.");
|
||||
return;
|
||||
}
|
||||
PurgeComm (spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
uart_get_speed (const serial_port sp)
|
||||
{
|
||||
const serial_port_windows *spw = (serial_port_windows *) sp;
|
||||
if (!GetCommState (spw->hPort, (serial_port) & spw->dcb))
|
||||
return spw->dcb.BaudRate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
|
||||
{
|
||||
if (!ReadFile (((serial_port_windows *) sp)->hPort, pbtRx, (DWORD)(*pszRx), (LPDWORD) pszRx, NULL)) {
|
||||
return DEIO;
|
||||
}
|
||||
if (!*pszRx)
|
||||
return DEIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx)
|
||||
{
|
||||
DWORD dwTxLen = 0;
|
||||
if (!WriteFile (((serial_port_windows *) sp)->hPort, pbtTx, szTx, &dwTxLen, NULL)) {
|
||||
return DEIO;
|
||||
}
|
||||
if (!dwTxLen)
|
||||
return DEIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue