libnfc 1.4.2
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library 00003 * 00004 * Copyright (C) 2009, 2010, Roel Verdult, Romuald Conty 00005 * 00006 * This program is free software: you can redistribute it and/or modify it 00007 * under the terms of the GNU Lesser General Public License as published by the 00008 * Free Software Foundation, either version 3 of the License, or (at your 00009 * option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, but WITHOUT 00012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00014 * more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 * 00019 */ 00020 00026 typedef struct { 00027 HANDLE hPort; // Serial port handle 00028 DCB dcb; // Device control settings 00029 COMMTIMEOUTS ct; // Serial port time-out configuration 00030 } serial_port_windows; 00031 00032 serial_port 00033 uart_open (const char *pcPortName) 00034 { 00035 char acPortName[255]; 00036 serial_port_windows *sp = malloc (sizeof (serial_port_windows)); 00037 00038 // Copy the input "com?" to "\\.\COM?" format 00039 sprintf (acPortName, "\\\\.\\%s", pcPortName); 00040 _strupr (acPortName); 00041 00042 // Try to open the serial port 00043 sp->hPort = CreateFileA (acPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 00044 if (sp->hPort == INVALID_HANDLE_VALUE) { 00045 uart_close (sp); 00046 return INVALID_SERIAL_PORT; 00047 } 00048 // Prepare the device control 00049 memset (&sp->dcb, 0, sizeof (DCB)); 00050 sp->dcb.DCBlength = sizeof (DCB); 00051 if (!BuildCommDCBA ("baud=9600 data=8 parity=N stop=1", &sp->dcb)) { 00052 uart_close (sp); 00053 return INVALID_SERIAL_PORT; 00054 } 00055 // Update the active serial port 00056 if (!SetCommState (sp->hPort, &sp->dcb)) { 00057 uart_close (sp); 00058 return INVALID_SERIAL_PORT; 00059 } 00060 00061 sp->ct.ReadIntervalTimeout = 30; 00062 sp->ct.ReadTotalTimeoutMultiplier = 0; 00063 sp->ct.ReadTotalTimeoutConstant = 30; 00064 sp->ct.WriteTotalTimeoutMultiplier = 30; 00065 sp->ct.WriteTotalTimeoutConstant = 0; 00066 00067 if (!SetCommTimeouts (sp->hPort, &sp->ct)) { 00068 uart_close (sp); 00069 return INVALID_SERIAL_PORT; 00070 } 00071 00072 PurgeComm (sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); 00073 00074 return sp; 00075 } 00076 00077 void 00078 uart_close (const serial_port sp) 00079 { 00080 if (((serial_port_windows *) sp)->hPort != INVALID_HANDLE_VALUE) { 00081 CloseHandle (((serial_port_windows *) sp)->hPort); 00082 } 00083 free (sp); 00084 } 00085 00086 // TODO Remove PN53x related timeout 00087 void 00088 uart_set_speed (serial_port sp, const uint32_t uiPortSpeed) 00089 { 00090 serial_port_windows *spw; 00091 00092 DBG ("Serial port speed requested to be set to %d bauds.", uiPortSpeed); 00093 // Set port speed (Input and Output) 00094 switch (uiPortSpeed) { 00095 case 9600: 00096 case 19200: 00097 case 38400: 00098 case 57600: 00099 case 115200: 00100 case 230400: 00101 case 460800: 00102 break; 00103 default: 00104 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); 00105 return; 00106 }; 00107 spw = (serial_port_windows *) sp; 00108 00109 // Set timeouts 00110 //printf ("UART_SPEED_T0_TIME (%d) = %d\n", uiPortSpeed, UART_SPEED_T0_TIME(uiPortSpeed)); 00111 int iTimeout = 200; 00112 spw->ct.ReadIntervalTimeout = 2; 00113 spw->ct.ReadTotalTimeoutMultiplier = 0; 00114 spw->ct.ReadTotalTimeoutConstant = iTimeout; 00115 spw->ct.WriteTotalTimeoutMultiplier = iTimeout; 00116 spw->ct.WriteTotalTimeoutConstant = 0; 00117 00118 if (!SetCommTimeouts (spw->hPort, &spw->ct)) { 00119 ERR ("Unable to apply new timeout settings."); 00120 return; 00121 } 00122 00123 // Set baud rate 00124 spw->dcb.BaudRate = uiPortSpeed; 00125 if (!SetCommState (spw->hPort, &spw->dcb)) { 00126 ERR ("Unable to apply new speed settings."); 00127 return; 00128 } 00129 PurgeComm (spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR); 00130 } 00131 00132 uint32_t 00133 uart_get_speed (const serial_port sp) 00134 { 00135 const serial_port_windows *spw = (serial_port_windows *) sp; 00136 if (!GetCommState (spw->hPort, (serial_port) & spw->dcb)) 00137 return spw->dcb.BaudRate; 00138 00139 return 0; 00140 } 00141 00142 int 00143 uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx) 00144 { 00145 if (!ReadFile (((serial_port_windows *) sp)->hPort, pbtRx, (DWORD)(*pszRx), (LPDWORD) pszRx, NULL)) { 00146 return DEIO; 00147 } 00148 if (!*pszRx) 00149 return DEIO; 00150 return 0; 00151 } 00152 00153 int 00154 uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx) 00155 { 00156 DWORD dwTxLen = 0; 00157 if (!WriteFile (((serial_port_windows *) sp)->hPort, pbtTx, szTx, &dwTxLen, NULL)) { 00158 return DEIO; 00159 } 00160 if (!dwTxLen) 00161 return DEIO; 00162 return 0; 00163 } 00164