adafruit_pn532.c 34 KB

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