Martyn Gilbertson / M24SR
Committer:
Martyn Gilbertson
Date:
Wed Jul 31 09:33:56 2019 +0100
Revision:
2:de5aea7f83cd
Parent:
1:e356ce0033e4
Child:
3:5ebf4b2c51a1
[+] Add default password and verify routine to allow System File access
[+] Add routine to set the GPO pin states for RF and I2C

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Martyn Gilbertson 0:37cdeb4f5b6c 1 /* ISL MBED Libraries
Martyn Gilbertson 0:37cdeb4f5b6c 2 * Copyright (C) 2019 - Invisible Systems Ltd. All Rights Reserved.
Martyn Gilbertson 0:37cdeb4f5b6c 3 */
Martyn Gilbertson 0:37cdeb4f5b6c 4 #include "M24SR.h"
Martyn Gilbertson 0:37cdeb4f5b6c 5
Martyn Gilbertson 0:37cdeb4f5b6c 6 #define MAX_OPERATION_SIZE 246
Martyn Gilbertson 0:37cdeb4f5b6c 7 #define MAX_PAYLOAD 241
Martyn Gilbertson 0:37cdeb4f5b6c 8
Martyn Gilbertson 0:37cdeb4f5b6c 9 /** value returned by the NFC chip when a command is successfully completed */
Martyn Gilbertson 0:37cdeb4f5b6c 10 #define NFC_COMMAND_SUCCESS 0x9000
Martyn Gilbertson 0:37cdeb4f5b6c 11
Martyn Gilbertson 0:37cdeb4f5b6c 12 #define SYSTEM_FILE_ID_BYTES "\xE1\x01"
Martyn Gilbertson 0:37cdeb4f5b6c 13 #define CC_FILE_ID_BYTES "\xE1\x03"
Martyn Gilbertson 0:37cdeb4f5b6c 14
Martyn Gilbertson 0:37cdeb4f5b6c 15 #define UB_STATUS_OFFSET 4
Martyn Gilbertson 0:37cdeb4f5b6c 16 #define LB_STATUS_OFFSET 3
Martyn Gilbertson 0:37cdeb4f5b6c 17
Martyn Gilbertson 0:37cdeb4f5b6c 18 /* APDU command: class list */
Martyn Gilbertson 0:37cdeb4f5b6c 19 #define C_APDU_CLA_DEFAULT 0x00
Martyn Gilbertson 0:37cdeb4f5b6c 20 #define C_APDU_CLA_ST 0xA2
Martyn Gilbertson 0:37cdeb4f5b6c 21
Martyn Gilbertson 0:37cdeb4f5b6c 22 /* data area management commands */
Martyn Gilbertson 0:37cdeb4f5b6c 23 #define C_APDU_SELECT_FILE 0xA4
Martyn Gilbertson 0:37cdeb4f5b6c 24 #define C_APDU_GET_RESPONCE 0xC0
Martyn Gilbertson 0:37cdeb4f5b6c 25 #define C_APDU_STATUS 0xF2
Martyn Gilbertson 0:37cdeb4f5b6c 26 #define C_APDU_UPDATE_BINARY 0xD6
Martyn Gilbertson 0:37cdeb4f5b6c 27 #define C_APDU_READ_BINARY 0xB0
Martyn Gilbertson 0:37cdeb4f5b6c 28 #define C_APDU_WRITE_BINARY 0xD0
Martyn Gilbertson 0:37cdeb4f5b6c 29 #define C_APDU_UPDATE_RECORD 0xDC
Martyn Gilbertson 0:37cdeb4f5b6c 30 #define C_APDU_READ_RECORD 0xB2
Martyn Gilbertson 0:37cdeb4f5b6c 31
Martyn Gilbertson 0:37cdeb4f5b6c 32 /* safety management commands */
Martyn Gilbertson 0:37cdeb4f5b6c 33 #define C_APDU_VERIFY 0x20
Martyn Gilbertson 0:37cdeb4f5b6c 34 #define C_APDU_CHANGE 0x24
Martyn Gilbertson 0:37cdeb4f5b6c 35 #define C_APDU_DISABLE 0x26
Martyn Gilbertson 0:37cdeb4f5b6c 36 #define C_APDU_ENABLE 0x28
Martyn Gilbertson 0:37cdeb4f5b6c 37
Martyn Gilbertson 0:37cdeb4f5b6c 38 /* GPO management commands */
Martyn Gilbertson 0:37cdeb4f5b6c 39 #define C_APDU_INTERRUPT 0xD6
Martyn Gilbertson 0:37cdeb4f5b6c 40
Martyn Gilbertson 0:37cdeb4f5b6c 41 /* length */
Martyn Gilbertson 0:37cdeb4f5b6c 42 #define STATUS_LENGTH 2
Martyn Gilbertson 0:37cdeb4f5b6c 43 #define CRC_LENGTH 2
Martyn Gilbertson 0:37cdeb4f5b6c 44 #define STATUS_RESPONSE_LENGTH 5
Martyn Gilbertson 0:37cdeb4f5b6c 45 #define DESELECT_RESPONSE_LENGTH 3
Martyn Gilbertson 0:37cdeb4f5b6c 46 #define WATING_TIME_EXT_RESPONSE_LENGTH 4
Martyn Gilbertson 0:37cdeb4f5b6c 47 #define PASSWORD_LENGTH 16
Martyn Gilbertson 0:37cdeb4f5b6c 48
Martyn Gilbertson 0:37cdeb4f5b6c 49 #define DESELECT_REQUEST_COMMAND "\xC2\xE0\xB4"
Martyn Gilbertson 0:37cdeb4f5b6c 50 #define SELECT_APPLICATION_COMMAND "\xD2\x76\x00\x00\x85\x01\x01"
Martyn Gilbertson 0:37cdeb4f5b6c 51
Martyn Gilbertson 0:37cdeb4f5b6c 52 /* command structure mask */
Martyn Gilbertson 0:37cdeb4f5b6c 53 #define CMD_MASK_SELECT_APPLICATION 0x01FF
Martyn Gilbertson 0:37cdeb4f5b6c 54 #define CMD_MASK_SELECT_CC_FILE 0x017F
Martyn Gilbertson 0:37cdeb4f5b6c 55 #define CMD_MASK_SELECT_NDEF_FILE 0x017F
Martyn Gilbertson 0:37cdeb4f5b6c 56 #define CMD_MASK_READ_BINARY 0x019F
Martyn Gilbertson 0:37cdeb4f5b6c 57 #define CMD_MASK_UPDATE_BINARY 0x017F
Martyn Gilbertson 0:37cdeb4f5b6c 58 #define CMD_MASK_VERIFY_BINARY_WO_PWD 0x013F
Martyn Gilbertson 0:37cdeb4f5b6c 59 #define CMD_MASK_VERIFY_BINARY_WITH_PWD 0x017F
Martyn Gilbertson 0:37cdeb4f5b6c 60 #define CMD_MASK_CHANGE_REF_DATA 0x017F
Martyn Gilbertson 0:37cdeb4f5b6c 61 #define CMD_MASK_ENABLE_VERIFREQ 0x011F
Martyn Gilbertson 0:37cdeb4f5b6c 62 #define CMD_MASK_DISABLE_VERIFREQ 0x011F
Martyn Gilbertson 0:37cdeb4f5b6c 63 #define CMD_MASK_SEND_INTERRUPT 0x013F
Martyn Gilbertson 0:37cdeb4f5b6c 64 #define CMD_MASK_GPO_STATE 0x017F
Martyn Gilbertson 0:37cdeb4f5b6c 65
Martyn Gilbertson 0:37cdeb4f5b6c 66 /* command structure values for the mask */
Martyn Gilbertson 0:37cdeb4f5b6c 67 #define PCB_NEEDED 0x0001 /* PCB byte present or not */
Martyn Gilbertson 0:37cdeb4f5b6c 68 #define CLA_NEEDED 0x0002 /* CLA byte present or not */
Martyn Gilbertson 0:37cdeb4f5b6c 69 #define INS_NEEDED 0x0004 /* Operation code present or not*/
Martyn Gilbertson 0:37cdeb4f5b6c 70 #define P1_NEEDED 0x0008 /* Selection Mode present or not*/
Martyn Gilbertson 0:37cdeb4f5b6c 71 #define P2_NEEDED 0x0010 /* Selection Option present or not*/
Martyn Gilbertson 0:37cdeb4f5b6c 72 #define LC_NEEDED 0x0020 /* Data field length byte present or not */
Martyn Gilbertson 0:37cdeb4f5b6c 73 #define DATA_NEEDED 0x0040 /* Data present or not */
Martyn Gilbertson 0:37cdeb4f5b6c 74 #define LE_NEEDED 0x0080 /* Expected length present or not */
Martyn Gilbertson 0:37cdeb4f5b6c 75 #define CRC_NEEDED 0x0100 /* 2 CRC bytes present or not */
Martyn Gilbertson 0:37cdeb4f5b6c 76 #define DID_NEEDED 0x08 /* DID byte present or not */
Martyn Gilbertson 0:37cdeb4f5b6c 77
Martyn Gilbertson 0:37cdeb4f5b6c 78 /* offset */
Martyn Gilbertson 0:37cdeb4f5b6c 79 #define OFFSET_PCB 0
Martyn Gilbertson 0:37cdeb4f5b6c 80 #define OFFSET_CLASS 1
Martyn Gilbertson 0:37cdeb4f5b6c 81 #define OFFSET_INS 2
Martyn Gilbertson 0:37cdeb4f5b6c 82 #define OFFSET_P1 3
Martyn Gilbertson 0:37cdeb4f5b6c 83
Martyn Gilbertson 0:37cdeb4f5b6c 84 /* mask */
Martyn Gilbertson 0:37cdeb4f5b6c 85 #define MASK_BLOCK 0xC0
Martyn Gilbertson 0:37cdeb4f5b6c 86 #define MASK_I_BLOCK 0x00
Martyn Gilbertson 0:37cdeb4f5b6c 87 #define MASK_R_BLOCK 0x80
Martyn Gilbertson 0:37cdeb4f5b6c 88 #define MASK_S_BLOCK 0xC0
Martyn Gilbertson 0:37cdeb4f5b6c 89
Martyn Gilbertson 0:37cdeb4f5b6c 90 #define GETMSB(val) ((uint8_t) ((val & 0xFF00)>>8))
Martyn Gilbertson 0:37cdeb4f5b6c 91 #define GETLSB(val) ((uint8_t) (val & 0x00FF))
Martyn Gilbertson 0:37cdeb4f5b6c 92 #define SWAPS(val) (uint16_t) ((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8);
Martyn Gilbertson 0:37cdeb4f5b6c 93
Martyn Gilbertson 1:e356ce0033e4 94 /** Default I2C Frequency 500 kHz (820 kHz maximum) */
Martyn Gilbertson 0:37cdeb4f5b6c 95 #define M24SR_DEFAULT_FREQUENCY (uint32_t)500000
Martyn Gilbertson 0:37cdeb4f5b6c 96
Martyn Gilbertson 0:37cdeb4f5b6c 97
Martyn Gilbertson 2:de5aea7f83cd 98 M24SR::M24SR(PinName sda, PinName scl, uint8_t address, uint8_t *pass) : _i2c(sda,scl), _addr(address),
Martyn Gilbertson 0:37cdeb4f5b6c 99 _session_open(false), _ndef_size(0), _ndef_hdr_size(0), _write_bytes(0)
Martyn Gilbertson 0:37cdeb4f5b6c 100 {
Martyn Gilbertson 0:37cdeb4f5b6c 101 frequency(M24SR_DEFAULT_FREQUENCY);
Martyn Gilbertson 2:de5aea7f83cd 102 password(pass);
Martyn Gilbertson 0:37cdeb4f5b6c 103 }
Martyn Gilbertson 0:37cdeb4f5b6c 104
Martyn Gilbertson 0:37cdeb4f5b6c 105
Martyn Gilbertson 0:37cdeb4f5b6c 106 M24SR::~M24SR()
Martyn Gilbertson 0:37cdeb4f5b6c 107 {
Martyn Gilbertson 0:37cdeb4f5b6c 108
Martyn Gilbertson 0:37cdeb4f5b6c 109 }
Martyn Gilbertson 0:37cdeb4f5b6c 110
Martyn Gilbertson 0:37cdeb4f5b6c 111
Martyn Gilbertson 2:de5aea7f83cd 112 void M24SR::password(uint8_t *pass)
Martyn Gilbertson 2:de5aea7f83cd 113 {
Martyn Gilbertson 2:de5aea7f83cd 114 memcpy(_password, pass, 16);
Martyn Gilbertson 2:de5aea7f83cd 115 }
Martyn Gilbertson 2:de5aea7f83cd 116
Martyn Gilbertson 2:de5aea7f83cd 117
Martyn Gilbertson 0:37cdeb4f5b6c 118 void M24SR::frequency(uint32_t hz)
Martyn Gilbertson 0:37cdeb4f5b6c 119 {
Martyn Gilbertson 1:e356ce0033e4 120 _i2c.frequency(hz);
Martyn Gilbertson 0:37cdeb4f5b6c 121 }
Martyn Gilbertson 0:37cdeb4f5b6c 122
Martyn Gilbertson 0:37cdeb4f5b6c 123
Martyn Gilbertson 2:de5aea7f83cd 124 M24SR::status_t M24SR::verify(bool with_password)
Martyn Gilbertson 2:de5aea7f83cd 125 {
Martyn Gilbertson 2:de5aea7f83cd 126 status_t ret;
Martyn Gilbertson 2:de5aea7f83cd 127 uint16_t length;
Martyn Gilbertson 2:de5aea7f83cd 128
Martyn Gilbertson 2:de5aea7f83cd 129 // verify with password
Martyn Gilbertson 2:de5aea7f83cd 130 if (with_password)
Martyn Gilbertson 2:de5aea7f83cd 131 {
Martyn Gilbertson 2:de5aea7f83cd 132 C_APDU command(C_APDU_CLA_DEFAULT, C_APDU_VERIFY, 0x0003, 16, _password, 0);
Martyn Gilbertson 2:de5aea7f83cd 133
Martyn Gilbertson 2:de5aea7f83cd 134 /* build the I2C command */
Martyn Gilbertson 2:de5aea7f83cd 135 build_I_block_command(CMD_MASK_VERIFY_BINARY_WITH_PWD, &command, 0x00, &length, _packet_data);
Martyn Gilbertson 2:de5aea7f83cd 136
Martyn Gilbertson 2:de5aea7f83cd 137 }else{
Martyn Gilbertson 2:de5aea7f83cd 138 // verify with no password
Martyn Gilbertson 2:de5aea7f83cd 139
Martyn Gilbertson 2:de5aea7f83cd 140 C_APDU command(C_APDU_CLA_DEFAULT, C_APDU_VERIFY, 0x0003, 0, NULL, 0);
Martyn Gilbertson 2:de5aea7f83cd 141
Martyn Gilbertson 2:de5aea7f83cd 142 /* build the I2C command */
Martyn Gilbertson 2:de5aea7f83cd 143 build_I_block_command(CMD_MASK_VERIFY_BINARY_WO_PWD, &command, 0x00, &length, _packet_data);
Martyn Gilbertson 2:de5aea7f83cd 144 }
Martyn Gilbertson 2:de5aea7f83cd 145
Martyn Gilbertson 2:de5aea7f83cd 146 if ( _i2c.write(M24SR_DEFAULT_ADDRESS, (const char*) _packet_data, length) != 0 )
Martyn Gilbertson 2:de5aea7f83cd 147 {
Martyn Gilbertson 2:de5aea7f83cd 148 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 2:de5aea7f83cd 149 }
Martyn Gilbertson 2:de5aea7f83cd 150
Martyn Gilbertson 2:de5aea7f83cd 151 ret = io_poll_i2c();
Martyn Gilbertson 2:de5aea7f83cd 152 if (ret == M24SR_SUCCESS)
Martyn Gilbertson 2:de5aea7f83cd 153 {
Martyn Gilbertson 2:de5aea7f83cd 154 if ( _i2c.read(M24SR_DEFAULT_ADDRESS, (char*) _packet_data, STATUS_RESPONSE_LENGTH ) != 0 )
Martyn Gilbertson 2:de5aea7f83cd 155 {
Martyn Gilbertson 2:de5aea7f83cd 156 ret = M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 2:de5aea7f83cd 157 }else{
Martyn Gilbertson 2:de5aea7f83cd 158 ret = is_correct_crc_residue(_packet_data, STATUS_RESPONSE_LENGTH);
Martyn Gilbertson 2:de5aea7f83cd 159 }
Martyn Gilbertson 2:de5aea7f83cd 160 }
Martyn Gilbertson 2:de5aea7f83cd 161
Martyn Gilbertson 2:de5aea7f83cd 162 return ret;
Martyn Gilbertson 2:de5aea7f83cd 163 }
Martyn Gilbertson 2:de5aea7f83cd 164
Martyn Gilbertson 2:de5aea7f83cd 165
Martyn Gilbertson 2:de5aea7f83cd 166 M24SR::status_t M24SR::set_system_gpo(nfc_gpo_state_t rf, nfc_gpo_state_t i2c)
Martyn Gilbertson 2:de5aea7f83cd 167 {
Martyn Gilbertson 2:de5aea7f83cd 168 status_t ret;
Martyn Gilbertson 2:de5aea7f83cd 169 uint8_t gpo_state;
Martyn Gilbertson 2:de5aea7f83cd 170 uint8_t new_state = (rf << 4) | i2c;
Martyn Gilbertson 2:de5aea7f83cd 171
Martyn Gilbertson 2:de5aea7f83cd 172 if ( (ret = get_session(1)) != M24SR_SUCCESS )
Martyn Gilbertson 2:de5aea7f83cd 173 {
Martyn Gilbertson 2:de5aea7f83cd 174 // printf("Error opening session %4.4X\n", ret);
Martyn Gilbertson 2:de5aea7f83cd 175 return ret;
Martyn Gilbertson 2:de5aea7f83cd 176 }
Martyn Gilbertson 2:de5aea7f83cd 177
Martyn Gilbertson 2:de5aea7f83cd 178 if ( (ret = select_type((uint8_t*)SELECT_APPLICATION_COMMAND, 7, 0x0400, CMD_MASK_SELECT_APPLICATION)) != M24SR_SUCCESS)
Martyn Gilbertson 2:de5aea7f83cd 179 {
Martyn Gilbertson 2:de5aea7f83cd 180 // printf("Error Select Application %4.4X\n", ret );
Martyn Gilbertson 2:de5aea7f83cd 181 return ret;
Martyn Gilbertson 2:de5aea7f83cd 182 }
Martyn Gilbertson 2:de5aea7f83cd 183
Martyn Gilbertson 2:de5aea7f83cd 184 if ( (ret = select_type((uint8_t*)SYSTEM_FILE_ID_BYTES, 2, 0x000C, CMD_MASK_SELECT_CC_FILE)) != M24SR_SUCCESS)
Martyn Gilbertson 2:de5aea7f83cd 185 {
Martyn Gilbertson 2:de5aea7f83cd 186 // printf("Error select System file\r\n");
Martyn Gilbertson 2:de5aea7f83cd 187 return ret;
Martyn Gilbertson 2:de5aea7f83cd 188 }
Martyn Gilbertson 2:de5aea7f83cd 189
Martyn Gilbertson 2:de5aea7f83cd 190
Martyn Gilbertson 2:de5aea7f83cd 191 // get GPO state
Martyn Gilbertson 2:de5aea7f83cd 192 if ( (ret = read_binary( 0x0004, 1, (uint8_t*)&gpo_state )) != M24SR_SUCCESS )
Martyn Gilbertson 2:de5aea7f83cd 193 {
Martyn Gilbertson 2:de5aea7f83cd 194 //printf("Error read System File %4.4X\n", ret );
Martyn Gilbertson 2:de5aea7f83cd 195 return ret;
Martyn Gilbertson 2:de5aea7f83cd 196 }
Martyn Gilbertson 2:de5aea7f83cd 197
Martyn Gilbertson 2:de5aea7f83cd 198 //printf("New State: %2.2X Old State: %2.2X\n", new_state, gpo_state);
Martyn Gilbertson 2:de5aea7f83cd 199
Martyn Gilbertson 2:de5aea7f83cd 200 if (gpo_state == new_state)
Martyn Gilbertson 2:de5aea7f83cd 201 {
Martyn Gilbertson 2:de5aea7f83cd 202 return M24SR_SUCCESS;
Martyn Gilbertson 2:de5aea7f83cd 203 }
Martyn Gilbertson 2:de5aea7f83cd 204
Martyn Gilbertson 2:de5aea7f83cd 205 verify(_password);
Martyn Gilbertson 2:de5aea7f83cd 206
Martyn Gilbertson 2:de5aea7f83cd 207 // write new GPO state
Martyn Gilbertson 2:de5aea7f83cd 208 if ( (ret = update_binary( 0x0004, 1, (uint8_t*)&new_state )) != M24SR_SUCCESS )
Martyn Gilbertson 2:de5aea7f83cd 209 {
Martyn Gilbertson 2:de5aea7f83cd 210 //printf("Error update System File %4.4X\n", ret );
Martyn Gilbertson 2:de5aea7f83cd 211 return ret;
Martyn Gilbertson 2:de5aea7f83cd 212 }
Martyn Gilbertson 2:de5aea7f83cd 213
Martyn Gilbertson 2:de5aea7f83cd 214 // verify GPO state
Martyn Gilbertson 2:de5aea7f83cd 215 if ( (ret = read_binary( 0x0004, 1, (uint8_t*)&gpo_state )) != M24SR_SUCCESS )
Martyn Gilbertson 2:de5aea7f83cd 216 {
Martyn Gilbertson 2:de5aea7f83cd 217 //printf("Error read System File %4.4X\n", ret );
Martyn Gilbertson 2:de5aea7f83cd 218 return ret;
Martyn Gilbertson 2:de5aea7f83cd 219 }
Martyn Gilbertson 2:de5aea7f83cd 220
Martyn Gilbertson 2:de5aea7f83cd 221 if (gpo_state != new_state)
Martyn Gilbertson 2:de5aea7f83cd 222 {
Martyn Gilbertson 2:de5aea7f83cd 223 //printf("Error updating GPO State\r\n");
Martyn Gilbertson 2:de5aea7f83cd 224 return M24SR_UNSUCESSFUL_UPDATING;
Martyn Gilbertson 2:de5aea7f83cd 225 }
Martyn Gilbertson 2:de5aea7f83cd 226
Martyn Gilbertson 2:de5aea7f83cd 227
Martyn Gilbertson 2:de5aea7f83cd 228 deselect();
Martyn Gilbertson 2:de5aea7f83cd 229 //printf("Updated GPO State:%2.2X", gpo_state);
Martyn Gilbertson 2:de5aea7f83cd 230
Martyn Gilbertson 2:de5aea7f83cd 231 return ret;
Martyn Gilbertson 2:de5aea7f83cd 232 }
Martyn Gilbertson 2:de5aea7f83cd 233
Martyn Gilbertson 2:de5aea7f83cd 234
Martyn Gilbertson 2:de5aea7f83cd 235
Martyn Gilbertson 0:37cdeb4f5b6c 236 M24SR::status_t M24SR::session_start(bool parse_header)
Martyn Gilbertson 0:37cdeb4f5b6c 237 {
Martyn Gilbertson 0:37cdeb4f5b6c 238 status_t ret;
Martyn Gilbertson 0:37cdeb4f5b6c 239
Martyn Gilbertson 0:37cdeb4f5b6c 240 _ndef_hdr_size = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 241 _session_open = false;
Martyn Gilbertson 0:37cdeb4f5b6c 242 _ndef_size = 0; // no ndef file set
Martyn Gilbertson 0:37cdeb4f5b6c 243 _write_bytes = 0; // clear write bytes
Martyn Gilbertson 0:37cdeb4f5b6c 244
Martyn Gilbertson 0:37cdeb4f5b6c 245 /*
Martyn Gilbertson 0:37cdeb4f5b6c 246 1. Start session
Martyn Gilbertson 0:37cdeb4f5b6c 247 2. Send the SelectNDEFTagApplication command
Martyn Gilbertson 0:37cdeb4f5b6c 248 3. Select the CC file
Martyn Gilbertson 0:37cdeb4f5b6c 249 4. Read the CC file
Martyn Gilbertson 0:37cdeb4f5b6c 250 5. Select the NDEF file.
Martyn Gilbertson 0:37cdeb4f5b6c 251 */
Martyn Gilbertson 0:37cdeb4f5b6c 252
Martyn Gilbertson 0:37cdeb4f5b6c 253 if ( (ret = get_session(1)) != M24SR_SUCCESS )
Martyn Gilbertson 0:37cdeb4f5b6c 254 {
Martyn Gilbertson 0:37cdeb4f5b6c 255 // printf("Error opening session %4.4X\n", ret);
Martyn Gilbertson 0:37cdeb4f5b6c 256 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 257 }
Martyn Gilbertson 0:37cdeb4f5b6c 258
Martyn Gilbertson 0:37cdeb4f5b6c 259 if ( (ret = select_type((uint8_t*)SELECT_APPLICATION_COMMAND, 7, 0x0400, CMD_MASK_SELECT_APPLICATION)) != M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 260 {
Martyn Gilbertson 0:37cdeb4f5b6c 261 // printf("Error Select Application %4.4X\n", ret );
Martyn Gilbertson 0:37cdeb4f5b6c 262 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 263 }
Martyn Gilbertson 0:37cdeb4f5b6c 264
Martyn Gilbertson 0:37cdeb4f5b6c 265 if ( (ret = select_type((uint8_t*)CC_FILE_ID_BYTES, 2, 0x000C, CMD_MASK_SELECT_CC_FILE)) != M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 266 {
Martyn Gilbertson 0:37cdeb4f5b6c 267 // printf("Error read CC file\r\n");
Martyn Gilbertson 0:37cdeb4f5b6c 268 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 269 }
Martyn Gilbertson 0:37cdeb4f5b6c 270
Martyn Gilbertson 0:37cdeb4f5b6c 271 uint16_t ndef_id = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 272
Martyn Gilbertson 0:37cdeb4f5b6c 273 // get ndef ID
Martyn Gilbertson 0:37cdeb4f5b6c 274 if ( (ret = read_binary( 9, 2, (uint8_t*) &ndef_id )) != M24SR_SUCCESS )
Martyn Gilbertson 0:37cdeb4f5b6c 275 {
Martyn Gilbertson 0:37cdeb4f5b6c 276 // printf("Error read NDEF File %4.4X\n", ret );
Martyn Gilbertson 0:37cdeb4f5b6c 277 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 278 }
Martyn Gilbertson 0:37cdeb4f5b6c 279
Martyn Gilbertson 0:37cdeb4f5b6c 280 if ( (ret = select_type((uint8_t*)&ndef_id, 2, 0x000C, CMD_MASK_SELECT_NDEF_FILE ) ) != M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 281 {
Martyn Gilbertson 0:37cdeb4f5b6c 282 // printf("Error Select NDEF File %4.4X\n", ret );
Martyn Gilbertson 0:37cdeb4f5b6c 283 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 284 }
Martyn Gilbertson 0:37cdeb4f5b6c 285
Martyn Gilbertson 0:37cdeb4f5b6c 286 if (parse_header == true)
Martyn Gilbertson 0:37cdeb4f5b6c 287 {
Martyn Gilbertson 0:37cdeb4f5b6c 288 /** Get NDEF Header info used for reading */
Martyn Gilbertson 0:37cdeb4f5b6c 289 ret = parse_ndef_header();
Martyn Gilbertson 0:37cdeb4f5b6c 290 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 291 _session_open = true;
Martyn Gilbertson 0:37cdeb4f5b6c 292 }
Martyn Gilbertson 0:37cdeb4f5b6c 293 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 294 }
Martyn Gilbertson 0:37cdeb4f5b6c 295
Martyn Gilbertson 0:37cdeb4f5b6c 296
Martyn Gilbertson 0:37cdeb4f5b6c 297 M24SR::status_t M24SR::session_end(bool cancel)
Martyn Gilbertson 0:37cdeb4f5b6c 298 {
Martyn Gilbertson 0:37cdeb4f5b6c 299 if ( _session_open == true && _write_bytes != 0 && cancel == false )
Martyn Gilbertson 0:37cdeb4f5b6c 300 {
Martyn Gilbertson 0:37cdeb4f5b6c 301 // write size and header
Martyn Gilbertson 0:37cdeb4f5b6c 302 write_ndef_header(true);
Martyn Gilbertson 0:37cdeb4f5b6c 303 }
Martyn Gilbertson 0:37cdeb4f5b6c 304
Martyn Gilbertson 0:37cdeb4f5b6c 305 _session_open = false;
Martyn Gilbertson 0:37cdeb4f5b6c 306 _ndef_hdr_size = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 307 _ndef_size = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 308 _write_bytes = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 309
Martyn Gilbertson 0:37cdeb4f5b6c 310 deselect();
Martyn Gilbertson 0:37cdeb4f5b6c 311
Martyn Gilbertson 0:37cdeb4f5b6c 312 return M24SR_SUCCESS;
Martyn Gilbertson 0:37cdeb4f5b6c 313 }
Martyn Gilbertson 0:37cdeb4f5b6c 314
Martyn Gilbertson 0:37cdeb4f5b6c 315
Martyn Gilbertson 0:37cdeb4f5b6c 316 M24SR::status_t M24SR::read(uint16_t addr, char* data, uint16_t size)
Martyn Gilbertson 0:37cdeb4f5b6c 317 {
Martyn Gilbertson 0:37cdeb4f5b6c 318 status_t ret;
Martyn Gilbertson 0:37cdeb4f5b6c 319
Martyn Gilbertson 0:37cdeb4f5b6c 320 if ( _session_open == false )
Martyn Gilbertson 0:37cdeb4f5b6c 321 {
Martyn Gilbertson 0:37cdeb4f5b6c 322 return M24SR_ERROR;
Martyn Gilbertson 0:37cdeb4f5b6c 323 }
Martyn Gilbertson 0:37cdeb4f5b6c 324
Martyn Gilbertson 0:37cdeb4f5b6c 325 if ( _ndef_hdr_size + addr + size > _ndef_size )
Martyn Gilbertson 0:37cdeb4f5b6c 326 {
Martyn Gilbertson 0:37cdeb4f5b6c 327 return M24SR_WRONG_LENGHT;
Martyn Gilbertson 0:37cdeb4f5b6c 328 }
Martyn Gilbertson 0:37cdeb4f5b6c 329
Martyn Gilbertson 1:e356ce0033e4 330 #if (M24SR_READ_CONTINOUS)
Martyn Gilbertson 1:e356ce0033e4 331
Martyn Gilbertson 1:e356ce0033e4 332 int16_t wlen = 0; // read length
Martyn Gilbertson 1:e356ce0033e4 333 int16_t dlen = size; // data length remaining
Martyn Gilbertson 1:e356ce0033e4 334 int16_t addr_ofst = 0; // address to read
Martyn Gilbertson 1:e356ce0033e4 335
Martyn Gilbertson 1:e356ce0033e4 336 while (dlen > 0)
Martyn Gilbertson 1:e356ce0033e4 337 {
Martyn Gilbertson 1:e356ce0033e4 338 wlen = ((dlen > MAX_PAYLOAD ) ? MAX_PAYLOAD : dlen);
Martyn Gilbertson 1:e356ce0033e4 339
Martyn Gilbertson 1:e356ce0033e4 340 // if addr is not at the start of a page then read bytes until we hit the boundary
Martyn Gilbertson 1:e356ce0033e4 341 if ( addr_ofst == 0 && (addr % MAX_PAYLOAD ) != 0 )
Martyn Gilbertson 1:e356ce0033e4 342 {
Martyn Gilbertson 1:e356ce0033e4 343 wlen = MAX_PAYLOAD - (addr % MAX_PAYLOAD );
Martyn Gilbertson 1:e356ce0033e4 344 // check we have enough data
Martyn Gilbertson 1:e356ce0033e4 345 if (size < wlen)
Martyn Gilbertson 1:e356ce0033e4 346 {
Martyn Gilbertson 1:e356ce0033e4 347 wlen = size;
Martyn Gilbertson 1:e356ce0033e4 348 }
Martyn Gilbertson 1:e356ce0033e4 349 }
Martyn Gilbertson 1:e356ce0033e4 350
Martyn Gilbertson 1:e356ce0033e4 351 //printf("Read: Addr:%d Write: %d Remain: %d next: %d\n", addr + addr_ofst, wlen, dlen - wlen , addr_ofst + wlen);
Martyn Gilbertson 1:e356ce0033e4 352
Martyn Gilbertson 1:e356ce0033e4 353 // read in blocks of %MAX_PAYLOAD%
Martyn Gilbertson 1:e356ce0033e4 354 if ( (ret = read_binary( _ndef_hdr_size + addr + addr_ofst, wlen, (uint8_t*)data + addr_ofst )) != M24SR_SUCCESS )
Martyn Gilbertson 1:e356ce0033e4 355 {
Martyn Gilbertson 1:e356ce0033e4 356 return ret;
Martyn Gilbertson 1:e356ce0033e4 357 }
Martyn Gilbertson 1:e356ce0033e4 358
Martyn Gilbertson 1:e356ce0033e4 359
Martyn Gilbertson 1:e356ce0033e4 360 dlen -= wlen;
Martyn Gilbertson 1:e356ce0033e4 361 addr_ofst += wlen;
Martyn Gilbertson 1:e356ce0033e4 362 }
Martyn Gilbertson 1:e356ce0033e4 363 #else
Martyn Gilbertson 0:37cdeb4f5b6c 364 if ( (ret = read_binary( _ndef_hdr_size + addr, size, (uint8_t*)data )) != M24SR_SUCCESS )
Martyn Gilbertson 0:37cdeb4f5b6c 365 {
Martyn Gilbertson 0:37cdeb4f5b6c 366 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 367 }
Martyn Gilbertson 1:e356ce0033e4 368 #endif
Martyn Gilbertson 0:37cdeb4f5b6c 369 return M24SR_SUCCESS;
Martyn Gilbertson 0:37cdeb4f5b6c 370 }
Martyn Gilbertson 0:37cdeb4f5b6c 371
Martyn Gilbertson 0:37cdeb4f5b6c 372
Martyn Gilbertson 0:37cdeb4f5b6c 373 M24SR::status_t M24SR::write(uint16_t addr, const char* data, uint16_t size)
Martyn Gilbertson 0:37cdeb4f5b6c 374 {
Martyn Gilbertson 0:37cdeb4f5b6c 375 // write in blocks of MAX_PAYLOAD
Martyn Gilbertson 0:37cdeb4f5b6c 376 status_t ret;
Martyn Gilbertson 0:37cdeb4f5b6c 377
Martyn Gilbertson 0:37cdeb4f5b6c 378 if ( _session_open == false )
Martyn Gilbertson 0:37cdeb4f5b6c 379 {
Martyn Gilbertson 0:37cdeb4f5b6c 380 return M24SR_ERROR;
Martyn Gilbertson 0:37cdeb4f5b6c 381 }
Martyn Gilbertson 0:37cdeb4f5b6c 382
Martyn Gilbertson 0:37cdeb4f5b6c 383 // start a write session if not already started by using the _write_bytes to maintain header size
Martyn Gilbertson 0:37cdeb4f5b6c 384 if (_write_bytes == 0)
Martyn Gilbertson 0:37cdeb4f5b6c 385 {
Martyn Gilbertson 0:37cdeb4f5b6c 386 // build NDEF header to determine header size
Martyn Gilbertson 0:37cdeb4f5b6c 387 write_ndef_header(false);
Martyn Gilbertson 0:37cdeb4f5b6c 388 }
Martyn Gilbertson 0:37cdeb4f5b6c 389 _write_bytes += size;
Martyn Gilbertson 0:37cdeb4f5b6c 390
Martyn Gilbertson 0:37cdeb4f5b6c 391 if ( _ndef_hdr_size + addr + _write_bytes > 8000 )
Martyn Gilbertson 0:37cdeb4f5b6c 392 {
Martyn Gilbertson 0:37cdeb4f5b6c 393 return M24SR_WRONG_LENGHT;
Martyn Gilbertson 0:37cdeb4f5b6c 394 }
Martyn Gilbertson 0:37cdeb4f5b6c 395
Martyn Gilbertson 1:e356ce0033e4 396 #if (M24SR_WRITE_CONTINOUS)
Martyn Gilbertson 0:37cdeb4f5b6c 397
Martyn Gilbertson 0:37cdeb4f5b6c 398 int16_t wlen = 0; // write length
Martyn Gilbertson 0:37cdeb4f5b6c 399 int16_t dlen = size; // data length remaining
Martyn Gilbertson 0:37cdeb4f5b6c 400 int16_t addr_ofst = 0; // address to write
Martyn Gilbertson 0:37cdeb4f5b6c 401
Martyn Gilbertson 0:37cdeb4f5b6c 402 while (dlen > 0)
Martyn Gilbertson 0:37cdeb4f5b6c 403 {
Martyn Gilbertson 0:37cdeb4f5b6c 404 wlen = ((dlen > MAX_PAYLOAD ) ? MAX_PAYLOAD : dlen);
Martyn Gilbertson 0:37cdeb4f5b6c 405
Martyn Gilbertson 0:37cdeb4f5b6c 406 // if addr is not at the start of a page then write bytes until we hit the boundary
Martyn Gilbertson 0:37cdeb4f5b6c 407 if ( addr_ofst == 0 && (addr % MAX_PAYLOAD ) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 408 {
Martyn Gilbertson 0:37cdeb4f5b6c 409 wlen = MAX_PAYLOAD - (addr % MAX_PAYLOAD );
Martyn Gilbertson 0:37cdeb4f5b6c 410 // check we have enough data to hit end of page if not just write the entire length
Martyn Gilbertson 0:37cdeb4f5b6c 411 if (size < wlen)
Martyn Gilbertson 0:37cdeb4f5b6c 412 {
Martyn Gilbertson 0:37cdeb4f5b6c 413 wlen = size;
Martyn Gilbertson 0:37cdeb4f5b6c 414 }
Martyn Gilbertson 0:37cdeb4f5b6c 415 }
Martyn Gilbertson 0:37cdeb4f5b6c 416
Martyn Gilbertson 0:37cdeb4f5b6c 417 //printf("Write: Addr:%d Write: %d Remain: %d next: %d\n", addr + addr_ofst, wlen, dlen - wlen , addr_ofst + wlen);
Martyn Gilbertson 0:37cdeb4f5b6c 418
Martyn Gilbertson 0:37cdeb4f5b6c 419 // write in blocks of %MAX_PAYLOAD%
Martyn Gilbertson 0:37cdeb4f5b6c 420 if ( (ret = update_binary( _ndef_hdr_size + addr + addr_ofst, wlen, (uint8_t*)data + addr_ofst )) != M24SR_SUCCESS )
Martyn Gilbertson 0:37cdeb4f5b6c 421 {
Martyn Gilbertson 0:37cdeb4f5b6c 422 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 423 }
Martyn Gilbertson 0:37cdeb4f5b6c 424
Martyn Gilbertson 0:37cdeb4f5b6c 425
Martyn Gilbertson 0:37cdeb4f5b6c 426 dlen -= wlen;
Martyn Gilbertson 0:37cdeb4f5b6c 427 addr_ofst += wlen;
Martyn Gilbertson 0:37cdeb4f5b6c 428 }
Martyn Gilbertson 1:e356ce0033e4 429 #else
Martyn Gilbertson 1:e356ce0033e4 430 // printf("Write:%d\r\n", size);
Martyn Gilbertson 1:e356ce0033e4 431 if ( (ret = update_binary( _ndef_hdr_size + addr , size, (uint8_t*)data )) != M24SR_SUCCESS )
Martyn Gilbertson 1:e356ce0033e4 432 {
Martyn Gilbertson 1:e356ce0033e4 433 return ret;
Martyn Gilbertson 1:e356ce0033e4 434 }
Martyn Gilbertson 1:e356ce0033e4 435 #endif // #if (M24SR_WRITE_CONTINOUS)
Martyn Gilbertson 0:37cdeb4f5b6c 436
Martyn Gilbertson 0:37cdeb4f5b6c 437 return M24SR_SUCCESS;
Martyn Gilbertson 0:37cdeb4f5b6c 438 }
Martyn Gilbertson 0:37cdeb4f5b6c 439
Martyn Gilbertson 0:37cdeb4f5b6c 440
Martyn Gilbertson 0:37cdeb4f5b6c 441 M24SR::status_t M24SR::write_ndef_header(bool write)
Martyn Gilbertson 0:37cdeb4f5b6c 442 {
Martyn Gilbertson 0:37cdeb4f5b6c 443 status_t ret;
Martyn Gilbertson 0:37cdeb4f5b6c 444
Martyn Gilbertson 0:37cdeb4f5b6c 445 typedef struct __attribute__((packed))
Martyn Gilbertson 0:37cdeb4f5b6c 446 {
Martyn Gilbertson 0:37cdeb4f5b6c 447 uint8_t flags; // C1
Martyn Gilbertson 0:37cdeb4f5b6c 448 uint8_t type_len; // 1
Martyn Gilbertson 0:37cdeb4f5b6c 449 uint16_t pad; // 32bit padding if not SR flag
Martyn Gilbertson 0:37cdeb4f5b6c 450 uint16_t len; // len big endian
Martyn Gilbertson 0:37cdeb4f5b6c 451 uint8_t type; // 0x54
Martyn Gilbertson 0:37cdeb4f5b6c 452 uint8_t lang_len; // 0x02
Martyn Gilbertson 0:37cdeb4f5b6c 453 uint8_t lang1; // 'e'
Martyn Gilbertson 0:37cdeb4f5b6c 454 uint8_t lang2; // 'n'
Martyn Gilbertson 0:37cdeb4f5b6c 455 }ndef_hdr;
Martyn Gilbertson 0:37cdeb4f5b6c 456
Martyn Gilbertson 0:37cdeb4f5b6c 457 ndef_hdr hdr = {0xC1, 0x01, 0x0000,0x0000, 0x54, 0x02, 'e','n'}; // long
Martyn Gilbertson 0:37cdeb4f5b6c 458 //ndef_hdr hdr = {0xD1, 0x01, 0x01, 0x54, 0x02, 'e','n'}; // short
Martyn Gilbertson 0:37cdeb4f5b6c 459
Martyn Gilbertson 0:37cdeb4f5b6c 460 hdr.len = 3 + _write_bytes; // bytes in payload + lang
Martyn Gilbertson 0:37cdeb4f5b6c 461
Martyn Gilbertson 0:37cdeb4f5b6c 462 hdr.len = SWAPS( hdr.len );
Martyn Gilbertson 0:37cdeb4f5b6c 463
Martyn Gilbertson 0:37cdeb4f5b6c 464 // set size
Martyn Gilbertson 0:37cdeb4f5b6c 465 _ndef_hdr_size = 10 + 2 ; // header len includes 2 size bytes
Martyn Gilbertson 0:37cdeb4f5b6c 466
Martyn Gilbertson 0:37cdeb4f5b6c 467 if (write == true)
Martyn Gilbertson 0:37cdeb4f5b6c 468 {
Martyn Gilbertson 0:37cdeb4f5b6c 469 // write header
Martyn Gilbertson 0:37cdeb4f5b6c 470 ret = update_binary(2, 10, (uint8_t*)&hdr);
Martyn Gilbertson 0:37cdeb4f5b6c 471
Martyn Gilbertson 0:37cdeb4f5b6c 472 // write size
Martyn Gilbertson 0:37cdeb4f5b6c 473 uint16_t szc = _write_bytes + 10;
Martyn Gilbertson 0:37cdeb4f5b6c 474 szc = SWAPS ( szc );
Martyn Gilbertson 0:37cdeb4f5b6c 475 ret = update_binary(0, 2, (const uint8_t*)& szc );
Martyn Gilbertson 0:37cdeb4f5b6c 476 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 477 ret = M24SR_SUCCESS;
Martyn Gilbertson 0:37cdeb4f5b6c 478 }
Martyn Gilbertson 0:37cdeb4f5b6c 479
Martyn Gilbertson 0:37cdeb4f5b6c 480 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 481 }
Martyn Gilbertson 0:37cdeb4f5b6c 482
Martyn Gilbertson 0:37cdeb4f5b6c 483
Martyn Gilbertson 0:37cdeb4f5b6c 484 M24SR::status_t M24SR::parse_ndef_header()
Martyn Gilbertson 0:37cdeb4f5b6c 485 {
Martyn Gilbertson 0:37cdeb4f5b6c 486 status_t ret;
Martyn Gilbertson 0:37cdeb4f5b6c 487
Martyn Gilbertson 0:37cdeb4f5b6c 488 // read NDEF header
Martyn Gilbertson 0:37cdeb4f5b6c 489 uint8_t hdr[13];
Martyn Gilbertson 0:37cdeb4f5b6c 490
Martyn Gilbertson 0:37cdeb4f5b6c 491 if ( (ret = read_binary( 0, 12, (uint8_t*) &hdr )) != M24SR_SUCCESS )
Martyn Gilbertson 0:37cdeb4f5b6c 492 {
Martyn Gilbertson 0:37cdeb4f5b6c 493 // printf("Failed to read binary\r\n");
Martyn Gilbertson 0:37cdeb4f5b6c 494 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 495 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 496
Martyn Gilbertson 0:37cdeb4f5b6c 497 /** Get NDEF payload+hdr size from first 16 bits
Martyn Gilbertson 0:37cdeb4f5b6c 498 * Process bytes as they come
Martyn Gilbertson 0:37cdeb4f5b6c 499 */
Martyn Gilbertson 0:37cdeb4f5b6c 500 _ndef_size = ( hdr[0] << 8 | hdr[1] ) + 2; // 2 = the size bytes
Martyn Gilbertson 0:37cdeb4f5b6c 501 _ndef_hdr_size = 2;
Martyn Gilbertson 0:37cdeb4f5b6c 502
Martyn Gilbertson 0:37cdeb4f5b6c 503 if (_ndef_size < 10)
Martyn Gilbertson 0:37cdeb4f5b6c 504 {
Martyn Gilbertson 0:37cdeb4f5b6c 505 _ndef_hdr_size = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 506 _session_open = true;
Martyn Gilbertson 0:37cdeb4f5b6c 507 _ndef_size = 0; // no ndef file set
Martyn Gilbertson 0:37cdeb4f5b6c 508
Martyn Gilbertson 0:37cdeb4f5b6c 509 return M24SR_SUCCESS;
Martyn Gilbertson 0:37cdeb4f5b6c 510
Martyn Gilbertson 0:37cdeb4f5b6c 511 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 512
Martyn Gilbertson 0:37cdeb4f5b6c 513 uint8_t flags = hdr[_ndef_hdr_size++];
Martyn Gilbertson 0:37cdeb4f5b6c 514 uint8_t type_len = hdr[_ndef_hdr_size++];
Martyn Gilbertson 0:37cdeb4f5b6c 515
Martyn Gilbertson 0:37cdeb4f5b6c 516 // make sure it's the correct format (001 = well known)
Martyn Gilbertson 0:37cdeb4f5b6c 517 if ( (ret == M24SR_SUCCESS) && (flags & 0x01) != 0x01)
Martyn Gilbertson 0:37cdeb4f5b6c 518 {
Martyn Gilbertson 0:37cdeb4f5b6c 519 return M24SR_FILE_NOT_FOUND;
Martyn Gilbertson 0:37cdeb4f5b6c 520 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 521
Martyn Gilbertson 0:37cdeb4f5b6c 522 // if short record - Payload Len
Martyn Gilbertson 0:37cdeb4f5b6c 523 if ( (flags & 0x10) )
Martyn Gilbertson 0:37cdeb4f5b6c 524 {
Martyn Gilbertson 0:37cdeb4f5b6c 525 _ndef_hdr_size += 1; // 1 byte for short record
Martyn Gilbertson 0:37cdeb4f5b6c 526 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 527 _ndef_hdr_size += 4; // 4 bytes for long record
Martyn Gilbertson 0:37cdeb4f5b6c 528 }
Martyn Gilbertson 0:37cdeb4f5b6c 529
Martyn Gilbertson 0:37cdeb4f5b6c 530 // IL - ID length field present - ID Length
Martyn Gilbertson 0:37cdeb4f5b6c 531 if ( (flags & 0x08) )
Martyn Gilbertson 0:37cdeb4f5b6c 532 {
Martyn Gilbertson 0:37cdeb4f5b6c 533 _ndef_hdr_size += hdr[_ndef_hdr_size]; // ID length
Martyn Gilbertson 0:37cdeb4f5b6c 534 _ndef_hdr_size ++; // ID length
Martyn Gilbertson 0:37cdeb4f5b6c 535 }
Martyn Gilbertson 0:37cdeb4f5b6c 536
Martyn Gilbertson 0:37cdeb4f5b6c 537 // 0 1 2 3 4 5 6 7 8 9 a b
Martyn Gilbertson 0:37cdeb4f5b6c 538 // 0218 c1 01 00 00 02 11 54 02 75 6e
Martyn Gilbertson 0:37cdeb4f5b6c 539
Martyn Gilbertson 0:37cdeb4f5b6c 540 uint8_t type = hdr[_ndef_hdr_size];
Martyn Gilbertson 0:37cdeb4f5b6c 541 _ndef_hdr_size += type_len;
Martyn Gilbertson 0:37cdeb4f5b6c 542
Martyn Gilbertson 0:37cdeb4f5b6c 543 if (type == 0x54) // type 0x54 (Text) contains language and charset
Martyn Gilbertson 0:37cdeb4f5b6c 544 {
Martyn Gilbertson 0:37cdeb4f5b6c 545 uint8_t lang_len = hdr[_ndef_hdr_size++];
Martyn Gilbertson 0:37cdeb4f5b6c 546 //printf("offset = %u %u Lang=%c%c\r\n", _ndef_hdr_size, lang_len, hdr[_ndef_hdr_size], hdr[_ndef_hdr_size+1]);
Martyn Gilbertson 0:37cdeb4f5b6c 547 _ndef_hdr_size += lang_len;
Martyn Gilbertson 0:37cdeb4f5b6c 548 }
Martyn Gilbertson 0:37cdeb4f5b6c 549
Martyn Gilbertson 0:37cdeb4f5b6c 550 _session_open = true;
Martyn Gilbertson 0:37cdeb4f5b6c 551
Martyn Gilbertson 0:37cdeb4f5b6c 552 } // flags correct
Martyn Gilbertson 0:37cdeb4f5b6c 553
Martyn Gilbertson 0:37cdeb4f5b6c 554 } // header length
Martyn Gilbertson 0:37cdeb4f5b6c 555
Martyn Gilbertson 0:37cdeb4f5b6c 556 } // read binary
Martyn Gilbertson 0:37cdeb4f5b6c 557
Martyn Gilbertson 0:37cdeb4f5b6c 558 //printf("Header: %s\r\n" , mts::Text::bin2hexString((uint8_t*)hdr, _ndef_hdr_size).c_str() );
Martyn Gilbertson 0:37cdeb4f5b6c 559 return ret;
Martyn Gilbertson 0:37cdeb4f5b6c 560 }
Martyn Gilbertson 0:37cdeb4f5b6c 561
Martyn Gilbertson 0:37cdeb4f5b6c 562
Martyn Gilbertson 0:37cdeb4f5b6c 563 M24SR::status_t M24SR::read_binary(uint16_t offset, uint8_t size, uint8_t *buffer)
Martyn Gilbertson 0:37cdeb4f5b6c 564 {
Martyn Gilbertson 0:37cdeb4f5b6c 565 uint16_t length;
Martyn Gilbertson 0:37cdeb4f5b6c 566 status_t status;
Martyn Gilbertson 0:37cdeb4f5b6c 567
Martyn Gilbertson 0:37cdeb4f5b6c 568 if (size > MAX_OPERATION_SIZE)
Martyn Gilbertson 0:37cdeb4f5b6c 569 {
Martyn Gilbertson 0:37cdeb4f5b6c 570 size = MAX_OPERATION_SIZE;
Martyn Gilbertson 0:37cdeb4f5b6c 571 }
Martyn Gilbertson 0:37cdeb4f5b6c 572
Martyn Gilbertson 0:37cdeb4f5b6c 573 C_APDU command(C_APDU_CLA_DEFAULT, C_APDU_READ_BINARY, offset, 0, NULL, size);
Martyn Gilbertson 0:37cdeb4f5b6c 574
Martyn Gilbertson 0:37cdeb4f5b6c 575 build_I_block_command(CMD_MASK_READ_BINARY, &command, 0x00, &length, _packet_data);
Martyn Gilbertson 0:37cdeb4f5b6c 576
Martyn Gilbertson 0:37cdeb4f5b6c 577 if ( _i2c.write(M24SR_DEFAULT_ADDRESS, (const char*) _packet_data, length) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 578 {
Martyn Gilbertson 0:37cdeb4f5b6c 579 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 580 }
Martyn Gilbertson 0:37cdeb4f5b6c 581
Martyn Gilbertson 0:37cdeb4f5b6c 582 status = io_poll_i2c();
Martyn Gilbertson 0:37cdeb4f5b6c 583 if (status == M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 584 {
Martyn Gilbertson 0:37cdeb4f5b6c 585 if ( _i2c.read(M24SR_DEFAULT_ADDRESS, (char*) _packet_data, size + STATUS_RESPONSE_LENGTH ) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 586 {
Martyn Gilbertson 0:37cdeb4f5b6c 587 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 588 }
Martyn Gilbertson 0:37cdeb4f5b6c 589 status = is_correct_crc_residue(_packet_data, size + STATUS_RESPONSE_LENGTH);
Martyn Gilbertson 0:37cdeb4f5b6c 590
Martyn Gilbertson 0:37cdeb4f5b6c 591 memcpy(buffer, &_packet_data[1], size);
Martyn Gilbertson 0:37cdeb4f5b6c 592
Martyn Gilbertson 0:37cdeb4f5b6c 593 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 594 }
Martyn Gilbertson 0:37cdeb4f5b6c 595 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 596 }
Martyn Gilbertson 0:37cdeb4f5b6c 597
Martyn Gilbertson 0:37cdeb4f5b6c 598
Martyn Gilbertson 0:37cdeb4f5b6c 599 M24SR::status_t M24SR::update_binary(uint16_t offset, uint8_t size, const uint8_t *buffer)
Martyn Gilbertson 0:37cdeb4f5b6c 600 {
Martyn Gilbertson 0:37cdeb4f5b6c 601 status_t status;
Martyn Gilbertson 0:37cdeb4f5b6c 602 uint16_t length;
Martyn Gilbertson 0:37cdeb4f5b6c 603
Martyn Gilbertson 0:37cdeb4f5b6c 604 if (size > MAX_OPERATION_SIZE)
Martyn Gilbertson 0:37cdeb4f5b6c 605 {
Martyn Gilbertson 0:37cdeb4f5b6c 606 size = MAX_OPERATION_SIZE;
Martyn Gilbertson 0:37cdeb4f5b6c 607 }
Martyn Gilbertson 0:37cdeb4f5b6c 608
Martyn Gilbertson 0:37cdeb4f5b6c 609 C_APDU command(C_APDU_CLA_DEFAULT, C_APDU_UPDATE_BINARY, offset, size, buffer, 0);
Martyn Gilbertson 0:37cdeb4f5b6c 610
Martyn Gilbertson 0:37cdeb4f5b6c 611 build_I_block_command(CMD_MASK_UPDATE_BINARY, &command, 0x00, &length, _packet_data);
Martyn Gilbertson 0:37cdeb4f5b6c 612
Martyn Gilbertson 0:37cdeb4f5b6c 613 if ( _i2c.write(M24SR_DEFAULT_ADDRESS, (const char*) _packet_data, length) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 614 {
Martyn Gilbertson 0:37cdeb4f5b6c 615 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 616 }
Martyn Gilbertson 0:37cdeb4f5b6c 617
Martyn Gilbertson 0:37cdeb4f5b6c 618 status = io_poll_i2c();
Martyn Gilbertson 0:37cdeb4f5b6c 619 if (status == M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 620 {
Martyn Gilbertson 0:37cdeb4f5b6c 621 if ( _i2c.read(M24SR_DEFAULT_ADDRESS, (char*) _packet_data, STATUS_RESPONSE_LENGTH ) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 622 {
Martyn Gilbertson 0:37cdeb4f5b6c 623 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 624 }
Martyn Gilbertson 0:37cdeb4f5b6c 625
Martyn Gilbertson 0:37cdeb4f5b6c 626 if ( is_S_block(_packet_data) == M24SR_SUCCESS )
Martyn Gilbertson 0:37cdeb4f5b6c 627 {
Martyn Gilbertson 0:37cdeb4f5b6c 628 /* check the CRC */
Martyn Gilbertson 0:37cdeb4f5b6c 629 status = is_correct_crc_residue(_packet_data, WATING_TIME_EXT_RESPONSE_LENGTH);
Martyn Gilbertson 0:37cdeb4f5b6c 630 if (status != M24SR_IO_ERROR_CRC)
Martyn Gilbertson 0:37cdeb4f5b6c 631 {
Martyn Gilbertson 0:37cdeb4f5b6c 632 /* send the FrameExension response*/
Martyn Gilbertson 0:37cdeb4f5b6c 633 status = send_fwt_extension(_packet_data[OFFSET_PCB + 1]);
Martyn Gilbertson 0:37cdeb4f5b6c 634 }
Martyn Gilbertson 0:37cdeb4f5b6c 635 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 636 status = is_correct_crc_residue(_packet_data, STATUS_RESPONSE_LENGTH);
Martyn Gilbertson 0:37cdeb4f5b6c 637 }
Martyn Gilbertson 0:37cdeb4f5b6c 638 }
Martyn Gilbertson 0:37cdeb4f5b6c 639
Martyn Gilbertson 0:37cdeb4f5b6c 640 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 641 }
Martyn Gilbertson 0:37cdeb4f5b6c 642
Martyn Gilbertson 0:37cdeb4f5b6c 643
Martyn Gilbertson 0:37cdeb4f5b6c 644 M24SR::status_t M24SR::select_type(uint8_t *cmd, uint8_t size, uint16_t P1_P2, uint16_t mask)
Martyn Gilbertson 0:37cdeb4f5b6c 645 {
Martyn Gilbertson 0:37cdeb4f5b6c 646 status_t status;
Martyn Gilbertson 0:37cdeb4f5b6c 647 uint16_t length;
Martyn Gilbertson 0:37cdeb4f5b6c 648
Martyn Gilbertson 0:37cdeb4f5b6c 649 C_APDU command(C_APDU_CLA_DEFAULT, C_APDU_SELECT_FILE, P1_P2, size, cmd, 0);
Martyn Gilbertson 0:37cdeb4f5b6c 650
Martyn Gilbertson 0:37cdeb4f5b6c 651 /* build the I2C command */
Martyn Gilbertson 0:37cdeb4f5b6c 652 build_I_block_command(mask, &command, 0x00, &length, _packet_data);
Martyn Gilbertson 0:37cdeb4f5b6c 653
Martyn Gilbertson 0:37cdeb4f5b6c 654 if ( _i2c.write(M24SR_DEFAULT_ADDRESS, (const char*) _packet_data, length) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 655 {
Martyn Gilbertson 0:37cdeb4f5b6c 656 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 657 }
Martyn Gilbertson 0:37cdeb4f5b6c 658
Martyn Gilbertson 0:37cdeb4f5b6c 659 status = io_poll_i2c();
Martyn Gilbertson 0:37cdeb4f5b6c 660 if (status == M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 661 {
Martyn Gilbertson 0:37cdeb4f5b6c 662 if ( _i2c.read(M24SR_DEFAULT_ADDRESS, (char*) _packet_data, STATUS_RESPONSE_LENGTH ) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 663 {
Martyn Gilbertson 0:37cdeb4f5b6c 664 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 665 }
Martyn Gilbertson 0:37cdeb4f5b6c 666
Martyn Gilbertson 0:37cdeb4f5b6c 667 status = is_correct_crc_residue(_packet_data, STATUS_RESPONSE_LENGTH);
Martyn Gilbertson 0:37cdeb4f5b6c 668 }
Martyn Gilbertson 0:37cdeb4f5b6c 669
Martyn Gilbertson 0:37cdeb4f5b6c 670 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 671 }
Martyn Gilbertson 0:37cdeb4f5b6c 672
Martyn Gilbertson 0:37cdeb4f5b6c 673
Martyn Gilbertson 0:37cdeb4f5b6c 674 M24SR::status_t M24SR::get_session(bool force)
Martyn Gilbertson 0:37cdeb4f5b6c 675 {
Martyn Gilbertson 0:37cdeb4f5b6c 676 /* special M24SR command */
Martyn Gilbertson 0:37cdeb4f5b6c 677 const uint8_t M24SR_OPENSESSION_COMMAND = 0x26;
Martyn Gilbertson 0:37cdeb4f5b6c 678 const uint8_t M24SR_KILLSESSION_COMMAND = 0x52;
Martyn Gilbertson 0:37cdeb4f5b6c 679
Martyn Gilbertson 0:37cdeb4f5b6c 680 status_t status;
Martyn Gilbertson 0:37cdeb4f5b6c 681
Martyn Gilbertson 0:37cdeb4f5b6c 682 /* Insure no access will be done just after open session */
Martyn Gilbertson 0:37cdeb4f5b6c 683 /* The only way here is to poll I2C to know when M24SR is ready */
Martyn Gilbertson 0:37cdeb4f5b6c 684 /* GPO can not be use with KillSession command */
Martyn Gilbertson 0:37cdeb4f5b6c 685 if ( _i2c.write(M24SR_DEFAULT_ADDRESS, (const char*) & (force == 1 ? M24SR_OPENSESSION_COMMAND : M24SR_KILLSESSION_COMMAND), 1) == 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 686 {
Martyn Gilbertson 0:37cdeb4f5b6c 687 status = io_poll_i2c();
Martyn Gilbertson 0:37cdeb4f5b6c 688 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 689 status = M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 690 }
Martyn Gilbertson 0:37cdeb4f5b6c 691
Martyn Gilbertson 0:37cdeb4f5b6c 692 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 693 }
Martyn Gilbertson 0:37cdeb4f5b6c 694
Martyn Gilbertson 0:37cdeb4f5b6c 695
Martyn Gilbertson 0:37cdeb4f5b6c 696 M24SR::status_t M24SR::send_fwt_extension(uint8_t fwt_byte)
Martyn Gilbertson 0:37cdeb4f5b6c 697 {
Martyn Gilbertson 0:37cdeb4f5b6c 698 status_t status;
Martyn Gilbertson 0:37cdeb4f5b6c 699 uint8_t length = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 700 uint16_t crc16;
Martyn Gilbertson 0:37cdeb4f5b6c 701
Martyn Gilbertson 0:37cdeb4f5b6c 702 /* create the response */
Martyn Gilbertson 0:37cdeb4f5b6c 703 _packet_data[length++] = 0xF2;
Martyn Gilbertson 0:37cdeb4f5b6c 704 _packet_data[length++] = fwt_byte;
Martyn Gilbertson 0:37cdeb4f5b6c 705
Martyn Gilbertson 0:37cdeb4f5b6c 706 /* compute the CRC */
Martyn Gilbertson 0:37cdeb4f5b6c 707 crc16 = compute_crc( _packet_data, 2 );
Martyn Gilbertson 0:37cdeb4f5b6c 708
Martyn Gilbertson 0:37cdeb4f5b6c 709 /* append the CRC16 */
Martyn Gilbertson 0:37cdeb4f5b6c 710 _packet_data[length++] = GETLSB(crc16);
Martyn Gilbertson 0:37cdeb4f5b6c 711 _packet_data[length++] = GETMSB(crc16);
Martyn Gilbertson 0:37cdeb4f5b6c 712
Martyn Gilbertson 0:37cdeb4f5b6c 713 if ( _i2c.write(M24SR_DEFAULT_ADDRESS, (const char*) _packet_data, length) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 714 {
Martyn Gilbertson 0:37cdeb4f5b6c 715 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 716 }
Martyn Gilbertson 0:37cdeb4f5b6c 717
Martyn Gilbertson 0:37cdeb4f5b6c 718 status = io_poll_i2c();
Martyn Gilbertson 0:37cdeb4f5b6c 719 if (status == M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 720 {
Martyn Gilbertson 0:37cdeb4f5b6c 721 if ( _i2c.read(M24SR_DEFAULT_ADDRESS, (char*) _packet_data, STATUS_RESPONSE_LENGTH ) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 722 {
Martyn Gilbertson 0:37cdeb4f5b6c 723 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 724 }
Martyn Gilbertson 0:37cdeb4f5b6c 725
Martyn Gilbertson 0:37cdeb4f5b6c 726 if (is_S_block(_packet_data) == M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 727 {
Martyn Gilbertson 0:37cdeb4f5b6c 728 /* check the CRC */
Martyn Gilbertson 0:37cdeb4f5b6c 729 status = is_correct_crc_residue(_packet_data, WATING_TIME_EXT_RESPONSE_LENGTH);
Martyn Gilbertson 0:37cdeb4f5b6c 730 if (status != M24SR_IO_ERROR_CRC)
Martyn Gilbertson 0:37cdeb4f5b6c 731 {
Martyn Gilbertson 0:37cdeb4f5b6c 732 /* send the FrameExension response */
Martyn Gilbertson 0:37cdeb4f5b6c 733 status = send_fwt_extension(_packet_data[OFFSET_PCB + 1]);
Martyn Gilbertson 0:37cdeb4f5b6c 734 }
Martyn Gilbertson 0:37cdeb4f5b6c 735 } else {
Martyn Gilbertson 0:37cdeb4f5b6c 736 status = is_correct_crc_residue(_packet_data, STATUS_RESPONSE_LENGTH);
Martyn Gilbertson 0:37cdeb4f5b6c 737 }
Martyn Gilbertson 0:37cdeb4f5b6c 738
Martyn Gilbertson 0:37cdeb4f5b6c 739 }
Martyn Gilbertson 0:37cdeb4f5b6c 740 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 741 }
Martyn Gilbertson 0:37cdeb4f5b6c 742
Martyn Gilbertson 0:37cdeb4f5b6c 743
Martyn Gilbertson 0:37cdeb4f5b6c 744 M24SR::status_t M24SR::deselect()
Martyn Gilbertson 0:37cdeb4f5b6c 745 {
Martyn Gilbertson 0:37cdeb4f5b6c 746 uint8_t buffer[] = DESELECT_REQUEST_COMMAND;
Martyn Gilbertson 0:37cdeb4f5b6c 747 status_t status;
Martyn Gilbertson 0:37cdeb4f5b6c 748
Martyn Gilbertson 0:37cdeb4f5b6c 749 if ( _i2c.write(M24SR_DEFAULT_ADDRESS, (const char*) buffer, sizeof(buffer) ) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 750 {
Martyn Gilbertson 0:37cdeb4f5b6c 751 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 752 }
Martyn Gilbertson 0:37cdeb4f5b6c 753
Martyn Gilbertson 0:37cdeb4f5b6c 754 status = io_poll_i2c();
Martyn Gilbertson 0:37cdeb4f5b6c 755 if (status == M24SR_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 756 {
Martyn Gilbertson 0:37cdeb4f5b6c 757 if ( _i2c.read(M24SR_DEFAULT_ADDRESS, (char*) _packet_data, 4 ) != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 758 {
Martyn Gilbertson 0:37cdeb4f5b6c 759 return M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 760 }
Martyn Gilbertson 0:37cdeb4f5b6c 761 }
Martyn Gilbertson 0:37cdeb4f5b6c 762
Martyn Gilbertson 0:37cdeb4f5b6c 763 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 764 }
Martyn Gilbertson 0:37cdeb4f5b6c 765
Martyn Gilbertson 0:37cdeb4f5b6c 766
Martyn Gilbertson 0:37cdeb4f5b6c 767 M24SR::status_t M24SR::is_S_block(uint8_t *buffer)
Martyn Gilbertson 0:37cdeb4f5b6c 768 {
Martyn Gilbertson 0:37cdeb4f5b6c 769 if ((buffer[OFFSET_PCB] & MASK_BLOCK) == MASK_S_BLOCK)
Martyn Gilbertson 0:37cdeb4f5b6c 770 {
Martyn Gilbertson 0:37cdeb4f5b6c 771 return M24SR_SUCCESS;
Martyn Gilbertson 0:37cdeb4f5b6c 772 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 773 return M24SR_ERROR;
Martyn Gilbertson 0:37cdeb4f5b6c 774 }
Martyn Gilbertson 0:37cdeb4f5b6c 775 }
Martyn Gilbertson 0:37cdeb4f5b6c 776
Martyn Gilbertson 0:37cdeb4f5b6c 777
Martyn Gilbertson 0:37cdeb4f5b6c 778 void M24SR::build_I_block_command(uint16_t command_mask, C_APDU *command, uint8_t did, uint16_t *length, uint8_t *command_buffer)
Martyn Gilbertson 0:37cdeb4f5b6c 779 {
Martyn Gilbertson 0:37cdeb4f5b6c 780 uint16_t crc16;
Martyn Gilbertson 0:37cdeb4f5b6c 781 static uint8_t _block_number;
Martyn Gilbertson 0:37cdeb4f5b6c 782
Martyn Gilbertson 0:37cdeb4f5b6c 783 (*length) = 0;
Martyn Gilbertson 0:37cdeb4f5b6c 784
Martyn Gilbertson 0:37cdeb4f5b6c 785 /* add the PCD byte */
Martyn Gilbertson 0:37cdeb4f5b6c 786 if ((command_mask & PCB_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 787 {
Martyn Gilbertson 0:37cdeb4f5b6c 788 /* toggle the block number */
Martyn Gilbertson 0:37cdeb4f5b6c 789 _block_number = !_block_number;
Martyn Gilbertson 0:37cdeb4f5b6c 790 /* Add the I block byte */
Martyn Gilbertson 0:37cdeb4f5b6c 791 command_buffer[(*length)++] = 0x02 | _block_number;
Martyn Gilbertson 0:37cdeb4f5b6c 792 }
Martyn Gilbertson 0:37cdeb4f5b6c 793
Martyn Gilbertson 0:37cdeb4f5b6c 794 /* add the DID byte */
Martyn Gilbertson 0:37cdeb4f5b6c 795 if ((_block_number & DID_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 796 {
Martyn Gilbertson 0:37cdeb4f5b6c 797 /* Add the I block byte */
Martyn Gilbertson 0:37cdeb4f5b6c 798 command_buffer[(*length)++] = did;
Martyn Gilbertson 0:37cdeb4f5b6c 799 }
Martyn Gilbertson 0:37cdeb4f5b6c 800
Martyn Gilbertson 0:37cdeb4f5b6c 801 /* add the Class byte */
Martyn Gilbertson 0:37cdeb4f5b6c 802 if ((command_mask & CLA_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 803 {
Martyn Gilbertson 0:37cdeb4f5b6c 804 command_buffer[(*length)++] = command->header.CLA;
Martyn Gilbertson 0:37cdeb4f5b6c 805 }
Martyn Gilbertson 0:37cdeb4f5b6c 806
Martyn Gilbertson 0:37cdeb4f5b6c 807 /* add the instruction byte byte */
Martyn Gilbertson 0:37cdeb4f5b6c 808 if ((command_mask & INS_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 809 {
Martyn Gilbertson 0:37cdeb4f5b6c 810 command_buffer[(*length)++] = command->header.INS;
Martyn Gilbertson 0:37cdeb4f5b6c 811 }
Martyn Gilbertson 0:37cdeb4f5b6c 812
Martyn Gilbertson 0:37cdeb4f5b6c 813 /* add the Selection Mode byte */
Martyn Gilbertson 0:37cdeb4f5b6c 814 if ((command_mask & P1_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 815 {
Martyn Gilbertson 0:37cdeb4f5b6c 816 command_buffer[(*length)++] = command->header.P1;
Martyn Gilbertson 0:37cdeb4f5b6c 817 }
Martyn Gilbertson 0:37cdeb4f5b6c 818
Martyn Gilbertson 0:37cdeb4f5b6c 819 /* add the Selection Mode byte */
Martyn Gilbertson 0:37cdeb4f5b6c 820 if ((command_mask & P2_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 821 {
Martyn Gilbertson 0:37cdeb4f5b6c 822 command_buffer[(*length)++] = command->header.P2;
Martyn Gilbertson 0:37cdeb4f5b6c 823 }
Martyn Gilbertson 0:37cdeb4f5b6c 824
Martyn Gilbertson 0:37cdeb4f5b6c 825 /* add Data field lengthbyte */
Martyn Gilbertson 0:37cdeb4f5b6c 826 if ((command_mask & LC_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 827 {
Martyn Gilbertson 0:37cdeb4f5b6c 828 command_buffer[(*length)++] = command->body.LC;
Martyn Gilbertson 0:37cdeb4f5b6c 829 }
Martyn Gilbertson 0:37cdeb4f5b6c 830
Martyn Gilbertson 0:37cdeb4f5b6c 831 /* add Data field */
Martyn Gilbertson 0:37cdeb4f5b6c 832 if ((command_mask & DATA_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 833 {
Martyn Gilbertson 0:37cdeb4f5b6c 834 if (command->body.data)
Martyn Gilbertson 0:37cdeb4f5b6c 835 {
Martyn Gilbertson 0:37cdeb4f5b6c 836 memcpy(&(command_buffer[(*length)]), command->body.data, command->body.LC);
Martyn Gilbertson 0:37cdeb4f5b6c 837 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 838 memset(&(command_buffer[(*length)]), 0, command->body.LC);
Martyn Gilbertson 0:37cdeb4f5b6c 839 }
Martyn Gilbertson 0:37cdeb4f5b6c 840 (*length) += command->body.LC;
Martyn Gilbertson 0:37cdeb4f5b6c 841 }
Martyn Gilbertson 0:37cdeb4f5b6c 842
Martyn Gilbertson 0:37cdeb4f5b6c 843 /* add Le field */
Martyn Gilbertson 0:37cdeb4f5b6c 844 if ((command_mask & LE_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 845 {
Martyn Gilbertson 0:37cdeb4f5b6c 846 command_buffer[(*length)++] = command->body.LE;
Martyn Gilbertson 0:37cdeb4f5b6c 847 }
Martyn Gilbertson 0:37cdeb4f5b6c 848
Martyn Gilbertson 0:37cdeb4f5b6c 849 /* add CRC field */
Martyn Gilbertson 0:37cdeb4f5b6c 850 if ((command_mask & CRC_NEEDED) != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 851 {
Martyn Gilbertson 0:37cdeb4f5b6c 852 crc16 = compute_crc(command_buffer, (uint8_t) (*length));
Martyn Gilbertson 0:37cdeb4f5b6c 853 /* append the CRC16 */
Martyn Gilbertson 0:37cdeb4f5b6c 854 command_buffer[(*length)++] = GETLSB(crc16);
Martyn Gilbertson 0:37cdeb4f5b6c 855 command_buffer[(*length)++] = GETMSB(crc16);
Martyn Gilbertson 0:37cdeb4f5b6c 856 }
Martyn Gilbertson 0:37cdeb4f5b6c 857 }
Martyn Gilbertson 0:37cdeb4f5b6c 858
Martyn Gilbertson 0:37cdeb4f5b6c 859
Martyn Gilbertson 0:37cdeb4f5b6c 860 M24SR::status_t M24SR::is_correct_crc_residue(uint8_t *data, uint8_t length)
Martyn Gilbertson 0:37cdeb4f5b6c 861 {
Martyn Gilbertson 0:37cdeb4f5b6c 862 uint16_t res_crc = 0x0000;
Martyn Gilbertson 0:37cdeb4f5b6c 863 status_t status;
Martyn Gilbertson 0:37cdeb4f5b6c 864
Martyn Gilbertson 0:37cdeb4f5b6c 865 /* check the CRC16 Residue */
Martyn Gilbertson 0:37cdeb4f5b6c 866 if (length != 0)
Martyn Gilbertson 0:37cdeb4f5b6c 867 {
Martyn Gilbertson 0:37cdeb4f5b6c 868 res_crc = compute_crc(data, length);
Martyn Gilbertson 0:37cdeb4f5b6c 869 }
Martyn Gilbertson 0:37cdeb4f5b6c 870
Martyn Gilbertson 0:37cdeb4f5b6c 871 if (res_crc == 0x0000)
Martyn Gilbertson 0:37cdeb4f5b6c 872 {
Martyn Gilbertson 0:37cdeb4f5b6c 873 /* Good CRC, but error status from M24SR */
Martyn Gilbertson 0:37cdeb4f5b6c 874 status = (status_t) (((data[length - UB_STATUS_OFFSET] << 8) & 0xFF00) | (data[length - LB_STATUS_OFFSET] & 0x00FF));
Martyn Gilbertson 0:37cdeb4f5b6c 875 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 876 res_crc = 0x0000;
Martyn Gilbertson 0:37cdeb4f5b6c 877 res_crc = compute_crc(data, 5);
Martyn Gilbertson 0:37cdeb4f5b6c 878 if (res_crc != 0x0000)
Martyn Gilbertson 0:37cdeb4f5b6c 879 {
Martyn Gilbertson 0:37cdeb4f5b6c 880 /* Bad CRC */
Martyn Gilbertson 0:37cdeb4f5b6c 881 return M24SR_IO_ERROR_CRC;
Martyn Gilbertson 0:37cdeb4f5b6c 882 }else{
Martyn Gilbertson 0:37cdeb4f5b6c 883 /* Good CRC, but error status from M24SR */
Martyn Gilbertson 0:37cdeb4f5b6c 884 status = (status_t) (((data[1] << 8) & 0xFF00) | (data[2] & 0x00FF));
Martyn Gilbertson 0:37cdeb4f5b6c 885 }
Martyn Gilbertson 0:37cdeb4f5b6c 886 }
Martyn Gilbertson 0:37cdeb4f5b6c 887
Martyn Gilbertson 0:37cdeb4f5b6c 888 if (status == NFC_COMMAND_SUCCESS)
Martyn Gilbertson 0:37cdeb4f5b6c 889 {
Martyn Gilbertson 0:37cdeb4f5b6c 890 status = M24SR_SUCCESS;
Martyn Gilbertson 0:37cdeb4f5b6c 891 }
Martyn Gilbertson 0:37cdeb4f5b6c 892
Martyn Gilbertson 0:37cdeb4f5b6c 893 return status;
Martyn Gilbertson 0:37cdeb4f5b6c 894 }
Martyn Gilbertson 0:37cdeb4f5b6c 895
Martyn Gilbertson 0:37cdeb4f5b6c 896
Martyn Gilbertson 0:37cdeb4f5b6c 897 uint16_t M24SR::compute_crc(uint8_t *data, uint8_t length)
Martyn Gilbertson 0:37cdeb4f5b6c 898 {
Martyn Gilbertson 0:37cdeb4f5b6c 899 uint8_t block;
Martyn Gilbertson 0:37cdeb4f5b6c 900 uint16_t crc16 = 0x6363; /* ITU-V.41 */
Martyn Gilbertson 0:37cdeb4f5b6c 901
Martyn Gilbertson 0:37cdeb4f5b6c 902 do {
Martyn Gilbertson 0:37cdeb4f5b6c 903 block = *data++;
Martyn Gilbertson 0:37cdeb4f5b6c 904 update_crc(block, &crc16);
Martyn Gilbertson 0:37cdeb4f5b6c 905 } while (--length);
Martyn Gilbertson 0:37cdeb4f5b6c 906
Martyn Gilbertson 0:37cdeb4f5b6c 907 return crc16;
Martyn Gilbertson 0:37cdeb4f5b6c 908 }
Martyn Gilbertson 0:37cdeb4f5b6c 909
Martyn Gilbertson 0:37cdeb4f5b6c 910
Martyn Gilbertson 0:37cdeb4f5b6c 911 uint16_t M24SR::update_crc(uint8_t ch, uint16_t *lpw_crc)
Martyn Gilbertson 0:37cdeb4f5b6c 912 {
Martyn Gilbertson 0:37cdeb4f5b6c 913 ch = (ch ^ (uint8_t) ((*lpw_crc) & 0x00FF));
Martyn Gilbertson 0:37cdeb4f5b6c 914 ch = (ch ^ (ch << 4));
Martyn Gilbertson 0:37cdeb4f5b6c 915 *lpw_crc = (*lpw_crc >> 8) ^ ((uint16_t) ch << 8) ^ ((uint16_t) ch << 3) ^ ((uint16_t) ch >> 4);
Martyn Gilbertson 0:37cdeb4f5b6c 916
Martyn Gilbertson 0:37cdeb4f5b6c 917 return (*lpw_crc);
Martyn Gilbertson 0:37cdeb4f5b6c 918 }
Martyn Gilbertson 0:37cdeb4f5b6c 919
Martyn Gilbertson 2:de5aea7f83cd 920
Martyn Gilbertson 0:37cdeb4f5b6c 921 M24SR::status_t M24SR::io_poll_i2c()
Martyn Gilbertson 0:37cdeb4f5b6c 922 {
Martyn Gilbertson 0:37cdeb4f5b6c 923 /* Make sure we don't block forever */
Martyn Gilbertson 1:e356ce0033e4 924 int8_t ctr = 100;
Martyn Gilbertson 0:37cdeb4f5b6c 925 int status = 1;
Martyn Gilbertson 0:37cdeb4f5b6c 926
Martyn Gilbertson 0:37cdeb4f5b6c 927 while ( status != 0 && ctr != 0 )
Martyn Gilbertson 0:37cdeb4f5b6c 928 {
Martyn Gilbertson 0:37cdeb4f5b6c 929 /* send the device address and wait to receive an ack bit */
Martyn Gilbertson 0:37cdeb4f5b6c 930 status = _i2c.write(M24SR_DEFAULT_ADDRESS, NULL, 0);
Martyn Gilbertson 0:37cdeb4f5b6c 931 }
Martyn Gilbertson 0:37cdeb4f5b6c 932
Martyn Gilbertson 0:37cdeb4f5b6c 933 return (status == 0) ? M24SR_SUCCESS : M24SR_IO_ERROR_I2CTIMEOUT;
Martyn Gilbertson 0:37cdeb4f5b6c 934 }
Martyn Gilbertson 2:de5aea7f83cd 935
Martyn Gilbertson 2:de5aea7f83cd 936