Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
M24SR.cpp@2:de5aea7f83cd, 2019-07-31 (annotated)
- 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?
User | Revision | Line number | New 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 |