libnfc 1.3.9
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library 00003 * 00004 * Copyright (C) 2009, Roel Verdult 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 00025 #ifdef HAVE_CONFIG_H 00026 # include "config.h" 00027 #endif // HAVE_CONFIG_H 00028 00029 #include "../drivers.h" 00030 00031 #include <stdio.h> 00032 #include <string.h> 00033 00034 #include "pn532_uart.h" 00035 00036 #include <nfc/nfc.h> 00037 #include <nfc/nfc-messages.h> 00038 00039 // Bus 00040 #include "uart.h" 00041 00042 #define BUFFER_LENGTH 256 00043 00044 #define SERIAL_DEFAULT_PORT_SPEED 115200 00045 00046 void pn532_uart_wakeup (const nfc_device_spec_t nds); 00047 bool pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success); 00048 00049 nfc_device_desc_t * 00050 pn532_uart_pick_device (void) 00051 { 00052 nfc_device_desc_t *pndd; 00053 00054 if ((pndd = malloc (sizeof (*pndd)))) { 00055 size_t szN; 00056 00057 if (!pn532_uart_list_devices (pndd, 1, &szN)) { 00058 DBG ("%s", "pn532_uart_list_devices failed"); 00059 return NULL; 00060 } 00061 00062 if (szN == 0) { 00063 DBG ("%s", "No device found"); 00064 return NULL; 00065 } 00066 } 00067 00068 return pndd; 00069 } 00070 00071 bool 00072 pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound) 00073 { 00077 #ifndef SERIAL_AUTOPROBE_ENABLED 00078 (void) pnddDevices; 00079 (void) szDevices; 00080 *pszDeviceFound = 0; 00081 DBG ("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe."); 00082 return false; 00083 #else /* SERIAL_AUTOPROBE_ENABLED */ 00084 *pszDeviceFound = 0; 00085 00086 serial_port sp; 00087 const char *pcPorts[] = DEFAULT_SERIAL_PORTS; 00088 const char *pcPort; 00089 int iDevice = 0; 00090 00091 while ((pcPort = pcPorts[iDevice++])) { 00092 sp = uart_open (pcPort); 00093 DBG ("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED); 00094 00095 if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) { 00096 bool bComOk; 00097 // Serial port claimed but we need to check if a PN532_UART is connected. 00098 uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED); 00099 // PN532 could be powered down, we need to wake it up before line testing. 00100 pn532_uart_wakeup ((nfc_device_spec_t) sp); 00101 // Check communication using "Diagnose" command, with "Comunication test" (0x00) 00102 if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk)) 00103 return false; 00104 if (!bComOk) 00105 continue; 00106 uart_close (sp); 00107 00108 snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort); 00109 pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0'; 00110 pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME; 00111 pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort); 00112 pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED; 00113 DBG ("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice); 00114 (*pszDeviceFound)++; 00115 00116 // Test if we reach the maximum "wanted" devices 00117 if ((*pszDeviceFound) >= szDevices) 00118 break; 00119 } 00120 # ifdef DEBUG 00121 if (sp == INVALID_SERIAL_PORT) 00122 DBG ("Invalid serial port: %s", pcPort); 00123 if (sp == CLAIMED_SERIAL_PORT) 00124 DBG ("Serial port already claimed: %s", pcPort); 00125 # endif 00126 /* DEBUG */ 00127 } 00128 #endif /* SERIAL_AUTOPROBE_ENABLED */ 00129 return true; 00130 } 00131 00132 nfc_device_t * 00133 pn532_uart_connect (const nfc_device_desc_t * pndd) 00134 { 00135 serial_port sp; 00136 nfc_device_t *pnd = NULL; 00137 bool bComOk; 00138 00139 DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed); 00140 sp = uart_open (pndd->pcPort); 00141 00142 if (sp == INVALID_SERIAL_PORT) 00143 ERR ("Invalid serial port: %s", pndd->pcPort); 00144 if (sp == CLAIMED_SERIAL_PORT) 00145 ERR ("Serial port already claimed: %s", pndd->pcPort); 00146 if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) 00147 return NULL; 00148 00149 uart_set_speed (sp, pndd->uiSpeed); 00150 00151 // PN532 could be powered down, we need to wake it up before line testing. 00152 pn532_uart_wakeup ((nfc_device_spec_t) sp); 00153 // Check communication using "Diagnose" command, with "Comunication test" (0x00) 00154 if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk)) 00155 return NULL; 00156 if (!bComOk) 00157 return NULL; 00158 00159 DBG ("Successfully connected to: %s", pndd->pcPort); 00160 00161 // We have a connection 00162 pnd = malloc (sizeof (nfc_device_t)); 00163 strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1); 00164 pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0'; 00165 00166 pnd->nc = NC_PN532; 00167 pnd->nds = (nfc_device_spec_t) sp; 00168 pnd->bActive = true; 00169 pnd->bCrc = true; 00170 pnd->bPar = true; 00171 pnd->ui8TxBits = 0; 00172 return pnd; 00173 } 00174 00175 void 00176 pn532_uart_disconnect (nfc_device_t * pnd) 00177 { 00178 uart_close ((serial_port) pnd->nds); 00179 free (pnd); 00180 } 00181 00182 bool 00183 pn532_uart_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx, 00184 size_t * pszRxLen) 00185 { 00186 byte_t abtTxBuf[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" 00187 byte_t abtRxBuf[BUFFER_LENGTH]; 00188 size_t szRxBufLen = BUFFER_LENGTH; 00189 size_t szPos; 00190 int res; 00191 // TODO: Move this one level up for libnfc-1.6 00192 uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; 00193 00194 // Packet length = data length (len) + checksum (1) + end of stream marker (1) 00195 abtTxBuf[3] = szTxLen; 00196 // Packet length checksum 00197 abtTxBuf[4] = BUFFER_LENGTH - abtTxBuf[3]; 00198 // Copy the PN53X command into the packet buffer 00199 memmove (abtTxBuf + 5, pbtTx, szTxLen); 00200 00201 // Calculate data payload checksum 00202 abtTxBuf[szTxLen + 5] = 0; 00203 for (szPos = 0; szPos < szTxLen; szPos++) { 00204 abtTxBuf[szTxLen + 5] -= abtTxBuf[szPos + 5]; 00205 } 00206 00207 // End of stream marker 00208 abtTxBuf[szTxLen + 6] = 0; 00209 00210 #ifdef DEBUG 00211 PRINT_HEX ("TX", abtTxBuf, szTxLen + 7); 00212 #endif 00213 res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTxLen + 7); 00214 if (res != 0) { 00215 ERR ("%s", "Unable to transmit data. (TX)"); 00216 pnd->iLastError = res; 00217 return false; 00218 } 00219 00220 res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen); 00221 if (res != 0) { 00222 ERR ("%s", "Unable to receive data. (RX)"); 00223 pnd->iLastError = res; 00224 return false; 00225 } 00226 #ifdef DEBUG 00227 PRINT_HEX ("RX", abtRxBuf, szRxBufLen); 00228 #endif 00229 00230 // WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time 00231 if (!pn53x_transceive_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen)) 00232 return false; 00233 szRxBufLen -= sizeof (ack_frame); 00234 memmove (abtRxBuf, abtRxBuf + sizeof (ack_frame), szRxBufLen); 00235 00236 if (szRxBufLen == 0) { 00237 szRxBufLen = BUFFER_LENGTH; 00238 do { 00239 delay_ms (10); 00240 res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen); 00241 } while (res != 0); 00242 #ifdef DEBUG 00243 PRINT_HEX ("RX", abtRxBuf, szRxBufLen); 00244 #endif 00245 } 00246 00247 #ifdef DEBUG 00248 PRINT_HEX ("TX", ack_frame, 6); 00249 #endif 00250 res = uart_send ((serial_port) pnd->nds, ack_frame, 6); 00251 if (res != 0) { 00252 ERR ("%s", "Unable to transmit data. (TX)"); 00253 pnd->iLastError = res; 00254 return false; 00255 } 00256 00257 if (!pn53x_transceive_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen)) 00258 return false; 00259 00260 // When the answer should be ignored, just return a successful result 00261 if (pbtRx == NULL || pszRxLen == NULL) 00262 return true; 00263 00264 // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) 00265 if (szRxBufLen < 9) { 00266 pnd->iLastError = DEINVAL; 00267 return false; 00268 } 00269 // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable) 00270 *pszRxLen = szRxBufLen - 9; 00271 memcpy (pbtRx, abtRxBuf + 7, *pszRxLen); 00272 00273 return true; 00274 } 00275 00276 void 00277 pn532_uart_wakeup (const nfc_device_spec_t nds) 00278 { 00279 byte_t abtRx[BUFFER_LENGTH]; 00280 size_t szRxLen; 00284 const byte_t pncmd_pn532c106_wakeup_preamble[] = 00285 { 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00, 0x00, 0xff, 0x03, 0xfd, 00286 0xd4, 0x14, 0x01, 0x17, 0x00 }; 00287 #ifdef DEBUG 00288 PRINT_HEX ("TX", pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble)); 00289 #endif 00290 uart_send ((serial_port) nds, pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble)); 00291 if (0 == uart_receive ((serial_port) nds, abtRx, &szRxLen)) { 00292 #ifdef DEBUG 00293 PRINT_HEX ("RX", abtRx, szRxLen); 00294 #endif 00295 } 00296 } 00297 00298 bool 00299 pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success) 00300 { 00301 byte_t abtRx[BUFFER_LENGTH]; 00302 size_t szRxLen; 00303 const byte_t attempted_result[] = 00304 { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xD5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 00305 0xbc, 0x00 }; 00306 int res; 00307 00309 const byte_t pncmd_communication_test[] = 00310 { 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 }; 00311 00312 *success = false; 00313 00314 #ifdef DEBUG 00315 PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test)); 00316 #endif 00317 res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test)); 00318 if (res != 0) { 00319 ERR ("%s", "Unable to transmit data. (TX)"); 00320 return false; 00321 } 00322 00323 res = uart_receive ((serial_port) nds, abtRx, &szRxLen); 00324 if (res != 0) { 00325 ERR ("%s", "Unable to receive data. (RX)"); 00326 return false; 00327 } 00328 #ifdef DEBUG 00329 PRINT_HEX ("RX", abtRx, szRxLen); 00330 #endif 00331 00332 if (0 == memcmp (abtRx, attempted_result, sizeof (attempted_result))) 00333 *success = true; 00334 00335 return true; 00336 }