adafruit_pn532.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. /*
  2. * Adafruit PN532 library adapted to use in NRF51 and NRF52
  3. *
  4. * Software License Agreement (BSD License)
  5. *
  6. * Copyright (c) 2012, Adafruit Industries
  7. * All rights reserved.
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the
  16. * names of its contributors may be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stdio.h>
  30. #include <inttypes.h>
  31. #include <string.h>
  32. #include "adafruit_pn532.h"
  33. #include "adafruit_pn532_config.h"
  34. #include "nrf_gpio.h"
  35. #include "nrf_delay.h"
  36. #include "nrf_drv_twi.h"
  37. #include "app_error.h"
  38. #include "nordic_common.h"
  39. // NTAG2XX Page read/write restrictions.
  40. #define NTAG2XX_MAX_READ_PAGE_NUMBER 231
  41. #define NTAG2XX_MIN_WRITE_PAGE_NUMBER 4
  42. #define NTAG2XX_MAX_WRITE_PAGE_NUMBER 225
  43. // Lengths and offsets for specific commands and responses.
  44. #define COMMAND_GETFIRMWAREVERSION_LENGTH 1
  45. #define REPLY_GETFIRMWAREVERSION_LENGTH (5 + PN532_FRAME_OVERHEAD)
  46. #define COMMAND_SAMCONFIGURATION_LENGTH 4
  47. #define REPLY_SAMCONFIGURATION_LENGTH (1 + PN532_FRAME_OVERHEAD)
  48. #define COMMAND_POWERDOWN_BASE_LENGTH 2 // No GenerateIRQ parameter.
  49. #define REPLY_POWERDOWN_LENGTH (2 + PN532_FRAME_OVERHEAD)
  50. #define COMMAND_RFCONFIGURATION_MAXRETRIES_LENGTH 5
  51. #define COMMAND_RFCONFIGURATION_RFFIELD_LENGTH 3
  52. #define REPLY_RFCONFIGURATION_LENGTH (1 + PN532_FRAME_OVERHEAD)
  53. #define COMMAND_INLISTPASSIVETARGET_BASE_LENGTH 3
  54. #define REPLY_INLISTPASSIVETARGET_106A_TARGET_LENGTH (14 + PN532_FRAME_OVERHEAD)
  55. #define REPLY_INLISTPASSIVETARGET_106A_NBTG_OFFSET 7
  56. #define REPLY_INLISTPASSIVETARGET_106A_TG_OFFSET 8
  57. #define REPLY_INLISTPASSIVETARGET_106A_UID_LEN_OFFSET 12
  58. #define REPLY_INLISTPASSIVETARGET_106A_UID_OFFSET 13
  59. #define COMMAND_INDATAEXCHANGE_BASE_LENGTH 2
  60. #define REPLY_INDATAEXCHANGE_BASE_LENGTH (2 + PN532_FRAME_OVERHEAD)
  61. // Configuration parameters for SAMCONFIGURATION command.
  62. #define SAMCONFIGURATION_MODE_NORMAL 0x01
  63. #define SAMCONFIGURATION_MODE_VIRTUAL_CARD 0x02
  64. #define SAMCONFIGURATION_MODE_WIRED_CARD 0x03
  65. #define SAMCONFIGURATION_MODE_DUAL_CARD 0x04
  66. #define SAMCONFIGURATION_IRQ_ENABLED 0x01
  67. #define SAMCONFIGURATION_IRQ_DISABLED 0x00
  68. // Configuration parameters for POWERDOWN command.
  69. #define POWERDOWN_WAKEUP_IRQ 0x80
  70. #define POWERDOWN_WAKEUP_SPI 0x20
  71. // Configuration parameters for RFCONFIGURATION command.
  72. #define RFCONFIGURATION_CFGITEM_RFFIELD 0x01
  73. #define RFCONFIGURATION_CFGITEM_MAXRETRIES 0x05
  74. #define RFCONFIGURATION_RFFIELD_ON 0x01
  75. #define RFCONFIGURATION_RFFIELD_OFF 0x00
  76. // Error mask for the status mask in INDATAEXCHANGE frame.
  77. #define PN532_STATUS_ERROR_MASK 0x3F
  78. // Card specific parameters.
  79. #define MIFARE_MAX_DATA_EXCHANGE 16
  80. #define MIFARE_PAGE_SIZE 4
  81. // Size of the PN532 size packet.
  82. #define PN532_ACK_PACKET_SIZE 6
  83. // Default time-out for read_passive_target_id (time required for field scan).
  84. #define PN532_DEFAULT_WAIT_FOR_READY_TIMEOUT 100
  85. // ACK frame format.
  86. static const uint8_t pn532_ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
  87. // Firmware version reply frame format (preamble to command byte).
  88. static const uint8_t pn532_rsp_firmware_ver[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03};
  89. static adafruit_pn532 pn532_object = {
  90. ._clk = 0,
  91. ._miso = 0,
  92. ._mosi = 0,
  93. ._ss = 0,
  94. ._irq = PN532_IRQ,
  95. ._reset = PN532_RESET,
  96. ._usingSPI = false,
  97. ._hardwareSPI = false
  98. };
  99. static const nrf_drv_twi_t m_twi_master = NRF_DRV_TWI_INSTANCE(MASTER_TWI_INST);
  100. static uint8_t pn532_packet_buf[PN532_PACKBUFFSIZ];
  101. static bool lib_initialized = false;
  102. /**
  103. * @brief Function to configure pins in host chip.
  104. *
  105. * This function configures specific pins to interact with the PN532 module.
  106. */
  107. static void adafruit_pn532_pin_setup(void)
  108. {
  109. nrf_gpio_cfg_input(pn532_object._irq, NRF_GPIO_PIN_NOPULL);
  110. // The reset pin in the AdaFruit NFC Shield is actually the PN532 reset indicator pin (RSTOUT_N)
  111. // and cannot be used to perform reset of the chip. (RSTPD_N pin, see AdaFruit NFC Shield
  112. // schematics).
  113. nrf_gpio_cfg_input(pn532_object._reset, NRF_GPIO_PIN_NOPULL);
  114. }
  115. /**
  116. * @brief Function to calculate the checksum byte.
  117. *
  118. * This function calculates the checksum byte, so that the sum of all verified bytes
  119. * and the checksum byte is equal to 0.
  120. *
  121. * @param current_sum[in] Sum of all bytes used to calculate checksum.
  122. *
  123. * @retval Value of the checksum byte.
  124. */
  125. static uint8_t adafruit_pn532_cs_complement_calc(uint8_t current_sum)
  126. {
  127. return ~current_sum + 1;
  128. }
  129. /**
  130. * @brief Function to check correctness of PN532 Normal information frame header.
  131. *
  132. * @param p_buffer[in] Pointer to the buffer containing frame header.
  133. * @param p_length[out] Pointer to the variable where the data length will be stored.
  134. *
  135. * @retval NRF_SUCCESS If the header was correct.
  136. * @retval NRF_ERROR_INVALID_DATA Otherwise.
  137. */
  138. static ret_code_t adafruit_pn532_header_check(uint8_t const * p_buffer, uint8_t * p_length)
  139. {
  140. // Preamble
  141. if ( (p_buffer[PN532_PREAMBLE_OFFSET] != PN532_PREAMBLE) ||
  142. (p_buffer[PN532_STARTCODE1_OFFSET] != PN532_STARTCODE1) ||
  143. (p_buffer[PN532_STARTCODE2_OFFSET] != PN532_STARTCODE2) )
  144. {
  145. PN532_LOG("Preamble missing\r\n");
  146. return NRF_ERROR_INVALID_DATA;
  147. }
  148. // Data length
  149. if (p_buffer[PN532_LENGTH_CS_OFFSET] !=
  150. adafruit_pn532_cs_complement_calc(p_buffer[PN532_LENGTH_OFFSET]))
  151. {
  152. PN532_LOG("Length check invalid: len: 0x%02x, cs: 02%02x\r\n",
  153. p_buffer[PN532_LENGTH_OFFSET], p_buffer[PN532_LENGTH_CS_OFFSET]);
  154. return NRF_ERROR_INVALID_DATA;
  155. }
  156. // Direction byte
  157. if ( (p_buffer[PN532_TFI_OFFSET] != PN532_PN532TOHOST) &&
  158. (p_buffer[PN532_TFI_OFFSET] != PN532_HOSTTOPN532) )
  159. {
  160. PN532_LOG("Invalid direction byte: %02x\r\n", p_buffer[PN532_TFI_OFFSET]);
  161. return NRF_ERROR_INVALID_DATA;
  162. }
  163. *p_length = p_buffer[PN532_LENGTH_OFFSET];
  164. return NRF_SUCCESS;
  165. }
  166. ret_code_t adafruit_pn532_init(bool force)
  167. {
  168. uint32_t ver_data; // Variable to store firmware version read from PN532.
  169. if (lib_initialized && !(force))
  170. {
  171. PN532_LOG("Library is already initialized\r\n");
  172. return NRF_SUCCESS;
  173. }
  174. if (force)
  175. {
  176. PN532_LOG("Forcing library reinitialization\r\n");
  177. }
  178. if (pn532_object._usingSPI)
  179. {
  180. PN532_LOG("Communication over SPI is currently not supported!\r\n");
  181. return NRF_ERROR_INTERNAL;
  182. }
  183. ret_code_t err_code = adafruit_pn532_create_i2c();
  184. if (err_code != NRF_SUCCESS)
  185. {
  186. PN532_LOG("Failed to create I2C, err_code = %d\r\n", err_code);
  187. return err_code;
  188. }
  189. adafruit_pn532_pin_setup();
  190. // Delay for PN532 to catch up with NRF.
  191. nrf_delay_ms(100);
  192. PN532_LOG("Looking for PN532\r\n");
  193. err_code = adafruit_pn532_get_firmware_version(&ver_data);
  194. if (err_code != NRF_SUCCESS)
  195. {
  196. PN532_LOG("Didn't find PN53x board, err_code = %d\r\n", err_code);
  197. return err_code;
  198. }
  199. PN532_LOG("Found chip PN5%02x\r\n", (ver_data >> 24) & 0xFF);
  200. PN532_LOG("Firmware version %d.%d\r\n", (ver_data >> 16) & 0xFF,
  201. (ver_data >> 8) & 0xFF);
  202. err_code = adafruit_pn532_sam_config(SAMCONFIGURATION_MODE_NORMAL);
  203. if (err_code != NRF_SUCCESS)
  204. {
  205. PN532_LOG("Failed to configure SAM, err_code = %d\r\n", err_code);
  206. return err_code;
  207. }
  208. err_code = adafruit_pn532_set_passive_activation_retries(0xFF);
  209. if (err_code != NRF_SUCCESS)
  210. {
  211. PN532_LOG("Failed to set passive activation retries, err_code = %d\r\n", err_code);
  212. return err_code;
  213. }
  214. PN532_LOG("Waiting for an ISO14443A card\r\n");
  215. lib_initialized = true;
  216. return NRF_SUCCESS;
  217. }
  218. ret_code_t adafruit_pn532_create_i2c()
  219. {
  220. PN532_LOG("Creating I2C\r\n");
  221. nrf_drv_twi_uninit(&m_twi_master);
  222. ret_code_t ret = nrf_drv_twi_init(&m_twi_master, NULL, NULL, NULL);
  223. if (ret != NRF_SUCCESS)
  224. {
  225. PN532_LOG("Failed to initialize TWI, err_code = %d\r\n", ret);
  226. return ret;
  227. }
  228. nrf_drv_twi_enable(&m_twi_master);
  229. return NRF_SUCCESS;
  230. }
  231. void print_hex(const uint8_t * p_data, const uint32_t len)
  232. {
  233. uint32_t i;
  234. for (i = 0; i < len; i++)
  235. {
  236. printf(" %02X", p_data[i]);
  237. }
  238. printf("\r\n");
  239. }
  240. void print_hex_char(const uint8_t * p_data, const uint32_t len)
  241. {
  242. uint32_t i;
  243. for (i = 0; i < len; i++)
  244. {
  245. printf(" %02X", p_data[i]);
  246. }
  247. printf(" ");
  248. for (i = 0; i < len; i++)
  249. {
  250. if ( (p_data[i] <= 0x1F) || (p_data[i] >= 0x7F) )
  251. {
  252. printf(" .");
  253. }
  254. else
  255. {
  256. printf(" %c", (char)p_data[i]);
  257. }
  258. }
  259. printf("\r\n");
  260. }
  261. ret_code_t adafruit_pn532_get_firmware_version(uint32_t * p_response)
  262. {
  263. PN532_LOG("Trying to get the firmware version\r\n");
  264. pn532_packet_buf[0] = PN532_COMMAND_GETFIRMWAREVERSION;
  265. ret_code_t err_code = adafruit_pn532_send_cmd(pn532_packet_buf,
  266. COMMAND_GETFIRMWAREVERSION_LENGTH,
  267. 1000);
  268. if (err_code != NRF_SUCCESS)
  269. {
  270. PN532_LOG("Failed to send GetFirmwareVersion command, err_code = %d\r\n", err_code);
  271. return err_code;
  272. }
  273. // Read data packet.
  274. err_code = adafruit_pn532_read_data(pn532_packet_buf, REPLY_GETFIRMWAREVERSION_LENGTH);
  275. if (err_code != NRF_SUCCESS)
  276. {
  277. PN532_LOG("Failed to read data, err_code = %d\r\n", err_code);
  278. return err_code;
  279. }
  280. if (memcmp(pn532_packet_buf + 1, pn532_rsp_firmware_ver, sizeof(pn532_rsp_firmware_ver)))
  281. {
  282. PN532_LOG("Firmware frame doesn't match!\r\n");
  283. return NRF_ERROR_NOT_FOUND;
  284. }
  285. // Extract firmware version from the frame.
  286. int offset = PN532_DATA_OFFSET + 1;
  287. *p_response = pn532_packet_buf[offset++];
  288. *p_response <<= 8;
  289. *p_response |= pn532_packet_buf[offset++];
  290. *p_response <<= 8;
  291. *p_response |= pn532_packet_buf[offset++];
  292. *p_response <<= 8;
  293. *p_response |= pn532_packet_buf[offset++];
  294. return NRF_SUCCESS;
  295. }
  296. ret_code_t adafruit_pn532_send_cmd(uint8_t * p_cmd, uint8_t cmd_len, uint16_t timeout)
  297. {
  298. PN532_LOG("Trying to send command\r\n");
  299. PN532_LOG_HEX(p_cmd, cmd_len);
  300. ret_code_t err_code = adafruit_pn532_write_command(p_cmd, cmd_len);
  301. if (err_code != NRF_SUCCESS)
  302. {
  303. PN532_LOG("Failed to write command, err_code = %d\r\n", err_code);
  304. return err_code;
  305. }
  306. // Wait for ACK
  307. if (!adafruit_pn532_waitready_ms(timeout))
  308. {
  309. PN532_LOG("Failed while waiting\r\n");
  310. return NRF_ERROR_INTERNAL;
  311. }
  312. return adafruit_pn532_read_ack();
  313. }
  314. ret_code_t adafruit_pn532_sam_config(uint8_t mode)
  315. {
  316. PN532_LOG("Attempting to configure SAM\r\n");
  317. ret_code_t err_code;
  318. if ( (mode != SAMCONFIGURATION_MODE_NORMAL)
  319. && (mode != SAMCONFIGURATION_MODE_VIRTUAL_CARD)
  320. && (mode != SAMCONFIGURATION_MODE_WIRED_CARD)
  321. && (mode != SAMCONFIGURATION_MODE_DUAL_CARD) )
  322. {
  323. return NRF_ERROR_INVALID_PARAM;
  324. }
  325. pn532_packet_buf[0] = PN532_COMMAND_SAMCONFIGURATION;
  326. pn532_packet_buf[1] = mode;
  327. pn532_packet_buf[2] = 0x14; // Time-out value
  328. pn532_packet_buf[3] = SAMCONFIGURATION_IRQ_ENABLED;
  329. err_code = adafruit_pn532_send_cmd(pn532_packet_buf, COMMAND_SAMCONFIGURATION_LENGTH, 1000);
  330. if (err_code != NRF_SUCCESS)
  331. {
  332. PN532_LOG("Failed while checking ACK! err_code = %d\r\n", err_code);
  333. return err_code;
  334. }
  335. err_code = adafruit_pn532_read_data(pn532_packet_buf, REPLY_SAMCONFIGURATION_LENGTH);
  336. if (err_code != NRF_SUCCESS)
  337. {
  338. PN532_LOG("Failed while reading data! err_code = %d\r\n", err_code);
  339. return err_code;
  340. }
  341. if (!(pn532_packet_buf[PN532_DATA_OFFSET] == PN532_COMMAND_SAMCONFIGURATION + 1))
  342. {
  343. PN532_LOG("Failed while checking SAMCONFIGURATION response, expected 0x%02x, got 0x%02x\r\n",
  344. PN532_COMMAND_SAMCONFIGURATION + 1, pn532_packet_buf[PN532_DATA_OFFSET]);
  345. return NRF_ERROR_NOT_FOUND;
  346. }
  347. return NRF_SUCCESS;
  348. }
  349. ret_code_t adafruit_pn532_power_down(void)
  350. {
  351. PN532_LOG("Powering down the PN532\r\n");
  352. pn532_packet_buf[0] = PN532_COMMAND_POWERDOWN;
  353. pn532_packet_buf[1] = POWERDOWN_WAKEUP_IRQ;
  354. ret_code_t err_code = adafruit_pn532_send_cmd(pn532_packet_buf,
  355. COMMAND_POWERDOWN_BASE_LENGTH,
  356. 1000);
  357. if (err_code != NRF_SUCCESS)
  358. {
  359. PN532_LOG("Failed while checking ACK! err_code = %d\r\n", err_code);
  360. return err_code;
  361. }
  362. err_code = adafruit_pn532_read_data(pn532_packet_buf, REPLY_POWERDOWN_LENGTH);
  363. if (err_code != NRF_SUCCESS)
  364. {
  365. PN532_LOG("Failed while reading data! err_code = %d\r\n", err_code);
  366. return err_code;
  367. }
  368. if (!(pn532_packet_buf[PN532_DATA_OFFSET] == PN532_COMMAND_POWERDOWN + 1))
  369. {
  370. PN532_LOG("Failed while checking POWERDOWN response, expected 0x%02x, got 0x%02x\r\n",
  371. PN532_COMMAND_POWERDOWN + 1, pn532_packet_buf[PN532_DATA_OFFSET]);
  372. return NRF_ERROR_NOT_FOUND;
  373. }
  374. // From PN532 user manual: "The PN532 needs approximately 1 ms to get into Power Down mode,
  375. // after the command response." (Rev. 02, p. 7.2.11, page 98)
  376. nrf_delay_ms(1);
  377. return NRF_SUCCESS;
  378. }
  379. ret_code_t adafruit_pn532_wake_up(void)
  380. {
  381. ret_code_t err_code;
  382. if (pn532_object._usingSPI)
  383. {
  384. PN532_LOG("Communication over SPI is currently not supported!\r\n");
  385. return NRF_ERROR_INTERNAL;
  386. }
  387. // Wakeup procedure as specified in PN532 User Manual Rev. 02, p. 7.2.11, page 99.
  388. uint8_t dummy_byte = 0x55;
  389. err_code = nrf_drv_twi_tx(&m_twi_master, PN532_I2C_ADDRESS, &dummy_byte, 1, false);
  390. if (err_code != NRF_SUCCESS)
  391. {
  392. PN532_LOG("Failed while calling twi tx, err_code = %d\r\n", err_code);
  393. return err_code;
  394. }
  395. // Wait specified time to ensure that the PN532 shield is fully operational
  396. // (PN532 data sheet, Rev. 3.2, page 209).
  397. nrf_delay_ms(2);
  398. return NRF_SUCCESS;
  399. }
  400. ret_code_t adafruit_pn532_set_passive_activation_retries(uint8_t max_retries)
  401. {
  402. ret_code_t err_code;
  403. pn532_packet_buf[0] = PN532_COMMAND_RFCONFIGURATION;
  404. pn532_packet_buf[1] = RFCONFIGURATION_CFGITEM_MAXRETRIES;
  405. pn532_packet_buf[2] = 0xFF; // MxRtyATR retries (default value)
  406. pn532_packet_buf[3] = 0x01; // MxRtyPSL retries (default value)
  407. pn532_packet_buf[4] = max_retries; // MxRtyPassiveActivation retries (user value)
  408. PN532_LOG("Setting MxRtyPassiveActivation to %i\r\n", max_retries);
  409. err_code = adafruit_pn532_send_cmd(pn532_packet_buf,
  410. COMMAND_RFCONFIGURATION_MAXRETRIES_LENGTH,
  411. 1000);
  412. if (err_code != NRF_SUCCESS)
  413. {
  414. PN532_LOG("Failed while checking ACK! err_code = %d\r\n", err_code);
  415. return err_code;
  416. }
  417. return NRF_SUCCESS;
  418. }
  419. ret_code_t adafruit_pn532_read_passive_target_id(uint8_t card_baudrate,
  420. uint8_t * p_uid,
  421. uint8_t * p_uid_len,
  422. uint16_t timeout)
  423. {
  424. PN532_LOG("Trying to read passive target ID\r\n");
  425. if (p_uid == NULL || p_uid_len == NULL)
  426. {
  427. PN532_LOG("NULL pointers passed as arguments to adafruit_pn532_read_passive_target_id.");
  428. return NRF_ERROR_INVALID_PARAM;
  429. }
  430. if (card_baudrate != PN532_MIFARE_ISO14443A_BAUD)
  431. {
  432. PN532_LOG("Only ISO14443 type A cards are supported.\r\n");
  433. return NRF_ERROR_INVALID_PARAM;
  434. }
  435. pn532_packet_buf[0] = PN532_COMMAND_INLISTPASSIVETARGET;
  436. pn532_packet_buf[1] = 1; // Maximum number of targets.
  437. pn532_packet_buf[2] = card_baudrate;
  438. ret_code_t err_code = adafruit_pn532_send_cmd(pn532_packet_buf,
  439. COMMAND_INLISTPASSIVETARGET_BASE_LENGTH,
  440. PN532_DEFAULT_WAIT_FOR_READY_TIMEOUT);
  441. if (err_code != NRF_SUCCESS)
  442. {
  443. PN532_LOG("No card(s) read, err_code = %d\r\n", err_code);
  444. return err_code;
  445. }
  446. PN532_LOG("Waiting for IRQ (indicates card presence)\r\n");
  447. // Give PN532 a little time to scan in case time-out is very small.
  448. if (timeout < PN532_DEFAULT_WAIT_FOR_READY_TIMEOUT)
  449. {
  450. timeout = PN532_DEFAULT_WAIT_FOR_READY_TIMEOUT;
  451. }
  452. if (!adafruit_pn532_waitready_ms(timeout))
  453. {
  454. PN532_LOG("IRQ time-out\r\n");
  455. return NRF_ERROR_INTERNAL;
  456. }
  457. err_code = adafruit_pn532_read_data(pn532_packet_buf,
  458. REPLY_INLISTPASSIVETARGET_106A_TARGET_LENGTH);
  459. if (err_code != NRF_SUCCESS)
  460. {
  461. PN532_LOG("Failed while reading data! err_code = %d\r\n", err_code);
  462. return err_code;
  463. }
  464. if (pn532_packet_buf[REPLY_INLISTPASSIVETARGET_106A_NBTG_OFFSET] != 1)
  465. {
  466. PN532_LOG("Failed while checking number of targets, expected 1, got %02x\r\n",
  467. pn532_packet_buf[REPLY_INLISTPASSIVETARGET_106A_NBTG_OFFSET]);
  468. return NRF_ERROR_INVALID_DATA;
  469. }
  470. if (*p_uid_len < pn532_packet_buf[REPLY_INLISTPASSIVETARGET_106A_UID_LEN_OFFSET])
  471. {
  472. PN532_LOG("Buffer length is invalid.\r\n");
  473. return NRF_ERROR_INVALID_LENGTH;
  474. }
  475. *p_uid_len = pn532_packet_buf[REPLY_INLISTPASSIVETARGET_106A_UID_LEN_OFFSET];
  476. pn532_object._inListedTag = pn532_packet_buf[REPLY_INLISTPASSIVETARGET_106A_TG_OFFSET];
  477. memcpy(p_uid, pn532_packet_buf + REPLY_INLISTPASSIVETARGET_106A_UID_OFFSET, *p_uid_len);
  478. return NRF_SUCCESS;
  479. }
  480. ret_code_t adafruit_pn532_in_data_exchange(uint8_t * p_send,
  481. uint8_t send_len,
  482. uint8_t * p_response,
  483. uint8_t * p_response_len)
  484. {
  485. PN532_LOG("Trying in data exchange\r\n");
  486. if (send_len + 2 > PN532_PACKBUFFSIZ)
  487. {
  488. PN532_LOG("APDU length (%d) too long for packet buffer (%d)\r\n",
  489. send_len, PN532_PACKBUFFSIZ - 2);
  490. return NRF_ERROR_INTERNAL;
  491. }
  492. if (*p_response_len + REPLY_INDATAEXCHANGE_BASE_LENGTH > PN532_PACKBUFFSIZ)
  493. {
  494. PN532_LOG("Desired response length (%d) too long for packet buffer (%d)\r\n",
  495. *p_response_len, PN532_PACKBUFFSIZ);
  496. return NRF_ERROR_INTERNAL;
  497. }
  498. // Prepare command.
  499. pn532_packet_buf[0] = PN532_COMMAND_INDATAEXCHANGE;
  500. pn532_packet_buf[1] = pn532_object._inListedTag;
  501. memcpy(pn532_packet_buf + 2, p_send, send_len);
  502. ret_code_t err_code = adafruit_pn532_send_cmd(pn532_packet_buf,
  503. send_len + 2,
  504. 1000);
  505. if (err_code != NRF_SUCCESS)
  506. {
  507. PN532_LOG("Could not send ADPU, err_code = %d\r\n", err_code);
  508. return err_code;
  509. }
  510. if (!adafruit_pn532_waitready_ms(1000))
  511. {
  512. PN532_LOG("Response never received for ADPU\r\n");
  513. return NRF_ERROR_INTERNAL;
  514. }
  515. err_code = adafruit_pn532_read_data(pn532_packet_buf,
  516. *p_response_len + REPLY_INDATAEXCHANGE_BASE_LENGTH);
  517. // + 2 for command and status byte
  518. if (err_code != NRF_SUCCESS)
  519. {
  520. PN532_LOG("Could not read data, err_code = %d\r\n", err_code);
  521. return err_code;
  522. }
  523. uint8_t length = 0;
  524. err_code = adafruit_pn532_header_check(pn532_packet_buf, &length);
  525. if (err_code != NRF_SUCCESS)
  526. {
  527. PN532_LOG("Invalid frame header\r\n");
  528. return err_code;
  529. }
  530. if ( (pn532_packet_buf[PN532_TFI_OFFSET] != PN532_PN532TOHOST) ||
  531. (pn532_packet_buf[PN532_DATA_OFFSET] != PN532_COMMAND_INDATAEXCHANGE + 1) )
  532. {
  533. PN532_LOG("Don't know how to handle this command: %02x\r\n",
  534. pn532_packet_buf[PN532_DATA_OFFSET]);
  535. return NRF_ERROR_INTERNAL;
  536. }
  537. // Check InDataExchange Status byte.
  538. if ((pn532_packet_buf[PN532_DATA_OFFSET + 1] & PN532_STATUS_ERROR_MASK) != 0x00)
  539. {
  540. PN532_LOG("Status code indicates an error, %02x\r\n",
  541. pn532_packet_buf[PN532_DATA_OFFSET + 1]);
  542. return NRF_ERROR_INTERNAL;
  543. }
  544. length -= 3; // Calculate the actual data length
  545. // Silently truncate response to fit into reply desired data size.
  546. if (length > *p_response_len)
  547. {
  548. length = *p_response_len;
  549. }
  550. memcpy(p_response, pn532_packet_buf + PN532_DATA_OFFSET + 2, length);
  551. *p_response_len = length;
  552. return NRF_SUCCESS;
  553. }
  554. ret_code_t adafruit_pn532_ntag2xx_read_page(uint8_t page, uint8_t * p_buffer)
  555. {
  556. PN532_LOG("Trying to read page %u\r\n", page);
  557. ret_code_t err_code;
  558. uint8_t cmd_buf[2];
  559. uint8_t response_len = MIFARE_PAGE_SIZE;
  560. cmd_buf[0] = MIFARE_CMD_READ;
  561. cmd_buf[1] = page;
  562. err_code = adafruit_pn532_in_data_exchange(cmd_buf, 2, p_buffer, &response_len);
  563. if (err_code != NRF_SUCCESS)
  564. {
  565. PN532_LOG("Failed to read page %d\r\n", page);
  566. return err_code;
  567. }
  568. PN532_LOG("Page %d : ", page);
  569. PN532_LOG_HEX(p_buffer, MIFARE_PAGE_SIZE);
  570. return NRF_SUCCESS;
  571. }
  572. ret_code_t adafruit_pn532_ntag2xx_write_page(uint8_t page, uint8_t * p_data)
  573. {
  574. if ( (page < NTAG2XX_MIN_WRITE_PAGE_NUMBER) ||
  575. (page > NTAG2XX_MAX_WRITE_PAGE_NUMBER) )
  576. {
  577. PN532_LOG("Page value out of range, page = %d\r\n", page);
  578. return NRF_ERROR_INVALID_PARAM;
  579. }
  580. PN532_LOG("Trying to write 4 uint8_t page %u\r\n", page);
  581. uint8_t write_buf[MIFARE_MAX_DATA_EXCHANGE];
  582. uint8_t response_len = MIFARE_MAX_DATA_EXCHANGE;
  583. write_buf[0] = MIFARE_ULTRALIGHT_CMD_WRITE;
  584. write_buf[1] = page;
  585. memcpy(write_buf + 2, p_data, MIFARE_PAGE_SIZE);
  586. ret_code_t err_code = adafruit_pn532_in_data_exchange(write_buf, 2 + MIFARE_PAGE_SIZE,
  587. write_buf, &response_len);
  588. if (err_code != NRF_SUCCESS)
  589. {
  590. PN532_LOG("Failed to write page %d\r\n", page);
  591. return err_code;
  592. }
  593. return NRF_SUCCESS;
  594. }
  595. ret_code_t adafruit_pn532_ntag2xx_write_ndef_uri(uint8_t uri_id, char * p_url, uint8_t data_len)
  596. {
  597. PN532_LOG("Trying to write URI %d\r\n", uri_id);
  598. uint8_t page_buf[4] = {0};
  599. uint8_t uri_len = strlen(p_url);
  600. uint8_t page_header[] =
  601. {
  602. 0x00, 0x03, uri_len + 5, 0xD1,
  603. 0x01, uri_len + 1, 0x55, uri_id
  604. };
  605. uint8_t page_header_len = sizeof(page_header);
  606. if ( (uri_len < 1) || (uri_len + 1 > (data_len - page_header_len)))
  607. {
  608. PN532_LOG("URL is too long for provided data length\r\n");
  609. return NRF_ERROR_INVALID_PARAM;
  610. }
  611. ret_code_t err_code;
  612. int32_t i;
  613. uint8_t current_page = 4;
  614. for (i = 0; i < 2; i++)
  615. {
  616. memcpy(page_buf, page_header + 4*i, MIFARE_PAGE_SIZE);
  617. err_code = adafruit_pn532_ntag2xx_write_page(current_page, page_buf);
  618. if (err_code != NRF_SUCCESS)
  619. {
  620. PN532_LOG("Failed to write URI page %d, err_code = %d\r\n", current_page, err_code);
  621. return err_code;
  622. }
  623. current_page++;
  624. }
  625. char * url_ptr = p_url;
  626. uint8_t len_to_cpy = 0;
  627. while (uri_len > 0)
  628. {
  629. // Prepare length of the chunk to copy.
  630. if (uri_len < MIFARE_PAGE_SIZE)
  631. {
  632. len_to_cpy = uri_len;
  633. // If do not copy a full page, prepare the buffer.
  634. memset(page_buf, 0x00, MIFARE_PAGE_SIZE);
  635. page_buf[len_to_cpy] = 0xFE; // Terminator block.
  636. }
  637. else
  638. {
  639. len_to_cpy = MIFARE_PAGE_SIZE;
  640. }
  641. memcpy(page_buf, url_ptr, len_to_cpy);
  642. err_code = adafruit_pn532_ntag2xx_write_page(current_page, page_buf);
  643. if (err_code != NRF_SUCCESS)
  644. {
  645. PN532_LOG("Failed to write page %d, err_code = %d\r\n", current_page, err_code);
  646. return err_code;
  647. }
  648. current_page++;
  649. // If the last page was sent, and there was no chance to insert TLV Terminator block,
  650. // send another page with Terminator block in it.
  651. if (uri_len == MIFARE_PAGE_SIZE)
  652. {
  653. memset(page_buf, 0x00, MIFARE_PAGE_SIZE);
  654. page_buf[0] = 0xFE;
  655. err_code = adafruit_pn532_ntag2xx_write_page(current_page, page_buf);
  656. if (err_code != NRF_SUCCESS)
  657. {
  658. PN532_LOG("Failed to write page %d, err_code = %d\r\n", current_page, err_code);
  659. return err_code;
  660. }
  661. current_page++;
  662. }
  663. uri_len -= len_to_cpy;
  664. url_ptr += len_to_cpy;
  665. }
  666. return NRF_SUCCESS;
  667. }
  668. ret_code_t adafruit_pn532_read_ack(void)
  669. {
  670. PN532_LOG("Reading ACK\r\n");
  671. uint8_t ack_buf[PN532_ACK_PACKET_SIZE];
  672. ret_code_t err_code;
  673. err_code = adafruit_pn532_read_data(ack_buf, PN532_ACK_PACKET_SIZE);
  674. if (err_code != NRF_SUCCESS)
  675. {
  676. PN532_LOG("ACK read failed\r\n");
  677. return err_code;
  678. }
  679. // Wait for irq to be taken off.
  680. for (uint16_t i = 0; i < 1000; i++)
  681. {
  682. if (!adafruit_pn532_is_ready())
  683. {
  684. break;
  685. }
  686. }
  687. if (memcmp(ack_buf, pn532_ack, PN532_ACK_PACKET_SIZE) != 0)
  688. {
  689. PN532_LOG("Failed while comparing ACK packet\r\n");
  690. return NRF_ERROR_INTERNAL;
  691. }
  692. return NRF_SUCCESS;
  693. }
  694. bool adafruit_pn532_is_ready(void)
  695. {
  696. return nrf_gpio_pin_read(pn532_object._irq) == 0;
  697. }
  698. bool adafruit_pn532_waitready_ms(uint16_t timeout)
  699. {
  700. uint16_t timer = 0;
  701. bool result = false;
  702. result = adafruit_pn532_is_ready();
  703. while ((!result) && (timer < timeout))
  704. {
  705. timer += 1;
  706. nrf_delay_ms(1);
  707. result = adafruit_pn532_is_ready();
  708. }
  709. return result;
  710. }
  711. /// Buffer for low level communication.
  712. static uint8_t pn532_rxtx_buffer[PN532_PACKBUFFSIZ];
  713. ret_code_t adafruit_pn532_read_data(uint8_t * p_buff, uint8_t n)
  714. {
  715. if (!adafruit_pn532_waitready_ms(PN532_DEFAULT_WAIT_FOR_READY_TIMEOUT))
  716. {
  717. return NRF_ERROR_INTERNAL;
  718. }
  719. if (pn532_object._usingSPI)
  720. {
  721. PN532_LOG("Communication over SPI is currently not supported!\r\n");
  722. return NRF_ERROR_INTERNAL;
  723. }
  724. if (n + 1 > PN532_PACKBUFFSIZ)
  725. {
  726. PN532_LOG("Rx buffer is too short!\r\n");
  727. return NRF_ERROR_INVALID_PARAM;
  728. }
  729. ret_code_t err_code;
  730. // In case of I2C, read the additional status byte.
  731. PN532_LOG("Reading: ");
  732. err_code = nrf_drv_twi_rx(&m_twi_master, PN532_I2C_ADDRESS, pn532_rxtx_buffer, n + 1);
  733. if (err_code != NRF_SUCCESS)
  734. {
  735. PN532_LOG("Failed while calling TWI rx, err_code = %d\r\n", err_code);
  736. return err_code;
  737. }
  738. memcpy(p_buff, pn532_rxtx_buffer + 1, n);
  739. PN532_LOG_HEX(p_buff, n);
  740. return NRF_SUCCESS;
  741. }
  742. ret_code_t adafruit_pn532_write_command(uint8_t * p_cmd, uint8_t cmd_len)
  743. {
  744. ret_code_t err_code;
  745. uint8_t checksum;
  746. if (pn532_object._usingSPI)
  747. {
  748. PN532_LOG("Communication over SPI is currently not supported!\r\n");
  749. return NRF_ERROR_INTERNAL;
  750. }
  751. if (cmd_len + PN532_FRAME_OVERHEAD > PN532_PACKBUFFSIZ)
  752. {
  753. PN532_LOG("Tx buffer is too short!\r\n");
  754. return NRF_ERROR_INVALID_PARAM;
  755. }
  756. // Compose header part of the command frame.
  757. pn532_rxtx_buffer[0] = PN532_PREAMBLE;
  758. pn532_rxtx_buffer[1] = PN532_STARTCODE1;
  759. pn532_rxtx_buffer[2] = PN532_STARTCODE2;
  760. pn532_rxtx_buffer[3] = cmd_len + 1; // Data length + TFI byte.
  761. pn532_rxtx_buffer[4] = adafruit_pn532_cs_complement_calc(cmd_len + 1);
  762. pn532_rxtx_buffer[5] = PN532_HOSTTOPN532;
  763. // Copy the payload data.
  764. memcpy(pn532_rxtx_buffer + HEADER_SEQUENCE_LENGTH, p_cmd, cmd_len);
  765. // Calculate checksum.
  766. checksum = PN532_HOSTTOPN532;
  767. for (uint8_t i = 0; i < cmd_len; i++)
  768. {
  769. checksum += p_cmd[i];
  770. }
  771. checksum = adafruit_pn532_cs_complement_calc(checksum);
  772. // Compose checksum part of the command frame.
  773. pn532_rxtx_buffer[HEADER_SEQUENCE_LENGTH + cmd_len] = checksum;
  774. pn532_rxtx_buffer[HEADER_SEQUENCE_LENGTH + cmd_len + 1] = PN532_POSTAMBLE;
  775. PN532_LOG("Sending command\r\n");
  776. PN532_LOG_HEX(pn532_rxtx_buffer, cmd_len + PN532_FRAME_OVERHEAD);
  777. err_code = nrf_drv_twi_tx(&m_twi_master, PN532_I2C_ADDRESS, pn532_rxtx_buffer,
  778. cmd_len + PN532_FRAME_OVERHEAD, false);
  779. if (err_code != NRF_SUCCESS)
  780. {
  781. PN532_LOG("Failed while calling TWI tx 1, err_code = %d\r\n", err_code);
  782. return err_code;
  783. }
  784. return NRF_SUCCESS;
  785. }
  786. /** Function for enabling or disabling the PN532 RF field.
  787. *
  788. * This function sends a configuration command to the PN532, which enables or disables the RF field.
  789. *
  790. * @param field_conf A value indicating whether the RF field should be turned on or off.
  791. * Valid values are 1 (field on) and 0 (field off).
  792. *
  793. * @retval NRF_SUCCESS If the RF field was enabled successfully.
  794. * @retval NRF_ERROR_INVALID_PARAM If the value in field_conf was invalid.
  795. * @retval Other Otherwise.
  796. */
  797. static ret_code_t adafruit_pn532_switch_field(uint8_t field_conf)
  798. {
  799. ret_code_t err_code;
  800. if ( (field_conf != RFCONFIGURATION_RFFIELD_ON) && (field_conf != RFCONFIGURATION_RFFIELD_OFF) )
  801. {
  802. PN532_LOG("Invalid field configuration: 0x%02x\r\n", field_conf);
  803. return NRF_ERROR_INVALID_PARAM;
  804. }
  805. pn532_packet_buf[0] = PN532_COMMAND_RFCONFIGURATION;
  806. pn532_packet_buf[1] = RFCONFIGURATION_CFGITEM_RFFIELD;
  807. pn532_packet_buf[2] = field_conf;
  808. err_code = adafruit_pn532_send_cmd(pn532_packet_buf,
  809. COMMAND_RFCONFIGURATION_RFFIELD_LENGTH ,
  810. 1000);
  811. if (err_code != NRF_SUCCESS)
  812. {
  813. PN532_LOG("Failed while checking ACK! err_code = %d\r\n", err_code);
  814. return err_code;
  815. }
  816. if (!adafruit_pn532_waitready_ms(PN532_DEFAULT_WAIT_FOR_READY_TIMEOUT))
  817. {
  818. return NRF_ERROR_INTERNAL;
  819. }
  820. return NRF_SUCCESS;
  821. }
  822. ret_code_t adafruit_pn532_field_on(void)
  823. {
  824. return adafruit_pn532_switch_field(RFCONFIGURATION_RFFIELD_ON);
  825. }
  826. ret_code_t adafruit_pn532_field_off(void)
  827. {
  828. return adafruit_pn532_switch_field(RFCONFIGURATION_RFFIELD_OFF);
  829. }