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