• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2011-2014 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains the implementation for ISO 15693 in Reader/Writer
22  *  mode.
23  *
24  ******************************************************************************/
25 #include <string.h>
26 #include "bt_types.h"
27 #include "nfc_target.h"
28 #include "trace_api.h"
29 
30 #include "nfc_api.h"
31 #include "nfc_int.h"
32 #include "rw_api.h"
33 #include "rw_int.h"
34 
35 /* Response timeout     */
36 #define RW_I93_TOUT_RESP 1000
37 /* stay quiet timeout   */
38 #define RW_I93_TOUT_STAY_QUIET 200
39 /* max reading data if read multi block is supported */
40 #define RW_I93_READ_MULTI_BLOCK_SIZE 128
41 /* CC, zero length NDEF, Terminator TLV              */
42 #define RW_I93_FORMAT_DATA_LEN 8
43 /* max getting lock status if get multi block sec is supported */
44 #define RW_I93_GET_MULTI_BLOCK_SEC_SIZE 253
45 
46 /* main state */
47 enum {
48   RW_I93_STATE_NOT_ACTIVATED, /* ISO15693 is not activated            */
49   RW_I93_STATE_IDLE,          /* waiting for upper layer API          */
50   RW_I93_STATE_BUSY,          /* waiting for response from tag        */
51 
52   RW_I93_STATE_DETECT_NDEF,   /* performing NDEF detection precedure  */
53   RW_I93_STATE_READ_NDEF,     /* performing read NDEF procedure       */
54   RW_I93_STATE_UPDATE_NDEF,   /* performing update NDEF procedure     */
55   RW_I93_STATE_FORMAT,        /* performing format procedure          */
56   RW_I93_STATE_SET_READ_ONLY, /* performing set read-only procedure   */
57 
58   RW_I93_STATE_PRESENCE_CHECK /* checking presence of tag             */
59 };
60 
61 /* sub state */
62 enum {
63   RW_I93_SUBSTATE_WAIT_UID,          /* waiting for response of inventory    */
64   RW_I93_SUBSTATE_WAIT_SYS_INFO,     /* waiting for response of get sys info */
65   RW_I93_SUBSTATE_WAIT_CC,           /* waiting for reading CC               */
66   RW_I93_SUBSTATE_SEARCH_NDEF_TLV,   /* searching NDEF TLV                   */
67   RW_I93_SUBSTATE_CHECK_LOCK_STATUS, /* check if any NDEF TLV is locked      */
68 
69   RW_I93_SUBSTATE_RESET_LEN,  /* set length to 0 to update NDEF TLV   */
70   RW_I93_SUBSTATE_WRITE_NDEF, /* writing NDEF and Terminator TLV      */
71   RW_I93_SUBSTATE_UPDATE_LEN, /* set length into NDEF TLV             */
72 
73   RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI, /* reset DSFID and AFI */
74   RW_I93_SUBSTATE_CHECK_READ_ONLY,   /* check if any block is locked         */
75   RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV, /* write CC and empty NDEF/Terminator TLV
76                                         */
77 
78   RW_I93_SUBSTATE_WAIT_UPDATE_CC, /* updating CC as read-only             */
79   RW_I93_SUBSTATE_LOCK_NDEF_TLV,  /* lock blocks of NDEF TLV              */
80   RW_I93_SUBSTATE_WAIT_LOCK_CC    /* lock block of CC                     */
81 };
82 
83 #if (BT_TRACE_VERBOSE == TRUE)
84 static char* rw_i93_get_state_name(uint8_t state);
85 static char* rw_i93_get_sub_state_name(uint8_t sub_state);
86 static char* rw_i93_get_tag_name(uint8_t product_version);
87 #endif
88 
89 static void rw_i93_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
90                               tNFC_CONN* p_data);
91 void rw_i93_handle_error(tNFC_STATUS status);
92 tNFC_STATUS rw_i93_send_cmd_get_sys_info(uint8_t* p_uid, uint8_t extra_flag);
93 
94 /*******************************************************************************
95 **
96 ** Function         rw_i93_get_product_version
97 **
98 ** Description      Get product version from UID
99 **
100 ** Returns          void
101 **
102 *******************************************************************************/
rw_i93_get_product_version(uint8_t * p_uid)103 void rw_i93_get_product_version(uint8_t* p_uid) {
104   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
105 
106   if (!memcmp(p_i93->uid, p_uid, I93_UID_BYTE_LEN)) {
107     return;
108   }
109 
110   RW_TRACE_DEBUG0("rw_i93_get_product_version ()");
111 
112   memcpy(p_i93->uid, p_uid, I93_UID_BYTE_LEN);
113 
114   if (p_uid[1] == I93_UID_IC_MFG_CODE_NXP) {
115     if (p_uid[2] == I93_UID_ICODE_SLI)
116       p_i93->product_version = RW_I93_ICODE_SLI;
117     else if (p_uid[2] == I93_UID_ICODE_SLI_S)
118       p_i93->product_version = RW_I93_ICODE_SLI_S;
119     else if (p_uid[2] == I93_UID_ICODE_SLI_L)
120       p_i93->product_version = RW_I93_ICODE_SLI_L;
121     else
122       p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
123   } else if (p_uid[1] == I93_UID_IC_MFG_CODE_TI) {
124     if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
125         I93_UID_TAG_IT_HF_I_PLUS_INLAY)
126       p_i93->product_version = RW_I93_TAG_IT_HF_I_PLUS_INLAY;
127     else if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
128              I93_UID_TAG_IT_HF_I_PLUS_CHIP)
129       p_i93->product_version = RW_I93_TAG_IT_HF_I_PLUS_CHIP;
130     else if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
131              I93_UID_TAG_IT_HF_I_STD_CHIP_INLAY)
132       p_i93->product_version = RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY;
133     else if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
134              I93_UID_TAG_IT_HF_I_PRO_CHIP_INLAY)
135       p_i93->product_version = RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY;
136     else
137       p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
138   } else if ((p_uid[1] == I93_UID_IC_MFG_CODE_STM) &&
139              (p_i93->info_flags & I93_INFO_FLAG_IC_REF)) {
140     if (p_i93->ic_reference == I93_IC_REF_STM_M24LR04E_R)
141       p_i93->product_version = RW_I93_STM_M24LR04E_R;
142     else if (p_i93->ic_reference == I93_IC_REF_STM_M24LR16E_R)
143       p_i93->product_version = RW_I93_STM_M24LR16E_R;
144     else if (p_i93->ic_reference == I93_IC_REF_STM_M24LR64E_R)
145       p_i93->product_version = RW_I93_STM_M24LR64E_R;
146     else {
147       switch (p_i93->ic_reference & I93_IC_REF_STM_MASK) {
148         case I93_IC_REF_STM_LRI1K:
149           p_i93->product_version = RW_I93_STM_LRI1K;
150           break;
151         case I93_IC_REF_STM_LRI2K:
152           p_i93->product_version = RW_I93_STM_LRI2K;
153           break;
154         case I93_IC_REF_STM_LRIS2K:
155           p_i93->product_version = RW_I93_STM_LRIS2K;
156           break;
157         case I93_IC_REF_STM_LRIS64K:
158           p_i93->product_version = RW_I93_STM_LRIS64K;
159           break;
160         case I93_IC_REF_STM_M24LR64_R:
161           p_i93->product_version = RW_I93_STM_M24LR64_R;
162           break;
163         default:
164           p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
165           break;
166       }
167     }
168   } else {
169     p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
170   }
171 
172 #if (BT_TRACE_VERBOSE == TRUE)
173   RW_TRACE_DEBUG1("product_version = <%s>",
174                   rw_i93_get_tag_name(p_i93->product_version));
175 #else
176   RW_TRACE_DEBUG1("product_version = %d", p_i93->product_version);
177 #endif
178 
179   switch (p_i93->product_version) {
180     case RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY:
181     case RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY:
182       /* these don't support Get System Information Command */
183       /* these support only Inventory, Stay Quiet, Read Single Block, Write
184        * Single Block, Lock Block */
185       p_i93->block_size = I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_BLK_SIZE;
186       p_i93->num_block = I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_NUM_USER_BLK;
187       break;
188     default:
189       break;
190   }
191 }
192 
193 /*******************************************************************************
194 **
195 ** Function         rw_i93_process_sys_info
196 **
197 ** Description      Store system information of tag
198 **
199 ** Returns          FALSE if retrying with protocol extension flag
200 **
201 *******************************************************************************/
rw_i93_process_sys_info(uint8_t * p_data)202 bool rw_i93_process_sys_info(uint8_t* p_data) {
203   uint8_t* p = p_data;
204   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
205   uint8_t uid[I93_UID_BYTE_LEN], *p_uid;
206 
207   RW_TRACE_DEBUG0("rw_i93_process_sys_info ()");
208 
209   STREAM_TO_UINT8(p_i93->info_flags, p);
210 
211   p_uid = uid;
212   STREAM_TO_ARRAY8(p_uid, p);
213 
214   if (p_i93->info_flags & I93_INFO_FLAG_DSFID) {
215     STREAM_TO_UINT8(p_i93->dsfid, p);
216   }
217   if (p_i93->info_flags & I93_INFO_FLAG_AFI) {
218     STREAM_TO_UINT8(p_i93->afi, p);
219   }
220   if (p_i93->info_flags & I93_INFO_FLAG_MEM_SIZE) {
221     if (p_i93->intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
222       STREAM_TO_UINT16(p_i93->num_block, p);
223     } else {
224       STREAM_TO_UINT8(p_i93->num_block, p);
225     }
226     /* it is one less than actual number of bytes */
227     p_i93->num_block += 1;
228 
229     STREAM_TO_UINT8(p_i93->block_size, p);
230     /* it is one less than actual number of blocks */
231     p_i93->block_size = (p_i93->block_size & 0x1F) + 1;
232   }
233   if (p_i93->info_flags & I93_INFO_FLAG_IC_REF) {
234     STREAM_TO_UINT8(p_i93->ic_reference, p);
235 
236     /* clear existing UID to set product version */
237     p_i93->uid[0] = 0x00;
238 
239     /* store UID and get product version */
240     rw_i93_get_product_version(p_uid);
241 
242     if (p_i93->uid[0] == I93_UID_FIRST_BYTE) {
243       if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
244           (p_i93->ic_reference == I93_IC_REF_ICODE_SLI_L)) {
245         p_i93->num_block = 8;
246         p_i93->block_size = 4;
247       } else if (p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) {
248         /*
249         **  LRI1K:      010000xx(b), blockSize: 4, numberBlocks: 0x20
250         **  LRI2K:      001000xx(b), blockSize: 4, numberBlocks: 0x40
251         **  LRIS2K:     001010xx(b), blockSize: 4, numberBlocks: 0x40
252         **  LRIS64K:    010001xx(b), blockSize: 4, numberBlocks: 0x800
253         **  M24LR64-R:  001011xx(b), blockSize: 4, numberBlocks: 0x800
254         **  M24LR04E-R: 01011010(b), blockSize: 4, numberBlocks: 0x80
255         **  M24LR16E-R: 01001110(b), blockSize: 4, numberBlocks: 0x200
256         **  M24LR64E-R: 01011110(b), blockSize: 4, numberBlocks: 0x800
257         */
258         if ((p_i93->product_version == RW_I93_STM_M24LR16E_R) ||
259             (p_i93->product_version == RW_I93_STM_M24LR64E_R)) {
260           /*
261           ** M24LR16E-R or M24LR64E-R returns system information
262           ** without memory size, if option flag is not set.
263           ** LRIS64K and M24LR64-R return error if option flag is not
264           ** set.
265           */
266           if (!(p_i93->intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)) {
267             /* get memory size with protocol extension flag */
268             if (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_YES) ==
269                 NFC_STATUS_OK) {
270               /* STM supports more than 2040 bytes */
271               p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
272 
273               return false;
274             }
275           }
276           return true;
277         } else if ((p_i93->product_version == RW_I93_STM_LRI2K) &&
278                    (p_i93->ic_reference == 0x21)) {
279           /* workaround of byte order in memory size information */
280           p_i93->num_block = 64;
281           p_i93->block_size = 4;
282         }
283       }
284     }
285   }
286 
287   return true;
288 }
289 
290 /*******************************************************************************
291 **
292 ** Function         rw_i93_check_sys_info_prot_ext
293 **
294 ** Description      Check if need to set protocol extension flag to get system
295 **                  info
296 **
297 ** Returns          TRUE if sent Get System Info with protocol extension flag
298 **
299 *******************************************************************************/
rw_i93_check_sys_info_prot_ext(uint8_t error_code)300 bool rw_i93_check_sys_info_prot_ext(uint8_t error_code) {
301   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
302 
303   RW_TRACE_DEBUG0("rw_i93_check_sys_info_prot_ext ()");
304 
305   if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) &&
306       (p_i93->sent_cmd == I93_CMD_GET_SYS_INFO) &&
307       (error_code == I93_ERROR_CODE_OPTION_NOT_SUPPORTED) &&
308       (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_YES) ==
309        NFC_STATUS_OK)) {
310     return true;
311   } else {
312     return false;
313   }
314 }
315 
316 /*******************************************************************************
317 **
318 ** Function         rw_i93_send_to_upper
319 **
320 ** Description      Send response to upper layer
321 **
322 ** Returns          void
323 **
324 *******************************************************************************/
rw_i93_send_to_upper(NFC_HDR * p_resp)325 void rw_i93_send_to_upper(NFC_HDR* p_resp) {
326   uint8_t *p = (uint8_t *)(p_resp + 1) + p_resp->offset, *p_uid;
327   uint16_t length = p_resp->len;
328   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
329   tRW_DATA rw_data;
330   uint8_t event = RW_I93_MAX_EVT;
331   uint8_t flags;
332   NFC_HDR* p_buff;
333 
334   RW_TRACE_DEBUG0("rw_i93_send_to_upper ()");
335 
336   STREAM_TO_UINT8(flags, p);
337   length--;
338 
339   if (flags & I93_FLAG_ERROR_DETECTED) {
340     if ((length) && (rw_i93_check_sys_info_prot_ext(*p))) {
341       /* getting system info with protocol extension flag */
342       /* This STM tag supports more than 2040 bytes */
343       p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
344       p_i93->state = RW_I93_STATE_BUSY;
345     } else {
346       /* notify error to upper layer */
347       rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED;
348       rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
349       STREAM_TO_UINT8(rw_data.i93_cmd_cmpl.error_code, p);
350 
351       rw_cb.tcb.i93.sent_cmd = 0;
352       (*(rw_cb.p_cback))(RW_I93_CMD_CMPL_EVT, &rw_data);
353     }
354     return;
355   }
356 
357   switch (p_i93->sent_cmd) {
358     case I93_CMD_INVENTORY:
359 
360       /* forward inventory response */
361       rw_data.i93_inventory.status = NFC_STATUS_OK;
362       STREAM_TO_UINT8(rw_data.i93_inventory.dsfid, p);
363 
364       p_uid = rw_data.i93_inventory.uid;
365       STREAM_TO_ARRAY8(p_uid, p);
366 
367       /* store UID and get product version */
368       rw_i93_get_product_version(p_uid);
369 
370       event = RW_I93_INVENTORY_EVT;
371       break;
372 
373     case I93_CMD_READ_SINGLE_BLOCK:
374     case I93_CMD_READ_MULTI_BLOCK:
375     case I93_CMD_GET_MULTI_BLK_SEC:
376 
377       /* forward tag data or security status */
378       p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE));
379 
380       if (p_buff) {
381         p_buff->offset = 0;
382         p_buff->len = length;
383 
384         memcpy((p_buff + 1), p, length);
385 
386         rw_data.i93_data.status = NFC_STATUS_OK;
387         rw_data.i93_data.command = p_i93->sent_cmd;
388         rw_data.i93_data.p_data = p_buff;
389 
390         event = RW_I93_DATA_EVT;
391       } else {
392         rw_data.i93_cmd_cmpl.status = NFC_STATUS_NO_BUFFERS;
393         rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
394         rw_data.i93_cmd_cmpl.error_code = 0;
395 
396         event = RW_I93_CMD_CMPL_EVT;
397       }
398       break;
399 
400     case I93_CMD_WRITE_SINGLE_BLOCK:
401     case I93_CMD_LOCK_BLOCK:
402     case I93_CMD_WRITE_MULTI_BLOCK:
403     case I93_CMD_SELECT:
404     case I93_CMD_RESET_TO_READY:
405     case I93_CMD_WRITE_AFI:
406     case I93_CMD_LOCK_AFI:
407     case I93_CMD_WRITE_DSFID:
408     case I93_CMD_LOCK_DSFID:
409 
410       /* notify the complete of command */
411       rw_data.i93_cmd_cmpl.status = NFC_STATUS_OK;
412       rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
413       rw_data.i93_cmd_cmpl.error_code = 0;
414 
415       event = RW_I93_CMD_CMPL_EVT;
416       break;
417 
418     case I93_CMD_GET_SYS_INFO:
419 
420       if (rw_i93_process_sys_info(p)) {
421         rw_data.i93_sys_info.status = NFC_STATUS_OK;
422         rw_data.i93_sys_info.info_flags = p_i93->info_flags;
423         rw_data.i93_sys_info.dsfid = p_i93->dsfid;
424         rw_data.i93_sys_info.afi = p_i93->afi;
425         rw_data.i93_sys_info.num_block = p_i93->num_block;
426         rw_data.i93_sys_info.block_size = p_i93->block_size;
427         rw_data.i93_sys_info.IC_reference = p_i93->ic_reference;
428 
429         memcpy(rw_data.i93_sys_info.uid, p_i93->uid, I93_UID_BYTE_LEN);
430 
431         event = RW_I93_SYS_INFO_EVT;
432       } else {
433         /* retrying with protocol extension flag */
434         p_i93->state = RW_I93_STATE_BUSY;
435         return;
436       }
437       break;
438 
439     default:
440       break;
441   }
442 
443   rw_cb.tcb.i93.sent_cmd = 0;
444   if (event != RW_I93_MAX_EVT) {
445     (*(rw_cb.p_cback))(event, &rw_data);
446   } else {
447     RW_TRACE_ERROR0("rw_i93_send_to_upper (): Invalid response");
448   }
449 }
450 
451 /*******************************************************************************
452 **
453 ** Function         rw_i93_send_to_lower
454 **
455 ** Description      Send Request frame to lower layer
456 **
457 ** Returns          TRUE if success
458 **
459 *******************************************************************************/
rw_i93_send_to_lower(NFC_HDR * p_msg)460 bool rw_i93_send_to_lower(NFC_HDR* p_msg) {
461 #if (BT_TRACE_PROTOCOL == TRUE)
462   DispRWI93Tag(p_msg, false, 0x00);
463 #endif
464 
465   /* store command for retransmitting */
466   if (rw_cb.tcb.i93.p_retry_cmd) {
467     GKI_freebuf(rw_cb.tcb.i93.p_retry_cmd);
468     rw_cb.tcb.i93.p_retry_cmd = NULL;
469   }
470 
471   rw_cb.tcb.i93.p_retry_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
472 
473   if (rw_cb.tcb.i93.p_retry_cmd) {
474     memcpy(rw_cb.tcb.i93.p_retry_cmd, p_msg,
475            sizeof(NFC_HDR) + p_msg->offset + p_msg->len);
476   }
477 
478   if (NFC_SendData(NFC_RF_CONN_ID, p_msg) != NFC_STATUS_OK) {
479     RW_TRACE_ERROR0("rw_i93_send_to_lower (): NFC_SendData () failed");
480     return false;
481   }
482 
483   nfc_start_quick_timer(&rw_cb.tcb.i93.timer, NFC_TTYPE_RW_I93_RESPONSE,
484                         (RW_I93_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
485 
486   return true;
487 }
488 
489 /*******************************************************************************
490 **
491 ** Function         rw_i93_send_cmd_inventory
492 **
493 ** Description      Send Inventory Request to VICC
494 **
495 ** Returns          tNFC_STATUS
496 **
497 *******************************************************************************/
rw_i93_send_cmd_inventory(uint8_t * p_uid,bool including_afi,uint8_t afi)498 tNFC_STATUS rw_i93_send_cmd_inventory(uint8_t* p_uid, bool including_afi,
499                                       uint8_t afi) {
500   NFC_HDR* p_cmd;
501   uint8_t *p, flags;
502 
503   RW_TRACE_DEBUG2("rw_i93_send_cmd_inventory () including_afi:%d, AFI:0x%02X",
504                   including_afi, afi);
505 
506   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
507 
508   if (!p_cmd) {
509     RW_TRACE_ERROR0("rw_i93_send_cmd_inventory (): Cannot allocate buffer");
510     return NFC_STATUS_NO_BUFFERS;
511   }
512 
513   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
514   p_cmd->len = 3;
515   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
516 
517   /* Flags */
518   flags = (I93_FLAG_SLOT_ONE | I93_FLAG_INVENTORY_SET |
519            RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
520   if (including_afi) {
521     flags |= I93_FLAG_AFI_PRESENT;
522   }
523 
524   UINT8_TO_STREAM(p, flags);
525 
526   /* Command Code */
527   UINT8_TO_STREAM(p, I93_CMD_INVENTORY);
528 
529   if (including_afi) {
530     /* Parameters */
531     UINT8_TO_STREAM(p, afi); /* Optional AFI */
532     p_cmd->len++;
533   }
534 
535   if (p_uid) {
536     UINT8_TO_STREAM(p, I93_UID_BYTE_LEN * 8); /* Mask Length */
537     ARRAY8_TO_STREAM(p, p_uid);               /* UID */
538     p_cmd->len += I93_UID_BYTE_LEN;
539   } else {
540     UINT8_TO_STREAM(p, 0x00); /* Mask Length */
541   }
542 
543   if (rw_i93_send_to_lower(p_cmd)) {
544     rw_cb.tcb.i93.sent_cmd = I93_CMD_INVENTORY;
545     return NFC_STATUS_OK;
546   } else {
547     return NFC_STATUS_FAILED;
548   }
549 }
550 
551 /*******************************************************************************
552 **
553 ** Function         rw_i93_send_cmd_stay_quiet
554 **
555 ** Description      Send Stay Quiet Request to VICC
556 **
557 ** Returns          tNFC_STATUS
558 **
559 *******************************************************************************/
rw_i93_send_cmd_stay_quiet(void)560 tNFC_STATUS rw_i93_send_cmd_stay_quiet(void) {
561   NFC_HDR* p_cmd;
562   uint8_t* p;
563 
564   RW_TRACE_DEBUG0("rw_i93_send_cmd_stay_quiet ()");
565 
566   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
567 
568   if (!p_cmd) {
569     RW_TRACE_ERROR0("rw_i93_send_cmd_stay_quiet (): Cannot allocate buffer");
570     return NFC_STATUS_NO_BUFFERS;
571   }
572 
573   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
574   p_cmd->len = 10;
575   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
576 
577   /* Flags */
578   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
579                       RW_I93_FLAG_DATA_RATE));
580 
581   /* Command Code */
582   UINT8_TO_STREAM(p, I93_CMD_STAY_QUIET);
583 
584   /* Parameters */
585   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
586 
587   if (rw_i93_send_to_lower(p_cmd)) {
588     rw_cb.tcb.i93.sent_cmd = I93_CMD_STAY_QUIET;
589 
590     /* restart timer for stay quiet */
591     nfc_start_quick_timer(
592         &rw_cb.tcb.i93.timer, NFC_TTYPE_RW_I93_RESPONSE,
593         (RW_I93_TOUT_STAY_QUIET * QUICK_TIMER_TICKS_PER_SEC) / 1000);
594     return NFC_STATUS_OK;
595   } else {
596     return NFC_STATUS_FAILED;
597   }
598 }
599 
600 /*******************************************************************************
601 **
602 ** Function         rw_i93_send_cmd_read_single_block
603 **
604 ** Description      Send Read Single Block Request to VICC
605 **
606 ** Returns          tNFC_STATUS
607 **
608 *******************************************************************************/
rw_i93_send_cmd_read_single_block(uint16_t block_number,bool read_security)609 tNFC_STATUS rw_i93_send_cmd_read_single_block(uint16_t block_number,
610                                               bool read_security) {
611   NFC_HDR* p_cmd;
612   uint8_t *p, flags;
613 
614   RW_TRACE_DEBUG0("rw_i93_send_cmd_read_single_block ()");
615 
616   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
617 
618   if (!p_cmd) {
619     RW_TRACE_ERROR0(
620         "rw_i93_send_cmd_read_single_block (): Cannot allocate buffer");
621     return NFC_STATUS_NO_BUFFERS;
622   }
623 
624   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
625   p_cmd->len = 11;
626   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
627 
628   /* Flags */
629   flags =
630       (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
631 
632   if (read_security) flags |= I93_FLAG_OPTION_SET;
633 
634   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
635     flags |= I93_FLAG_PROT_EXT_YES;
636 
637   UINT8_TO_STREAM(p, flags);
638 
639   /* Command Code */
640   UINT8_TO_STREAM(p, I93_CMD_READ_SINGLE_BLOCK);
641 
642   /* Parameters */
643   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
644 
645   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
646     UINT16_TO_STREAM(p, block_number); /* Block number */
647     p_cmd->len++;
648   } else {
649     UINT8_TO_STREAM(p, block_number); /* Block number */
650   }
651 
652   if (rw_i93_send_to_lower(p_cmd)) {
653     rw_cb.tcb.i93.sent_cmd = I93_CMD_READ_SINGLE_BLOCK;
654     return NFC_STATUS_OK;
655   } else {
656     return NFC_STATUS_FAILED;
657   }
658 }
659 
660 /*******************************************************************************
661 **
662 ** Function         rw_i93_send_cmd_write_single_block
663 **
664 ** Description      Send Write Single Block Request to VICC
665 **
666 ** Returns          tNFC_STATUS
667 **
668 *******************************************************************************/
rw_i93_send_cmd_write_single_block(uint16_t block_number,uint8_t * p_data)669 tNFC_STATUS rw_i93_send_cmd_write_single_block(uint16_t block_number,
670                                                uint8_t* p_data) {
671   NFC_HDR* p_cmd;
672   uint8_t *p, flags;
673 
674   RW_TRACE_DEBUG0("rw_i93_send_cmd_write_single_block ()");
675 
676   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
677 
678   if (!p_cmd) {
679     RW_TRACE_ERROR0(
680         "rw_i93_send_cmd_write_single_block (): Cannot allocate buffer");
681     return NFC_STATUS_NO_BUFFERS;
682   }
683 
684   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
685   p_cmd->len = 11 + rw_cb.tcb.i93.block_size;
686   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
687 
688   /* Flags */
689   if ((rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
690       (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
691       (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
692       (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
693     /* Option must be set for TI tag */
694     flags = (I93_FLAG_ADDRESS_SET | I93_FLAG_OPTION_SET |
695              RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
696   } else {
697     flags = (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
698              RW_I93_FLAG_DATA_RATE);
699   }
700 
701   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
702     flags |= I93_FLAG_PROT_EXT_YES;
703 
704   UINT8_TO_STREAM(p, flags);
705 
706   /* Command Code */
707   UINT8_TO_STREAM(p, I93_CMD_WRITE_SINGLE_BLOCK);
708 
709   /* Parameters */
710   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
711 
712   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
713     UINT16_TO_STREAM(p, block_number); /* Block number */
714     p_cmd->len++;
715   } else {
716     UINT8_TO_STREAM(p, block_number); /* Block number */
717   }
718 
719   /* Data */
720   ARRAY_TO_STREAM(p, p_data, rw_cb.tcb.i93.block_size);
721 
722   if (rw_i93_send_to_lower(p_cmd)) {
723     rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_SINGLE_BLOCK;
724     return NFC_STATUS_OK;
725   } else {
726     return NFC_STATUS_FAILED;
727   }
728 }
729 
730 /*******************************************************************************
731 **
732 ** Function         rw_i93_send_cmd_lock_block
733 **
734 ** Description      Send Lock Block Request to VICC
735 **
736 **                  STM LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR64E-R
737 **                  do not support.
738 **
739 ** Returns          tNFC_STATUS
740 **
741 *******************************************************************************/
rw_i93_send_cmd_lock_block(uint8_t block_number)742 tNFC_STATUS rw_i93_send_cmd_lock_block(uint8_t block_number) {
743   NFC_HDR* p_cmd;
744   uint8_t* p;
745 
746   RW_TRACE_DEBUG0("rw_i93_send_cmd_lock_block ()");
747 
748   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
749 
750   if (!p_cmd) {
751     RW_TRACE_ERROR0("rw_i93_send_cmd_lock_block (): Cannot allocate buffer");
752     return NFC_STATUS_NO_BUFFERS;
753   }
754 
755   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
756   p_cmd->len = 11;
757   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
758 
759   /* Flags */
760   if ((rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
761       (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
762       (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
763       (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
764     /* Option must be set for TI tag */
765     UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | I93_FLAG_OPTION_SET |
766                         RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE));
767   } else {
768     UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
769                         RW_I93_FLAG_DATA_RATE));
770   }
771 
772   /* Command Code */
773   UINT8_TO_STREAM(p, I93_CMD_LOCK_BLOCK);
774 
775   /* Parameters */
776   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
777   UINT8_TO_STREAM(p, block_number);       /* Block number */
778 
779   if (rw_i93_send_to_lower(p_cmd)) {
780     rw_cb.tcb.i93.sent_cmd = I93_CMD_LOCK_BLOCK;
781     return NFC_STATUS_OK;
782   } else {
783     return NFC_STATUS_FAILED;
784   }
785 }
786 
787 /*******************************************************************************
788 **
789 ** Function         rw_i93_send_cmd_read_multi_blocks
790 **
791 ** Description      Send Read Multiple Blocks Request to VICC
792 **
793 ** Returns          tNFC_STATUS
794 **
795 *******************************************************************************/
rw_i93_send_cmd_read_multi_blocks(uint16_t first_block_number,uint16_t number_blocks)796 tNFC_STATUS rw_i93_send_cmd_read_multi_blocks(uint16_t first_block_number,
797                                               uint16_t number_blocks) {
798   NFC_HDR* p_cmd;
799   uint8_t *p, flags;
800 
801   RW_TRACE_DEBUG0("rw_i93_send_cmd_read_multi_blocks ()");
802 
803   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
804 
805   if (!p_cmd) {
806     RW_TRACE_ERROR0(
807         "rw_i93_send_cmd_read_multi_blocks (): Cannot allocate buffer");
808     return NFC_STATUS_NO_BUFFERS;
809   }
810 
811   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
812   p_cmd->len = 12;
813   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
814 
815   /* Flags */
816   flags =
817       (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
818 
819   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
820     flags |= I93_FLAG_PROT_EXT_YES;
821 
822   UINT8_TO_STREAM(p, flags);
823 
824   /* Command Code */
825   UINT8_TO_STREAM(p, I93_CMD_READ_MULTI_BLOCK);
826 
827   /* Parameters */
828   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
829 
830   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
831     UINT16_TO_STREAM(p, first_block_number); /* First block number */
832     p_cmd->len++;
833   } else {
834     UINT8_TO_STREAM(p, first_block_number); /* First block number */
835   }
836 
837   UINT8_TO_STREAM(
838       p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
839 
840   if (rw_i93_send_to_lower(p_cmd)) {
841     rw_cb.tcb.i93.sent_cmd = I93_CMD_READ_MULTI_BLOCK;
842     return NFC_STATUS_OK;
843   } else {
844     return NFC_STATUS_FAILED;
845   }
846 }
847 
848 /*******************************************************************************
849 **
850 ** Function         rw_i93_send_cmd_write_multi_blocks
851 **
852 ** Description      Send Write Multiple Blocks Request to VICC
853 **
854 ** Returns          tNFC_STATUS
855 **
856 *******************************************************************************/
rw_i93_send_cmd_write_multi_blocks(uint8_t first_block_number,uint16_t number_blocks,uint8_t * p_data)857 tNFC_STATUS rw_i93_send_cmd_write_multi_blocks(uint8_t first_block_number,
858                                                uint16_t number_blocks,
859                                                uint8_t* p_data) {
860   NFC_HDR* p_cmd;
861   uint8_t* p;
862 
863   RW_TRACE_DEBUG0("rw_i93_send_cmd_write_multi_blocks ()");
864 
865   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
866 
867   if (!p_cmd) {
868     RW_TRACE_ERROR0(
869         "rw_i93_send_cmd_write_multi_blocks (): Cannot allocate buffer");
870     return NFC_STATUS_NO_BUFFERS;
871   }
872 
873   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
874   p_cmd->len = 12 + number_blocks * rw_cb.tcb.i93.block_size;
875   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
876 
877   /* Flags */
878   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
879                       RW_I93_FLAG_DATA_RATE));
880 
881   /* Command Code */
882   UINT8_TO_STREAM(p, I93_CMD_WRITE_MULTI_BLOCK);
883 
884   /* Parameters */
885   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
886   UINT8_TO_STREAM(p, first_block_number); /* First block number */
887   UINT8_TO_STREAM(
888       p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
889 
890   /* Data */
891   ARRAY_TO_STREAM(p, p_data, number_blocks * rw_cb.tcb.i93.block_size);
892 
893   if (rw_i93_send_to_lower(p_cmd)) {
894     rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_MULTI_BLOCK;
895     return NFC_STATUS_OK;
896   } else {
897     return NFC_STATUS_FAILED;
898   }
899 }
900 
901 /*******************************************************************************
902 **
903 ** Function         rw_i93_send_cmd_select
904 **
905 ** Description      Send Select Request to VICC
906 **
907 ** Returns          tNFC_STATUS
908 **
909 *******************************************************************************/
rw_i93_send_cmd_select(uint8_t * p_uid)910 tNFC_STATUS rw_i93_send_cmd_select(uint8_t* p_uid) {
911   NFC_HDR* p_cmd;
912   uint8_t* p;
913 
914   RW_TRACE_DEBUG0("rw_i93_send_cmd_select ()");
915 
916   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
917 
918   if (!p_cmd) {
919     RW_TRACE_ERROR0("rw_i93_send_cmd_select (): Cannot allocate buffer");
920     return NFC_STATUS_NO_BUFFERS;
921   }
922 
923   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
924   p_cmd->len = 10;
925   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
926 
927   /* Flags */
928   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
929                       RW_I93_FLAG_DATA_RATE));
930 
931   /* Command Code */
932   UINT8_TO_STREAM(p, I93_CMD_SELECT);
933 
934   /* Parameters */
935   ARRAY8_TO_STREAM(p, p_uid); /* UID */
936 
937   if (rw_i93_send_to_lower(p_cmd)) {
938     rw_cb.tcb.i93.sent_cmd = I93_CMD_SELECT;
939     return NFC_STATUS_OK;
940   } else {
941     return NFC_STATUS_FAILED;
942   }
943 }
944 
945 /*******************************************************************************
946 **
947 ** Function         rw_i93_send_cmd_reset_to_ready
948 **
949 ** Description      Send Reset to Ready Request to VICC
950 **
951 ** Returns          tNFC_STATUS
952 **
953 *******************************************************************************/
rw_i93_send_cmd_reset_to_ready(void)954 tNFC_STATUS rw_i93_send_cmd_reset_to_ready(void) {
955   NFC_HDR* p_cmd;
956   uint8_t* p;
957 
958   RW_TRACE_DEBUG0("rw_i93_send_cmd_reset_to_ready ()");
959 
960   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
961 
962   if (!p_cmd) {
963     RW_TRACE_ERROR0(
964         "rw_i93_send_cmd_reset_to_ready (): Cannot allocate buffer");
965     return NFC_STATUS_NO_BUFFERS;
966   }
967 
968   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
969   p_cmd->len = 10;
970   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
971 
972   /* Flags */
973   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
974                       RW_I93_FLAG_DATA_RATE));
975 
976   /* Command Code */
977   UINT8_TO_STREAM(p, I93_CMD_RESET_TO_READY);
978 
979   /* Parameters */
980   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
981 
982   if (rw_i93_send_to_lower(p_cmd)) {
983     rw_cb.tcb.i93.sent_cmd = I93_CMD_RESET_TO_READY;
984     return NFC_STATUS_OK;
985   } else {
986     return NFC_STATUS_FAILED;
987   }
988 }
989 
990 /*******************************************************************************
991 **
992 ** Function         rw_i93_send_cmd_write_afi
993 **
994 ** Description      Send Write AFI Request to VICC
995 **
996 ** Returns          tNFC_STATUS
997 **
998 *******************************************************************************/
rw_i93_send_cmd_write_afi(uint8_t afi)999 tNFC_STATUS rw_i93_send_cmd_write_afi(uint8_t afi) {
1000   NFC_HDR* p_cmd;
1001   uint8_t* p;
1002 
1003   RW_TRACE_DEBUG0("rw_i93_send_cmd_write_afi ()");
1004 
1005   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
1006 
1007   if (!p_cmd) {
1008     RW_TRACE_ERROR0("rw_i93_send_cmd_write_afi (): Cannot allocate buffer");
1009     return NFC_STATUS_NO_BUFFERS;
1010   }
1011 
1012   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1013   p_cmd->len = 11;
1014   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
1015 
1016   /* Flags */
1017   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
1018                       RW_I93_FLAG_DATA_RATE));
1019 
1020   /* Command Code */
1021   UINT8_TO_STREAM(p, I93_CMD_WRITE_AFI);
1022 
1023   /* Parameters */
1024   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
1025   UINT8_TO_STREAM(p, afi);                /* AFI */
1026 
1027   if (rw_i93_send_to_lower(p_cmd)) {
1028     rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_AFI;
1029     return NFC_STATUS_OK;
1030   } else {
1031     return NFC_STATUS_FAILED;
1032   }
1033 }
1034 
1035 /*******************************************************************************
1036 **
1037 ** Function         rw_i93_send_cmd_lock_afi
1038 **
1039 ** Description      Send Lock AFI Request to VICC
1040 **
1041 ** Returns          tNFC_STATUS
1042 **
1043 *******************************************************************************/
rw_i93_send_cmd_lock_afi(void)1044 tNFC_STATUS rw_i93_send_cmd_lock_afi(void) {
1045   NFC_HDR* p_cmd;
1046   uint8_t* p;
1047 
1048   RW_TRACE_DEBUG0("rw_i93_send_cmd_lock_afi ()");
1049 
1050   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
1051 
1052   if (!p_cmd) {
1053     RW_TRACE_ERROR0("rw_i93_send_cmd_lock_afi (): Cannot allocate buffer");
1054     return NFC_STATUS_NO_BUFFERS;
1055   }
1056 
1057   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1058   p_cmd->len = 10;
1059   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
1060 
1061   /* Flags */
1062   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
1063                       RW_I93_FLAG_DATA_RATE));
1064 
1065   /* Command Code */
1066   UINT8_TO_STREAM(p, I93_CMD_LOCK_AFI);
1067 
1068   /* Parameters */
1069   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
1070 
1071   if (rw_i93_send_to_lower(p_cmd)) {
1072     rw_cb.tcb.i93.sent_cmd = I93_CMD_LOCK_AFI;
1073     return NFC_STATUS_OK;
1074   } else {
1075     return NFC_STATUS_FAILED;
1076   }
1077 }
1078 
1079 /*******************************************************************************
1080 **
1081 ** Function         rw_i93_send_cmd_write_dsfid
1082 **
1083 ** Description      Send Write DSFID Request to VICC
1084 **
1085 ** Returns          tNFC_STATUS
1086 **
1087 *******************************************************************************/
rw_i93_send_cmd_write_dsfid(uint8_t dsfid)1088 tNFC_STATUS rw_i93_send_cmd_write_dsfid(uint8_t dsfid) {
1089   NFC_HDR* p_cmd;
1090   uint8_t* p;
1091 
1092   RW_TRACE_DEBUG0("rw_i93_send_cmd_write_dsfid ()");
1093 
1094   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
1095 
1096   if (!p_cmd) {
1097     RW_TRACE_ERROR0("rw_i93_send_cmd_write_dsfid (): Cannot allocate buffer");
1098     return NFC_STATUS_NO_BUFFERS;
1099   }
1100 
1101   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1102   p_cmd->len = 11;
1103   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
1104 
1105   /* Flags */
1106   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
1107                       RW_I93_FLAG_DATA_RATE));
1108 
1109   /* Command Code */
1110   UINT8_TO_STREAM(p, I93_CMD_WRITE_DSFID);
1111 
1112   /* Parameters */
1113   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
1114   UINT8_TO_STREAM(p, dsfid);              /* DSFID */
1115 
1116   if (rw_i93_send_to_lower(p_cmd)) {
1117     rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_DSFID;
1118     return NFC_STATUS_OK;
1119   } else {
1120     return NFC_STATUS_FAILED;
1121   }
1122 }
1123 
1124 /*******************************************************************************
1125 **
1126 ** Function         rw_i93_send_cmd_lock_dsfid
1127 **
1128 ** Description      Send Lock DSFID Request to VICC
1129 **
1130 ** Returns          tNFC_STATUS
1131 **
1132 *******************************************************************************/
rw_i93_send_cmd_lock_dsfid(void)1133 tNFC_STATUS rw_i93_send_cmd_lock_dsfid(void) {
1134   NFC_HDR* p_cmd;
1135   uint8_t* p;
1136 
1137   RW_TRACE_DEBUG0("rw_i93_send_cmd_lock_dsfid ()");
1138 
1139   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
1140 
1141   if (!p_cmd) {
1142     RW_TRACE_ERROR0("rw_i93_send_cmd_lock_dsfid (): Cannot allocate buffer");
1143     return NFC_STATUS_NO_BUFFERS;
1144   }
1145 
1146   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1147   p_cmd->len = 10;
1148   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
1149 
1150   /* Flags */
1151   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
1152                       RW_I93_FLAG_DATA_RATE));
1153 
1154   /* Command Code */
1155   UINT8_TO_STREAM(p, I93_CMD_LOCK_DSFID);
1156 
1157   /* Parameters */
1158   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
1159 
1160   if (rw_i93_send_to_lower(p_cmd)) {
1161     rw_cb.tcb.i93.sent_cmd = I93_CMD_LOCK_DSFID;
1162     return NFC_STATUS_OK;
1163   } else {
1164     return NFC_STATUS_FAILED;
1165   }
1166 }
1167 
1168 /*******************************************************************************
1169 **
1170 ** Function         rw_i93_send_cmd_get_sys_info
1171 **
1172 ** Description      Send Get System Information Request to VICC
1173 **
1174 ** Returns          tNFC_STATUS
1175 **
1176 *******************************************************************************/
rw_i93_send_cmd_get_sys_info(uint8_t * p_uid,uint8_t extra_flags)1177 tNFC_STATUS rw_i93_send_cmd_get_sys_info(uint8_t* p_uid, uint8_t extra_flags) {
1178   NFC_HDR* p_cmd;
1179   uint8_t* p;
1180 
1181   RW_TRACE_DEBUG0("rw_i93_send_cmd_get_sys_info ()");
1182 
1183   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
1184 
1185   if (!p_cmd) {
1186     RW_TRACE_ERROR0("rw_i93_send_cmd_get_sys_info (): Cannot allocate buffer");
1187     return NFC_STATUS_NO_BUFFERS;
1188   }
1189 
1190   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1191   p_cmd->len = 10;
1192   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
1193 
1194   /* Flags */
1195   UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
1196                       RW_I93_FLAG_DATA_RATE | extra_flags));
1197 
1198   /* Command Code */
1199   UINT8_TO_STREAM(p, I93_CMD_GET_SYS_INFO);
1200 
1201   /* Parameters */
1202   if (p_uid) {
1203     ARRAY8_TO_STREAM(p, p_uid); /* UID */
1204   } else {
1205     ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
1206   }
1207 
1208   if (rw_i93_send_to_lower(p_cmd)) {
1209     rw_cb.tcb.i93.sent_cmd = I93_CMD_GET_SYS_INFO;
1210     return NFC_STATUS_OK;
1211   } else {
1212     return NFC_STATUS_FAILED;
1213   }
1214 }
1215 
1216 /*******************************************************************************
1217 **
1218 ** Function         rw_i93_send_cmd_get_multi_block_sec
1219 **
1220 ** Description      Send Get Multiple Block Security Status Request to VICC
1221 **
1222 ** Returns          tNFC_STATUS
1223 **
1224 *******************************************************************************/
rw_i93_send_cmd_get_multi_block_sec(uint16_t first_block_number,uint16_t number_blocks)1225 tNFC_STATUS rw_i93_send_cmd_get_multi_block_sec(uint16_t first_block_number,
1226                                                 uint16_t number_blocks) {
1227   NFC_HDR* p_cmd;
1228   uint8_t *p, flags;
1229 
1230   RW_TRACE_DEBUG0("rw_i93_send_cmd_get_multi_block_sec ()");
1231 
1232   p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
1233 
1234   if (!p_cmd) {
1235     RW_TRACE_ERROR0(
1236         "rw_i93_send_cmd_get_multi_block_sec (): Cannot allocate buffer");
1237     return NFC_STATUS_NO_BUFFERS;
1238   }
1239 
1240   p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1241   p_cmd->len = 12;
1242   p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
1243 
1244   /* Flags */
1245   flags =
1246       (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
1247 
1248   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
1249     flags |= I93_FLAG_PROT_EXT_YES;
1250 
1251   UINT8_TO_STREAM(p, flags);
1252 
1253   /* Command Code */
1254   UINT8_TO_STREAM(p, I93_CMD_GET_MULTI_BLK_SEC);
1255 
1256   /* Parameters */
1257   ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
1258 
1259   if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
1260     UINT16_TO_STREAM(p, first_block_number); /* First block number */
1261     UINT16_TO_STREAM(
1262         p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
1263     p_cmd->len += 2;
1264   } else {
1265     UINT8_TO_STREAM(p, first_block_number); /* First block number */
1266     UINT8_TO_STREAM(
1267         p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
1268   }
1269 
1270   if (rw_i93_send_to_lower(p_cmd)) {
1271     rw_cb.tcb.i93.sent_cmd = I93_CMD_GET_MULTI_BLK_SEC;
1272     return NFC_STATUS_OK;
1273   } else {
1274     return NFC_STATUS_FAILED;
1275   }
1276 }
1277 
1278 /*******************************************************************************
1279 **
1280 ** Function         rw_i93_get_next_blocks
1281 **
1282 ** Description      Read as many blocks as possible (up to
1283 **                  RW_I93_READ_MULTI_BLOCK_SIZE)
1284 **
1285 ** Returns          tNFC_STATUS
1286 **
1287 *******************************************************************************/
rw_i93_get_next_blocks(uint16_t offset)1288 tNFC_STATUS rw_i93_get_next_blocks(uint16_t offset) {
1289   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
1290   uint16_t first_block;
1291   uint16_t num_block;
1292 
1293   RW_TRACE_DEBUG0("rw_i93_get_next_blocks ()");
1294 
1295   first_block = offset / p_i93->block_size;
1296 
1297   /* more blocks, more efficent but more error rate */
1298 
1299   if (p_i93->intl_flags & RW_I93_FLAG_READ_MULTI_BLOCK) {
1300     num_block = RW_I93_READ_MULTI_BLOCK_SIZE / p_i93->block_size;
1301 
1302     if (num_block + first_block > p_i93->num_block)
1303       num_block = p_i93->num_block - first_block;
1304 
1305     if (p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) {
1306       /* LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR64E-R requires
1307       ** - The max number of blocks is 32 and they are all located in the
1308       **   same sector.
1309       ** - The sector is 32 blocks of 4 bytes.
1310       */
1311       if ((p_i93->product_version == RW_I93_STM_LRIS64K) ||
1312           (p_i93->product_version == RW_I93_STM_M24LR64_R) ||
1313           (p_i93->product_version == RW_I93_STM_M24LR04E_R) ||
1314           (p_i93->product_version == RW_I93_STM_M24LR16E_R) ||
1315           (p_i93->product_version == RW_I93_STM_M24LR64E_R)) {
1316         if (num_block > I93_STM_MAX_BLOCKS_PER_READ)
1317           num_block = I93_STM_MAX_BLOCKS_PER_READ;
1318 
1319         if ((first_block / I93_STM_BLOCKS_PER_SECTOR) !=
1320             ((first_block + num_block - 1) / I93_STM_BLOCKS_PER_SECTOR)) {
1321           num_block = I93_STM_BLOCKS_PER_SECTOR -
1322                       (first_block % I93_STM_BLOCKS_PER_SECTOR);
1323         }
1324       }
1325     }
1326 
1327     return rw_i93_send_cmd_read_multi_blocks(first_block, num_block);
1328   } else {
1329     return rw_i93_send_cmd_read_single_block(first_block, false);
1330   }
1331 }
1332 
1333 /*******************************************************************************
1334 **
1335 ** Function         rw_i93_get_next_block_sec
1336 **
1337 ** Description      Get as many security of blocks as possible from
1338 **                  p_i93->rw_offset (up to RW_I93_GET_MULTI_BLOCK_SEC_SIZE)
1339 **
1340 ** Returns          tNFC_STATUS
1341 **
1342 *******************************************************************************/
rw_i93_get_next_block_sec(void)1343 tNFC_STATUS rw_i93_get_next_block_sec(void) {
1344   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
1345   uint16_t num_blocks;
1346 
1347   RW_TRACE_DEBUG0("rw_i93_get_next_block_sec ()");
1348 
1349   if (p_i93->num_block <= p_i93->rw_offset) {
1350     RW_TRACE_ERROR2("rw_offset(0x%x) must be less than num_block(0x%x)",
1351                     p_i93->rw_offset, p_i93->num_block);
1352     return NFC_STATUS_FAILED;
1353   }
1354 
1355   num_blocks = p_i93->num_block - p_i93->rw_offset;
1356 
1357   if (num_blocks > RW_I93_GET_MULTI_BLOCK_SEC_SIZE)
1358     num_blocks = RW_I93_GET_MULTI_BLOCK_SEC_SIZE;
1359 
1360   return rw_i93_send_cmd_get_multi_block_sec(p_i93->rw_offset, num_blocks);
1361 }
1362 
1363 /*******************************************************************************
1364 **
1365 ** Function         rw_i93_sm_detect_ndef
1366 **
1367 ** Description      Process NDEF detection procedure
1368 **
1369 **                  1. Get UID if not having yet
1370 **                  2. Get System Info if not having yet
1371 **                  3. Read first block for CC
1372 **                  4. Search NDEF Type and length
1373 **                  5. Get block status to get max NDEF size and read-only
1374 **                     status
1375 **
1376 ** Returns          void
1377 **
1378 *******************************************************************************/
rw_i93_sm_detect_ndef(NFC_HDR * p_resp)1379 void rw_i93_sm_detect_ndef(NFC_HDR* p_resp) {
1380   uint8_t *p = (uint8_t *)(p_resp + 1) + p_resp->offset, *p_uid;
1381   uint8_t flags, u8 = 0, cc[4];
1382   uint16_t length = p_resp->len, xx, block, first_block, last_block, num_blocks;
1383   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
1384   tRW_DATA rw_data;
1385   tNFC_STATUS status = NFC_STATUS_FAILED;
1386 
1387 #if (BT_TRACE_VERBOSE == TRUE)
1388   RW_TRACE_DEBUG2("rw_i93_sm_detect_ndef () sub_state:%s (0x%x)",
1389                   rw_i93_get_sub_state_name(p_i93->sub_state),
1390                   p_i93->sub_state);
1391 #else
1392   RW_TRACE_DEBUG1("rw_i93_sm_detect_ndef () sub_state:0x%x", p_i93->sub_state);
1393 #endif
1394 
1395   STREAM_TO_UINT8(flags, p);
1396   length--;
1397 
1398   if (flags & I93_FLAG_ERROR_DETECTED) {
1399     if ((length) && (rw_i93_check_sys_info_prot_ext(*p))) {
1400       /* getting system info with protocol extension flag */
1401       /* This STM tag supports more than 2040 bytes */
1402       p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
1403     } else {
1404       RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
1405       rw_i93_handle_error(NFC_STATUS_FAILED);
1406     }
1407     return;
1408   }
1409 
1410   switch (p_i93->sub_state) {
1411     case RW_I93_SUBSTATE_WAIT_UID:
1412 
1413       STREAM_TO_UINT8(u8, p); /* DSFID */
1414       p_uid = p_i93->uid;
1415       STREAM_TO_ARRAY8(p_uid, p);
1416 
1417       if (u8 != I93_DFS_UNSUPPORTED) {
1418         /* if Data Storage Format is unknown */
1419         RW_TRACE_DEBUG1("Got unknown DSFID (0x%02x)", u8);
1420         rw_i93_handle_error(NFC_STATUS_FAILED);
1421       } else {
1422         /* get system information to get memory size */
1423         if (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_NO) ==
1424             NFC_STATUS_OK) {
1425           p_i93->sub_state = RW_I93_SUBSTATE_WAIT_SYS_INFO;
1426         } else {
1427           rw_i93_handle_error(NFC_STATUS_FAILED);
1428         }
1429       }
1430       break;
1431 
1432     case RW_I93_SUBSTATE_WAIT_SYS_INFO:
1433 
1434       p_i93->block_size = 0;
1435       p_i93->num_block = 0;
1436 
1437       if (!rw_i93_process_sys_info(p)) {
1438         /* retrying with protocol extension flag */
1439         break;
1440       }
1441 
1442       if ((p_i93->block_size == 0) || (p_i93->num_block == 0)) {
1443         RW_TRACE_DEBUG0("Unable to get tag memory size");
1444         rw_i93_handle_error(status);
1445       } else {
1446         /* read CC in the first block */
1447         if (rw_i93_send_cmd_read_single_block(0x0000, false) == NFC_STATUS_OK) {
1448           p_i93->sub_state = RW_I93_SUBSTATE_WAIT_CC;
1449         } else {
1450           rw_i93_handle_error(NFC_STATUS_FAILED);
1451         }
1452       }
1453       break;
1454 
1455     case RW_I93_SUBSTATE_WAIT_CC:
1456 
1457       /* assume block size is more than 4 */
1458       STREAM_TO_ARRAY(cc, p, 4);
1459 
1460       status = NFC_STATUS_FAILED;
1461 
1462       /*
1463       ** Capability Container (CC)
1464       **
1465       ** CC[0] : magic number (0xE1)
1466       ** CC[1] : Bit 7-6:Major version number
1467       **       : Bit 5-4:Minor version number
1468       **       : Bit 3-2:Read access condition (00b: read access granted
1469       **         without any security)
1470       **       : Bit 1-0:Write access condition (00b: write access granted
1471       **         without any security)
1472       ** CC[2] : Memory size in 8 bytes (Ex. 0x04 is 32 bytes) [STM, set to
1473       **         0xFF if more than 2040bytes]
1474       ** CC[3] : Bit 0:Read multiple blocks is supported [NXP, STM]
1475       **       : Bit 1:Inventory page read is supported [NXP]
1476       **       : Bit 2:More than 2040 bytes are supported [STM]
1477       */
1478 
1479       RW_TRACE_DEBUG4(
1480           "rw_i93_sm_detect_ndef (): cc: 0x%02X 0x%02X 0x%02X 0x%02X", cc[0],
1481           cc[1], cc[2], cc[3]);
1482       RW_TRACE_DEBUG2(
1483           "rw_i93_sm_detect_ndef (): Total blocks:0x%04X, Block size:0x%02X",
1484           p_i93->num_block, p_i93->block_size);
1485 
1486       if ((cc[0] == I93_ICODE_CC_MAGIC_NUMER) &&
1487           ((cc[3] & I93_STM_CC_OVERFLOW_MASK) ||
1488            (cc[2] * 8) == (p_i93->num_block * p_i93->block_size))) {
1489         if ((cc[1] & I93_ICODE_CC_READ_ACCESS_MASK) ==
1490             I93_ICODE_CC_READ_ACCESS_GRANTED) {
1491           if ((cc[1] & I93_ICODE_CC_WRITE_ACCESS_MASK) !=
1492               I93_ICODE_CC_WRITE_ACCESS_GRANTED) {
1493             /* read-only or password required to write */
1494             p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
1495           }
1496           if (cc[3] & I93_ICODE_CC_MBREAD_MASK) {
1497             /* tag supports read multi blocks command */
1498             p_i93->intl_flags |= RW_I93_FLAG_READ_MULTI_BLOCK;
1499           }
1500           status = NFC_STATUS_OK;
1501         }
1502       }
1503 
1504       if (status == NFC_STATUS_OK) {
1505         /* seach NDEF TLV from offset 4 when CC file coded on 4 bytes NFC Forum
1506          */
1507         if (cc[2] != 0)
1508           p_i93->rw_offset = 4;
1509         else
1510           p_i93->rw_offset = 8;
1511 
1512         if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
1513           p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
1514           p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
1515         } else {
1516           rw_i93_handle_error(NFC_STATUS_FAILED);
1517         }
1518       } else {
1519         rw_i93_handle_error(NFC_STATUS_FAILED);
1520       }
1521       break;
1522 
1523     case RW_I93_SUBSTATE_SEARCH_NDEF_TLV:
1524 
1525       /* search TLV within read blocks */
1526       for (xx = 0; xx < length; xx++) {
1527         /* if looking for type */
1528         if (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_TYPE) {
1529           if (*(p + xx) == I93_ICODE_TLV_TYPE_NULL) {
1530             continue;
1531           } else if ((*(p + xx) == I93_ICODE_TLV_TYPE_NDEF) ||
1532                      (*(p + xx) == I93_ICODE_TLV_TYPE_PROP)) {
1533             /* store found type and get length field */
1534             p_i93->tlv_type = *(p + xx);
1535             p_i93->ndef_tlv_start_offset = p_i93->rw_offset + xx;
1536 
1537             p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_1;
1538           } else if (*(p + xx) == I93_ICODE_TLV_TYPE_TERM) {
1539             /* no NDEF TLV found */
1540             p_i93->tlv_type = I93_ICODE_TLV_TYPE_TERM;
1541             break;
1542           } else {
1543             RW_TRACE_DEBUG1("Invalid type: 0x%02x", *(p + xx));
1544             rw_i93_handle_error(NFC_STATUS_FAILED);
1545             return;
1546           }
1547         } else if (p_i93->tlv_detect_state ==
1548                    RW_I93_TLV_DETECT_STATE_LENGTH_1) {
1549           /* if 3 bytes length field */
1550           if (*(p + xx) == 0xFF) {
1551             /* need 2 more bytes for length field */
1552             p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_2;
1553           } else {
1554             p_i93->tlv_length = *(p + xx);
1555             p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_VALUE;
1556 
1557             if (p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
1558               p_i93->ndef_tlv_last_offset =
1559                   p_i93->ndef_tlv_start_offset + 1 + p_i93->tlv_length;
1560               break;
1561             }
1562           }
1563         } else if (p_i93->tlv_detect_state ==
1564                    RW_I93_TLV_DETECT_STATE_LENGTH_2) {
1565           /* the second byte of 3 bytes length field */
1566           p_i93->tlv_length = *(p + xx);
1567           p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_3;
1568         } else if (p_i93->tlv_detect_state ==
1569                    RW_I93_TLV_DETECT_STATE_LENGTH_3) {
1570           /* the last byte of 3 bytes length field */
1571           p_i93->tlv_length = (p_i93->tlv_length << 8) + *(p + xx);
1572           p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_VALUE;
1573 
1574           if (p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
1575             p_i93->ndef_tlv_last_offset =
1576                 p_i93->ndef_tlv_start_offset + 3 + p_i93->tlv_length;
1577             break;
1578           }
1579         } else if (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_VALUE) {
1580           /* this is other than NDEF TLV */
1581           if (p_i93->tlv_length <= length - xx) {
1582             /* skip value field */
1583             xx += (uint8_t)p_i93->tlv_length;
1584             p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
1585           } else {
1586             /* read more data */
1587             p_i93->tlv_length -= (length - xx);
1588             break;
1589           }
1590         }
1591       }
1592 
1593       /* found NDEF TLV and read length field */
1594       if ((p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) &&
1595           (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_VALUE)) {
1596         p_i93->ndef_length = p_i93->tlv_length;
1597 
1598         /* get lock status to see if read-only */
1599         if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
1600             (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
1601             ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
1602              (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
1603           /* these doesn't support GetMultiBlockSecurityStatus */
1604 
1605           p_i93->rw_offset = p_i93->ndef_tlv_start_offset;
1606           first_block = p_i93->ndef_tlv_start_offset / p_i93->block_size;
1607 
1608           /* read block to get lock status */
1609           rw_i93_send_cmd_read_single_block(first_block, true);
1610           p_i93->sub_state = RW_I93_SUBSTATE_CHECK_LOCK_STATUS;
1611         } else {
1612           /* block offset for read-only check */
1613           p_i93->rw_offset = 0;
1614 
1615           if (rw_i93_get_next_block_sec() == NFC_STATUS_OK) {
1616             p_i93->sub_state = RW_I93_SUBSTATE_CHECK_LOCK_STATUS;
1617           } else {
1618             rw_i93_handle_error(NFC_STATUS_FAILED);
1619           }
1620         }
1621       } else {
1622         /* read more data */
1623         p_i93->rw_offset += length;
1624 
1625         if (p_i93->rw_offset >= p_i93->block_size * p_i93->num_block) {
1626           rw_i93_handle_error(NFC_STATUS_FAILED);
1627         } else if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
1628           p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
1629         } else {
1630           rw_i93_handle_error(NFC_STATUS_FAILED);
1631         }
1632       }
1633       break;
1634 
1635     case RW_I93_SUBSTATE_CHECK_LOCK_STATUS:
1636 
1637       if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
1638           (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
1639           ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
1640            (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
1641         /* these doesn't support GetMultiBlockSecurityStatus */
1642 
1643         block = (p_i93->rw_offset / p_i93->block_size);
1644         last_block = (p_i93->ndef_tlv_last_offset / p_i93->block_size);
1645 
1646         if ((*p) & I93_BLOCK_LOCKED) {
1647           if (block <= last_block) {
1648             p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
1649           }
1650         } else {
1651           /* if we need to check more user blocks */
1652           if (block + 1 < p_i93->num_block) {
1653             p_i93->rw_offset += p_i93->block_size;
1654 
1655             /* read block to get lock status */
1656             rw_i93_send_cmd_read_single_block(
1657                 (uint16_t)(p_i93->rw_offset / p_i93->block_size), true);
1658             break;
1659           }
1660         }
1661 
1662         p_i93->max_ndef_length =
1663             p_i93->ndef_length
1664             /* add available bytes including the last block of NDEF TLV */
1665             + (p_i93->block_size * (block - last_block) + 1) -
1666             (p_i93->ndef_tlv_last_offset % p_i93->block_size) - 1;
1667       } else {
1668         if (p_i93->rw_offset == 0) {
1669           p_i93->max_ndef_length =
1670               p_i93->ndef_length
1671               /* add available bytes in the last block of NDEF TLV */
1672               + p_i93->block_size -
1673               (p_i93->ndef_tlv_last_offset % p_i93->block_size) - 1;
1674 
1675           first_block = (p_i93->ndef_tlv_start_offset / p_i93->block_size);
1676         } else {
1677           first_block = 0;
1678         }
1679 
1680         last_block = (p_i93->ndef_tlv_last_offset / p_i93->block_size);
1681         num_blocks = length;
1682 
1683         for (block = first_block; block < num_blocks; block++) {
1684           /* if any block of NDEF TLV is locked */
1685           if ((block + p_i93->rw_offset) <= last_block) {
1686             if (*(p + block) & I93_BLOCK_LOCKED) {
1687               p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
1688               break;
1689             }
1690           } else {
1691             if (*(p + block) & I93_BLOCK_LOCKED) {
1692               /* no more consecutive unlocked block */
1693               break;
1694             } else {
1695               /* add block size if not locked */
1696               p_i93->max_ndef_length += p_i93->block_size;
1697             }
1698           }
1699         }
1700 
1701         /* update next security of block to check */
1702         p_i93->rw_offset += num_blocks;
1703 
1704         /* if need to check more */
1705         if (p_i93->num_block > p_i93->rw_offset) {
1706           if (rw_i93_get_next_block_sec() != NFC_STATUS_OK) {
1707             rw_i93_handle_error(NFC_STATUS_FAILED);
1708           }
1709           break;
1710         }
1711       }
1712 
1713       /* check if need to adjust max NDEF length */
1714       if ((p_i93->ndef_length < 0xFF) && (p_i93->max_ndef_length >= 0xFF)) {
1715         /* 3 bytes length field must be used */
1716         p_i93->max_ndef_length -= 2;
1717       }
1718 
1719       rw_data.ndef.status = NFC_STATUS_OK;
1720       rw_data.ndef.protocol = NFC_PROTOCOL_15693;
1721       rw_data.ndef.flags = 0;
1722       rw_data.ndef.flags |= RW_NDEF_FL_SUPPORTED;
1723       rw_data.ndef.flags |= RW_NDEF_FL_FORMATED;
1724       rw_data.ndef.flags |= RW_NDEF_FL_FORMATABLE;
1725       rw_data.ndef.cur_size = p_i93->ndef_length;
1726 
1727       if (p_i93->intl_flags & RW_I93_FLAG_READ_ONLY) {
1728         rw_data.ndef.flags |= RW_NDEF_FL_READ_ONLY;
1729         rw_data.ndef.max_size = p_i93->ndef_length;
1730       } else {
1731         rw_data.ndef.flags |= RW_NDEF_FL_HARD_LOCKABLE;
1732         rw_data.ndef.max_size = p_i93->max_ndef_length;
1733       }
1734 
1735       p_i93->state = RW_I93_STATE_IDLE;
1736       p_i93->sent_cmd = 0;
1737 
1738       RW_TRACE_DEBUG3("NDEF cur_size(%d),max_size (%d), flags (0x%x)",
1739                       rw_data.ndef.cur_size, rw_data.ndef.max_size,
1740                       rw_data.ndef.flags);
1741 
1742       (*(rw_cb.p_cback))(RW_I93_NDEF_DETECT_EVT, &rw_data);
1743       break;
1744 
1745     default:
1746       break;
1747   }
1748 }
1749 
1750 /*******************************************************************************
1751 **
1752 ** Function         rw_i93_sm_read_ndef
1753 **
1754 ** Description      Process NDEF read procedure
1755 **
1756 ** Returns          void
1757 **
1758 *******************************************************************************/
rw_i93_sm_read_ndef(NFC_HDR * p_resp)1759 void rw_i93_sm_read_ndef(NFC_HDR* p_resp) {
1760   uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
1761   uint8_t flags;
1762   uint16_t offset, length = p_resp->len;
1763   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
1764   tRW_DATA rw_data;
1765 
1766   RW_TRACE_DEBUG0("rw_i93_sm_read_ndef ()");
1767 
1768   STREAM_TO_UINT8(flags, p);
1769   length--;
1770 
1771   if (flags & I93_FLAG_ERROR_DETECTED) {
1772     RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
1773     rw_i93_handle_error(NFC_STATUS_FAILED);
1774     return;
1775   }
1776 
1777   /* if this is the first block */
1778   if (p_i93->rw_length == 0) {
1779     /* get start of NDEF in the first block */
1780     offset = p_i93->ndef_tlv_start_offset % p_i93->block_size;
1781 
1782     if (p_i93->ndef_length < 0xFF) {
1783       offset += 2;
1784     } else {
1785       offset += 4;
1786     }
1787 
1788     /* adjust offset if read more blocks because the first block doesn't have
1789      * NDEF */
1790     offset -= (p_i93->rw_offset - p_i93->ndef_tlv_start_offset);
1791   } else {
1792     offset = 0;
1793   }
1794 
1795   /* if read enough data to skip type and length field for the beginning */
1796   if (offset < length) {
1797     offset++; /* flags */
1798     p_resp->offset += offset;
1799     p_resp->len -= offset;
1800 
1801     rw_data.data.status = NFC_STATUS_OK;
1802     rw_data.data.p_data = p_resp;
1803 
1804     p_i93->rw_length += p_resp->len;
1805   } else {
1806     /* in case of no Ndef data included */
1807     p_resp->len = 0;
1808   }
1809 
1810   /* if read all of NDEF data */
1811   if (p_i93->rw_length >= p_i93->ndef_length) {
1812     /* remove extra btyes in the last block */
1813     p_resp->len -= (p_i93->rw_length - p_i93->ndef_length);
1814 
1815     p_i93->state = RW_I93_STATE_IDLE;
1816     p_i93->sent_cmd = 0;
1817 
1818     RW_TRACE_DEBUG2("NDEF read complete read (%d)/total (%d)", p_resp->len,
1819                     p_i93->ndef_length);
1820 
1821     (*(rw_cb.p_cback))(RW_I93_NDEF_READ_CPLT_EVT, &rw_data);
1822   } else {
1823     RW_TRACE_DEBUG2("NDEF read segment read (%d)/total (%d)", p_resp->len,
1824                     p_i93->ndef_length);
1825 
1826     if (p_resp->len > 0) {
1827       (*(rw_cb.p_cback))(RW_I93_NDEF_READ_EVT, &rw_data);
1828     }
1829 
1830     /* this will make read data from next block */
1831     p_i93->rw_offset += length;
1832 
1833     if (rw_i93_get_next_blocks(p_i93->rw_offset) != NFC_STATUS_OK) {
1834       rw_i93_handle_error(NFC_STATUS_FAILED);
1835     }
1836   }
1837 }
1838 
1839 /*******************************************************************************
1840 **
1841 ** Function         rw_i93_sm_update_ndef
1842 **
1843 ** Description      Process NDEF update procedure
1844 **
1845 **                  1. Set length field to zero
1846 **                  2. Write NDEF and Terminator TLV
1847 **                  3. Set length field to NDEF length
1848 **
1849 ** Returns          void
1850 **
1851 *******************************************************************************/
rw_i93_sm_update_ndef(NFC_HDR * p_resp)1852 void rw_i93_sm_update_ndef(NFC_HDR* p_resp) {
1853   uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
1854   uint8_t flags, xx, length_offset, buff[I93_MAX_BLOCK_LENGH];
1855   uint16_t length = p_resp->len, block_number;
1856   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
1857   tRW_DATA rw_data;
1858 
1859 #if (BT_TRACE_VERBOSE == TRUE)
1860   RW_TRACE_DEBUG2("rw_i93_sm_update_ndef () sub_state:%s (0x%x)",
1861                   rw_i93_get_sub_state_name(p_i93->sub_state),
1862                   p_i93->sub_state);
1863 #else
1864   RW_TRACE_DEBUG1("rw_i93_sm_update_ndef () sub_state:0x%x", p_i93->sub_state);
1865 #endif
1866 
1867   STREAM_TO_UINT8(flags, p);
1868   length--;
1869 
1870   if (flags & I93_FLAG_ERROR_DETECTED) {
1871     if (((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
1872          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
1873          (p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
1874          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) &&
1875         (*p == I93_ERROR_CODE_BLOCK_FAIL_TO_WRITE)) {
1876       /* ignore error */
1877     } else {
1878       RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
1879       rw_i93_handle_error(NFC_STATUS_FAILED);
1880       return;
1881     }
1882   }
1883 
1884   switch (p_i93->sub_state) {
1885     case RW_I93_SUBSTATE_RESET_LEN:
1886 
1887       /* get offset of length field */
1888       length_offset = (p_i93->ndef_tlv_start_offset + 1) % p_i93->block_size;
1889 
1890       /* set length to zero */
1891       *(p + length_offset) = 0x00;
1892 
1893       if (p_i93->ndef_length > 0) {
1894         /* if 3 bytes length field is needed */
1895         if (p_i93->ndef_length >= 0xFF) {
1896           xx = length_offset + 3;
1897         } else {
1898           xx = length_offset + 1;
1899         }
1900 
1901         /* write the first part of NDEF in the same block */
1902         for (; xx < p_i93->block_size; xx++) {
1903           if (p_i93->rw_length < p_i93->ndef_length) {
1904             *(p + xx) = *(p_i93->p_update_data + p_i93->rw_length++);
1905           } else {
1906             *(p + xx) = I93_ICODE_TLV_TYPE_NULL;
1907           }
1908         }
1909       }
1910 
1911       block_number = (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
1912 
1913       if (rw_i93_send_cmd_write_single_block(block_number, p) ==
1914           NFC_STATUS_OK) {
1915         /* update next writing offset */
1916         p_i93->rw_offset = (block_number + 1) * p_i93->block_size;
1917         p_i93->sub_state = RW_I93_SUBSTATE_WRITE_NDEF;
1918       } else {
1919         rw_i93_handle_error(NFC_STATUS_FAILED);
1920       }
1921       break;
1922 
1923     case RW_I93_SUBSTATE_WRITE_NDEF:
1924 
1925       /* if it's not the end of tag memory */
1926       if (p_i93->rw_offset < p_i93->block_size * p_i93->num_block) {
1927         block_number = p_i93->rw_offset / p_i93->block_size;
1928 
1929         /* if we have more data to write */
1930         if (p_i93->rw_length < p_i93->ndef_length) {
1931           p = p_i93->p_update_data + p_i93->rw_length;
1932 
1933           p_i93->rw_offset += p_i93->block_size;
1934           p_i93->rw_length += p_i93->block_size;
1935 
1936           /* if this is the last block of NDEF TLV */
1937           if (p_i93->rw_length > p_i93->ndef_length) {
1938             /* length of NDEF TLV in the block */
1939             xx = (uint8_t)(p_i93->block_size -
1940                            (p_i93->rw_length - p_i93->ndef_length));
1941 
1942             /* set NULL TLV in the unused part of block */
1943             memset(buff, I93_ICODE_TLV_TYPE_NULL, p_i93->block_size);
1944             memcpy(buff, p, xx);
1945             p = buff;
1946 
1947             /* if it's the end of tag memory */
1948             if ((p_i93->rw_offset >= p_i93->block_size * p_i93->num_block) &&
1949                 (xx < p_i93->block_size)) {
1950               buff[xx] = I93_ICODE_TLV_TYPE_TERM;
1951             }
1952 
1953             p_i93->ndef_tlv_last_offset =
1954                 p_i93->rw_offset - p_i93->block_size + xx - 1;
1955           }
1956 
1957           if (rw_i93_send_cmd_write_single_block(block_number, p) !=
1958               NFC_STATUS_OK) {
1959             rw_i93_handle_error(NFC_STATUS_FAILED);
1960           }
1961         } else {
1962           /* if this is the very next block of NDEF TLV */
1963           if (block_number ==
1964               (p_i93->ndef_tlv_last_offset / p_i93->block_size) + 1) {
1965             p_i93->rw_offset += p_i93->block_size;
1966 
1967             /* write Terminator TLV and NULL TLV */
1968             memset(buff, I93_ICODE_TLV_TYPE_NULL, p_i93->block_size);
1969             buff[0] = I93_ICODE_TLV_TYPE_TERM;
1970             p = buff;
1971 
1972             if (rw_i93_send_cmd_write_single_block(block_number, p) !=
1973                 NFC_STATUS_OK) {
1974               rw_i93_handle_error(NFC_STATUS_FAILED);
1975             }
1976           } else {
1977             /* finished writing NDEF and Terminator TLV */
1978             /* read length field to update length       */
1979             block_number =
1980                 (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
1981 
1982             if (rw_i93_send_cmd_read_single_block(block_number, false) ==
1983                 NFC_STATUS_OK) {
1984               /* set offset to length field */
1985               p_i93->rw_offset = p_i93->ndef_tlv_start_offset + 1;
1986 
1987               /* get size of length field */
1988               if (p_i93->ndef_length >= 0xFF) {
1989                 p_i93->rw_length = 3;
1990               } else if (p_i93->ndef_length > 0) {
1991                 p_i93->rw_length = 1;
1992               } else {
1993                 p_i93->rw_length = 0;
1994               }
1995 
1996               p_i93->sub_state = RW_I93_SUBSTATE_UPDATE_LEN;
1997             } else {
1998               rw_i93_handle_error(NFC_STATUS_FAILED);
1999             }
2000           }
2001         }
2002       } else {
2003         /* if we have no more data to write */
2004         if (p_i93->rw_length >= p_i93->ndef_length) {
2005           /* finished writing NDEF and Terminator TLV */
2006           /* read length field to update length       */
2007           block_number = (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
2008 
2009           if (rw_i93_send_cmd_read_single_block(block_number, false) ==
2010               NFC_STATUS_OK) {
2011             /* set offset to length field */
2012             p_i93->rw_offset = p_i93->ndef_tlv_start_offset + 1;
2013 
2014             /* get size of length field */
2015             if (p_i93->ndef_length >= 0xFF) {
2016               p_i93->rw_length = 3;
2017             } else if (p_i93->ndef_length > 0) {
2018               p_i93->rw_length = 1;
2019             } else {
2020               p_i93->rw_length = 0;
2021             }
2022 
2023             p_i93->sub_state = RW_I93_SUBSTATE_UPDATE_LEN;
2024             break;
2025           }
2026         }
2027         rw_i93_handle_error(NFC_STATUS_FAILED);
2028       }
2029       break;
2030 
2031     case RW_I93_SUBSTATE_UPDATE_LEN:
2032 
2033       /* if we have more length field to write */
2034       if (p_i93->rw_length > 0) {
2035         /* if we got ack for writing, read next block to update rest of length
2036          * field */
2037         if (length == 0) {
2038           block_number = p_i93->rw_offset / p_i93->block_size;
2039 
2040           if (rw_i93_send_cmd_read_single_block(block_number, false) !=
2041               NFC_STATUS_OK) {
2042             rw_i93_handle_error(NFC_STATUS_FAILED);
2043           }
2044         } else {
2045           length_offset = p_i93->rw_offset % p_i93->block_size;
2046 
2047           /* update length field within the read block */
2048           for (xx = length_offset; xx < p_i93->block_size; xx++) {
2049             if (p_i93->rw_length == 3)
2050               *(p + xx) = 0xFF;
2051             else if (p_i93->rw_length == 2)
2052               *(p + xx) = (uint8_t)((p_i93->ndef_length >> 8) & 0xFF);
2053             else if (p_i93->rw_length == 1)
2054               *(p + xx) = (uint8_t)(p_i93->ndef_length & 0xFF);
2055 
2056             p_i93->rw_length--;
2057             if (p_i93->rw_length == 0) break;
2058           }
2059 
2060           block_number = (p_i93->rw_offset / p_i93->block_size);
2061 
2062           if (rw_i93_send_cmd_write_single_block(block_number, p) ==
2063               NFC_STATUS_OK) {
2064             /* set offset to the beginning of next block */
2065             p_i93->rw_offset +=
2066                 p_i93->block_size - (p_i93->rw_offset % p_i93->block_size);
2067           } else {
2068             rw_i93_handle_error(NFC_STATUS_FAILED);
2069           }
2070         }
2071       } else {
2072         RW_TRACE_DEBUG3("NDEF update complete, %d bytes, (%d-%d)",
2073                         p_i93->ndef_length, p_i93->ndef_tlv_start_offset,
2074                         p_i93->ndef_tlv_last_offset);
2075 
2076         p_i93->state = RW_I93_STATE_IDLE;
2077         p_i93->sent_cmd = 0;
2078         p_i93->p_update_data = NULL;
2079 
2080         rw_data.status = NFC_STATUS_OK;
2081         (*(rw_cb.p_cback))(RW_I93_NDEF_UPDATE_CPLT_EVT, &rw_data);
2082       }
2083       break;
2084 
2085     default:
2086       break;
2087   }
2088 }
2089 
2090 /*******************************************************************************
2091 **
2092 ** Function         rw_i93_sm_format
2093 **
2094 ** Description      Process format procedure
2095 **
2096 **                  1. Get UID
2097 **                  2. Get sys info for memory size (reset AFI/DSFID)
2098 **                  3. Get block status to get read-only status
2099 **                  4. Write CC and empty NDEF
2100 **
2101 ** Returns          void
2102 **
2103 *******************************************************************************/
rw_i93_sm_format(NFC_HDR * p_resp)2104 void rw_i93_sm_format(NFC_HDR* p_resp) {
2105   uint8_t *p = (uint8_t *)(p_resp + 1) + p_resp->offset, *p_uid;
2106   uint8_t flags;
2107   uint16_t length = p_resp->len, xx, block_number;
2108   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
2109   tRW_DATA rw_data;
2110   tNFC_STATUS status = NFC_STATUS_FAILED;
2111 
2112 #if (BT_TRACE_VERBOSE == TRUE)
2113   RW_TRACE_DEBUG2("rw_i93_sm_format () sub_state:%s (0x%x)",
2114                   rw_i93_get_sub_state_name(p_i93->sub_state),
2115                   p_i93->sub_state);
2116 #else
2117   RW_TRACE_DEBUG1("rw_i93_sm_format () sub_state:0x%x", p_i93->sub_state);
2118 #endif
2119 
2120   STREAM_TO_UINT8(flags, p);
2121   length--;
2122 
2123   if (flags & I93_FLAG_ERROR_DETECTED) {
2124     if (((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
2125          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
2126          (p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
2127          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) &&
2128         (*p == I93_ERROR_CODE_BLOCK_FAIL_TO_WRITE)) {
2129       /* ignore error */
2130     } else if ((length) && (rw_i93_check_sys_info_prot_ext(*p))) {
2131       /* getting system info with protocol extension flag */
2132       /* This STM tag supports more than 2040 bytes */
2133       p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
2134       return;
2135     } else {
2136       RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
2137       rw_i93_handle_error(NFC_STATUS_FAILED);
2138       return;
2139     }
2140   }
2141 
2142   switch (p_i93->sub_state) {
2143     case RW_I93_SUBSTATE_WAIT_UID:
2144 
2145       p++; /* skip DSFID */
2146       p_uid = p_i93->uid;
2147       STREAM_TO_ARRAY8(p_uid, p); /* store UID */
2148 
2149       /* get system information to get memory size */
2150       if (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_NO) ==
2151           NFC_STATUS_OK) {
2152         p_i93->sub_state = RW_I93_SUBSTATE_WAIT_SYS_INFO;
2153       } else {
2154         rw_i93_handle_error(NFC_STATUS_FAILED);
2155       }
2156       break;
2157 
2158     case RW_I93_SUBSTATE_WAIT_SYS_INFO:
2159 
2160       p_i93->block_size = 0;
2161       p_i93->num_block = 0;
2162 
2163       if (!rw_i93_process_sys_info(p)) {
2164         /* retrying with protocol extension flag */
2165         break;
2166       }
2167 
2168       if (p_i93->info_flags & I93_INFO_FLAG_DSFID) {
2169         /* DSFID, if any DSFID then reset */
2170         if (p_i93->dsfid != I93_DFS_UNSUPPORTED) {
2171           p_i93->intl_flags |= RW_I93_FLAG_RESET_DSFID;
2172         }
2173       }
2174       if (p_i93->info_flags & I93_INFO_FLAG_AFI) {
2175         /* AFI, reset to 0 */
2176         if (p_i93->afi != 0x00) {
2177           p_i93->intl_flags |= RW_I93_FLAG_RESET_AFI;
2178         }
2179       }
2180 
2181       if ((p_i93->block_size == 0) || (p_i93->num_block == 0)) {
2182         RW_TRACE_DEBUG0("Unable to get tag memory size");
2183         rw_i93_handle_error(status);
2184       } else if (p_i93->intl_flags & RW_I93_FLAG_RESET_DSFID) {
2185         if (rw_i93_send_cmd_write_dsfid(I93_DFS_UNSUPPORTED) == NFC_STATUS_OK) {
2186           p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
2187         } else {
2188           rw_i93_handle_error(NFC_STATUS_FAILED);
2189         }
2190       } else if (p_i93->intl_flags & RW_I93_FLAG_RESET_AFI) {
2191         if (rw_i93_send_cmd_write_afi(0x00) == NFC_STATUS_OK) {
2192           p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
2193         } else {
2194           rw_i93_handle_error(NFC_STATUS_FAILED);
2195         }
2196       } else {
2197         /* get lock status to see if read-only */
2198         if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
2199             (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK)) {
2200           /* these doesn't support GetMultiBlockSecurityStatus */
2201 
2202           rw_cb.tcb.i93.rw_offset = 0;
2203 
2204           /* read blocks with option flag to get block security status */
2205           if (rw_i93_send_cmd_read_single_block(0x0000, true) ==
2206               NFC_STATUS_OK) {
2207             p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
2208           } else {
2209             rw_i93_handle_error(NFC_STATUS_FAILED);
2210           }
2211         } else {
2212           /* block offset for read-only check */
2213           p_i93->rw_offset = 0;
2214 
2215           if (rw_i93_get_next_block_sec() == NFC_STATUS_OK) {
2216             p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
2217           } else {
2218             rw_i93_handle_error(NFC_STATUS_FAILED);
2219           }
2220         }
2221       }
2222 
2223       break;
2224 
2225     case RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI:
2226 
2227       if (p_i93->sent_cmd == I93_CMD_WRITE_DSFID) {
2228         p_i93->intl_flags &= ~RW_I93_FLAG_RESET_DSFID;
2229       } else if (p_i93->sent_cmd == I93_CMD_WRITE_AFI) {
2230         p_i93->intl_flags &= ~RW_I93_FLAG_RESET_AFI;
2231       }
2232 
2233       if (p_i93->intl_flags & RW_I93_FLAG_RESET_DSFID) {
2234         if (rw_i93_send_cmd_write_dsfid(I93_DFS_UNSUPPORTED) == NFC_STATUS_OK) {
2235           p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
2236         } else {
2237           rw_i93_handle_error(NFC_STATUS_FAILED);
2238         }
2239       } else if (p_i93->intl_flags & RW_I93_FLAG_RESET_AFI) {
2240         if (rw_i93_send_cmd_write_afi(0x00) == NFC_STATUS_OK) {
2241           p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
2242         } else {
2243           rw_i93_handle_error(NFC_STATUS_FAILED);
2244         }
2245       } else {
2246         /* get lock status to see if read-only */
2247         if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
2248             (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK)) {
2249           /* these doesn't support GetMultiBlockSecurityStatus */
2250 
2251           rw_cb.tcb.i93.rw_offset = 0;
2252 
2253           /* read blocks with option flag to get block security status */
2254           if (rw_i93_send_cmd_read_single_block(0x0000, true) ==
2255               NFC_STATUS_OK) {
2256             p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
2257           } else {
2258             rw_i93_handle_error(NFC_STATUS_FAILED);
2259           }
2260         } else {
2261           /* block offset for read-only check */
2262           p_i93->rw_offset = 0;
2263 
2264           if (rw_i93_get_next_block_sec() == NFC_STATUS_OK) {
2265             p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
2266           } else {
2267             rw_i93_handle_error(NFC_STATUS_FAILED);
2268           }
2269         }
2270       }
2271       break;
2272 
2273     case RW_I93_SUBSTATE_CHECK_READ_ONLY:
2274 
2275       if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
2276           (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
2277           ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
2278            (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
2279         if ((*p) & I93_BLOCK_LOCKED) {
2280           rw_i93_handle_error(NFC_STATUS_FAILED);
2281           break;
2282         }
2283 
2284         /* if we checked all of user blocks */
2285         if ((p_i93->rw_offset / p_i93->block_size) + 1 == p_i93->num_block) {
2286           if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
2287               (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
2288             /* read the block which has AFI */
2289             p_i93->rw_offset = I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_AFI_LOCATION;
2290             rw_i93_send_cmd_read_single_block(
2291                 (uint16_t)(p_i93->rw_offset / p_i93->block_size), true);
2292             break;
2293           }
2294         } else if (p_i93->rw_offset ==
2295                    I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_AFI_LOCATION) {
2296           /* no block is locked */
2297         } else {
2298           p_i93->rw_offset += p_i93->block_size;
2299           rw_i93_send_cmd_read_single_block(
2300               (uint16_t)(p_i93->rw_offset / p_i93->block_size), true);
2301           break;
2302         }
2303       } else {
2304         /* if any block is locked, we cannot format it */
2305         for (xx = 0; xx < length; xx++) {
2306           if (*(p + xx) & I93_BLOCK_LOCKED) {
2307             rw_i93_handle_error(NFC_STATUS_FAILED);
2308             break;
2309           }
2310         }
2311 
2312         /* update block offset for read-only check */
2313         p_i93->rw_offset += length;
2314 
2315         /* if need to get more lock status of blocks */
2316         if (p_i93->num_block > p_i93->rw_offset) {
2317           if (rw_i93_get_next_block_sec() != NFC_STATUS_OK) {
2318             rw_i93_handle_error(NFC_STATUS_FAILED);
2319           }
2320           break;
2321         }
2322       }
2323 
2324       /* get buffer to store CC, zero length NDEF TLV and Terminator TLV */
2325       p_i93->p_update_data = (uint8_t*)GKI_getbuf(RW_I93_FORMAT_DATA_LEN);
2326 
2327       if (!p_i93->p_update_data) {
2328         RW_TRACE_ERROR0("rw_i93_sm_format (): Cannot allocate buffer");
2329         rw_i93_handle_error(NFC_STATUS_FAILED);
2330         break;
2331       }
2332 
2333       p = p_i93->p_update_data;
2334 
2335       /* Capability Container */
2336       *(p++) = I93_ICODE_CC_MAGIC_NUMER; /* magic number */
2337       *(p++) = 0x40;                     /* version 1.0, read/write */
2338 
2339       /* if memory size is less than 2048 bytes */
2340       if (((p_i93->num_block * p_i93->block_size) / 8) < 0x100)
2341         *(p++) = (uint8_t)((p_i93->num_block * p_i93->block_size) /
2342                            8); /* memory size */
2343       else
2344         *(p++) = 0xFF;
2345 
2346       if ((p_i93->product_version == RW_I93_ICODE_SLI) ||
2347           (p_i93->product_version == RW_I93_ICODE_SLI_S) ||
2348           (p_i93->product_version == RW_I93_ICODE_SLI_L)) {
2349         if (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK)
2350           *(p++) = I93_ICODE_CC_IPREAD_MASK; /* IPREAD */
2351         else
2352           *(p++) = I93_ICODE_CC_MBREAD_MASK; /* MBREAD, read multi block command
2353                                                 supported */
2354       } else if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
2355                  (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP)) {
2356         *(p++) = I93_ICODE_CC_MBREAD_MASK; /* MBREAD, read multi block command
2357                                               supported */
2358       } else if ((p_i93->product_version ==
2359                   RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
2360                  (p_i93->product_version ==
2361                   RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
2362         *(p++) = 0;
2363       } else {
2364         /* STM except LRIS2K, Broadcom supports read multi block command */
2365 
2366         /* if memory size is more than 2040 bytes (which is not LRIS2K) */
2367         if (((p_i93->num_block * p_i93->block_size) / 8) > 0xFF)
2368           *(p++) = (I93_ICODE_CC_MBREAD_MASK | I93_STM_CC_OVERFLOW_MASK);
2369         else if (p_i93->product_version == RW_I93_STM_LRIS2K)
2370           *(p++) = 0x00;
2371         else
2372           *(p++) = I93_ICODE_CC_MBREAD_MASK;
2373       }
2374 
2375       /* zero length NDEF and Terminator TLV */
2376       *(p++) = I93_ICODE_TLV_TYPE_NDEF;
2377       *(p++) = 0x00;
2378       *(p++) = I93_ICODE_TLV_TYPE_TERM;
2379       *(p++) = I93_ICODE_TLV_TYPE_NULL;
2380 
2381       /* start from block 0 */
2382       p_i93->rw_offset = 0;
2383 
2384       if (rw_i93_send_cmd_write_single_block(0, p_i93->p_update_data) ==
2385           NFC_STATUS_OK) {
2386         p_i93->sub_state = RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV;
2387         p_i93->rw_offset += p_i93->block_size;
2388       } else {
2389         rw_i93_handle_error(NFC_STATUS_FAILED);
2390       }
2391       break;
2392 
2393     case RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV:
2394 
2395       /* if we have more data to write */
2396       if (p_i93->rw_offset < RW_I93_FORMAT_DATA_LEN) {
2397         block_number = (p_i93->rw_offset / p_i93->block_size);
2398         p = p_i93->p_update_data + p_i93->rw_offset;
2399 
2400         if (rw_i93_send_cmd_write_single_block(block_number, p) ==
2401             NFC_STATUS_OK) {
2402           p_i93->sub_state = RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV;
2403           p_i93->rw_offset += p_i93->block_size;
2404         } else {
2405           rw_i93_handle_error(NFC_STATUS_FAILED);
2406         }
2407       } else {
2408         GKI_freebuf(p_i93->p_update_data);
2409         p_i93->p_update_data = NULL;
2410 
2411         p_i93->state = RW_I93_STATE_IDLE;
2412         p_i93->sent_cmd = 0;
2413 
2414         rw_data.status = NFC_STATUS_OK;
2415         (*(rw_cb.p_cback))(RW_I93_FORMAT_CPLT_EVT, &rw_data);
2416       }
2417       break;
2418 
2419     default:
2420       break;
2421   }
2422 }
2423 
2424 /*******************************************************************************
2425 **
2426 ** Function         rw_i93_sm_set_read_only
2427 **
2428 ** Description      Process read-only procedure
2429 **
2430 **                  1. Update CC as read-only
2431 **                  2. Lock all block of NDEF TLV
2432 **                  3. Lock block of CC
2433 **
2434 ** Returns          void
2435 **
2436 *******************************************************************************/
rw_i93_sm_set_read_only(NFC_HDR * p_resp)2437 void rw_i93_sm_set_read_only(NFC_HDR* p_resp) {
2438   uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
2439   uint8_t flags, block_number;
2440   uint16_t length = p_resp->len;
2441   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
2442   tRW_DATA rw_data;
2443 
2444 #if (BT_TRACE_VERBOSE == TRUE)
2445   RW_TRACE_DEBUG2("rw_i93_sm_set_read_only () sub_state:%s (0x%x)",
2446                   rw_i93_get_sub_state_name(p_i93->sub_state),
2447                   p_i93->sub_state);
2448 #else
2449   RW_TRACE_DEBUG1("rw_i93_sm_set_read_only () sub_state:0x%x",
2450                   p_i93->sub_state);
2451 #endif
2452 
2453   STREAM_TO_UINT8(flags, p);
2454   length--;
2455 
2456   if (flags & I93_FLAG_ERROR_DETECTED) {
2457     if (((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
2458          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
2459          (p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
2460          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) &&
2461         (*p == I93_ERROR_CODE_BLOCK_FAIL_TO_WRITE)) {
2462       /* ignore error */
2463     } else {
2464       RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
2465       rw_i93_handle_error(NFC_STATUS_FAILED);
2466       return;
2467     }
2468   }
2469 
2470   switch (p_i93->sub_state) {
2471     case RW_I93_SUBSTATE_WAIT_CC:
2472 
2473       /* mark CC as read-only */
2474       *(p + 1) |= I93_ICODE_CC_READ_ONLY;
2475 
2476       if (rw_i93_send_cmd_write_single_block(0, p) == NFC_STATUS_OK) {
2477         p_i93->sub_state = RW_I93_SUBSTATE_WAIT_UPDATE_CC;
2478       } else {
2479         rw_i93_handle_error(NFC_STATUS_FAILED);
2480       }
2481       break;
2482 
2483     case RW_I93_SUBSTATE_WAIT_UPDATE_CC:
2484 
2485       /* successfully write CC then lock all blocks of NDEF TLV */
2486       p_i93->rw_offset = p_i93->ndef_tlv_start_offset;
2487       block_number = (uint8_t)(p_i93->rw_offset / p_i93->block_size);
2488 
2489       if (rw_i93_send_cmd_lock_block(block_number) == NFC_STATUS_OK) {
2490         p_i93->rw_offset += p_i93->block_size;
2491         p_i93->sub_state = RW_I93_SUBSTATE_LOCK_NDEF_TLV;
2492       } else {
2493         rw_i93_handle_error(NFC_STATUS_FAILED);
2494       }
2495       break;
2496 
2497     case RW_I93_SUBSTATE_LOCK_NDEF_TLV:
2498 
2499       /* if we need to lock more blocks */
2500       if (p_i93->rw_offset < p_i93->ndef_tlv_last_offset) {
2501         /* get the next block of NDEF TLV */
2502         block_number = (uint8_t)(p_i93->rw_offset / p_i93->block_size);
2503 
2504         if (rw_i93_send_cmd_lock_block(block_number) == NFC_STATUS_OK) {
2505           p_i93->rw_offset += p_i93->block_size;
2506         } else {
2507           rw_i93_handle_error(NFC_STATUS_FAILED);
2508         }
2509       }
2510       /* if the first block of NDEF TLV is different from block of CC */
2511       else if (p_i93->ndef_tlv_start_offset / p_i93->block_size != 0) {
2512         /* lock block of CC */
2513         if (rw_i93_send_cmd_lock_block(0) == NFC_STATUS_OK) {
2514           p_i93->sub_state = RW_I93_SUBSTATE_WAIT_LOCK_CC;
2515         } else {
2516           rw_i93_handle_error(NFC_STATUS_FAILED);
2517         }
2518       } else {
2519         p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
2520         p_i93->state = RW_I93_STATE_IDLE;
2521         p_i93->sent_cmd = 0;
2522 
2523         rw_data.status = NFC_STATUS_OK;
2524         (*(rw_cb.p_cback))(RW_I93_SET_TAG_RO_EVT, &rw_data);
2525       }
2526       break;
2527 
2528     case RW_I93_SUBSTATE_WAIT_LOCK_CC:
2529 
2530       p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
2531       p_i93->state = RW_I93_STATE_IDLE;
2532       p_i93->sent_cmd = 0;
2533 
2534       rw_data.status = NFC_STATUS_OK;
2535       (*(rw_cb.p_cback))(RW_I93_SET_TAG_RO_EVT, &rw_data);
2536       break;
2537 
2538     default:
2539       break;
2540   }
2541 }
2542 
2543 /*******************************************************************************
2544 **
2545 ** Function         rw_i93_handle_error
2546 **
2547 ** Description      notify error to application and clean up
2548 **
2549 ** Returns          none
2550 **
2551 *******************************************************************************/
rw_i93_handle_error(tNFC_STATUS status)2552 void rw_i93_handle_error(tNFC_STATUS status) {
2553   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
2554   tRW_DATA rw_data;
2555   tRW_EVENT event;
2556 
2557   RW_TRACE_DEBUG2("rw_i93_handle_error (): status:0x%02X, state:0x%X", status,
2558                   p_i93->state);
2559 
2560   nfc_stop_quick_timer(&p_i93->timer);
2561 
2562   if (rw_cb.p_cback) {
2563     rw_data.status = status;
2564 
2565     switch (p_i93->state) {
2566       case RW_I93_STATE_IDLE: /* in case of RawFrame */
2567         event = RW_I93_INTF_ERROR_EVT;
2568         break;
2569 
2570       case RW_I93_STATE_BUSY:
2571         if (p_i93->sent_cmd == I93_CMD_STAY_QUIET) {
2572           /* There is no response to Stay Quiet command */
2573           rw_data.i93_cmd_cmpl.status = NFC_STATUS_OK;
2574           rw_data.i93_cmd_cmpl.command = I93_CMD_STAY_QUIET;
2575           rw_data.i93_cmd_cmpl.error_code = 0;
2576           event = RW_I93_CMD_CMPL_EVT;
2577         } else {
2578           event = RW_I93_INTF_ERROR_EVT;
2579         }
2580         break;
2581 
2582       case RW_I93_STATE_DETECT_NDEF:
2583         rw_data.ndef.protocol = NFC_PROTOCOL_15693;
2584         rw_data.ndef.cur_size = 0;
2585         rw_data.ndef.max_size = 0;
2586         rw_data.ndef.flags = 0;
2587         rw_data.ndef.flags |= RW_NDEF_FL_FORMATABLE;
2588         rw_data.ndef.flags |= RW_NDEF_FL_UNKNOWN;
2589         event = RW_I93_NDEF_DETECT_EVT;
2590         break;
2591 
2592       case RW_I93_STATE_READ_NDEF:
2593         event = RW_I93_NDEF_READ_FAIL_EVT;
2594         break;
2595 
2596       case RW_I93_STATE_UPDATE_NDEF:
2597         p_i93->p_update_data = NULL;
2598         event = RW_I93_NDEF_UPDATE_FAIL_EVT;
2599         break;
2600 
2601       case RW_I93_STATE_FORMAT:
2602         if (p_i93->p_update_data) {
2603           GKI_freebuf(p_i93->p_update_data);
2604           p_i93->p_update_data = NULL;
2605         }
2606         event = RW_I93_FORMAT_CPLT_EVT;
2607         break;
2608 
2609       case RW_I93_STATE_SET_READ_ONLY:
2610         event = RW_I93_SET_TAG_RO_EVT;
2611         break;
2612 
2613       case RW_I93_STATE_PRESENCE_CHECK:
2614         event = RW_I93_PRESENCE_CHECK_EVT;
2615         break;
2616 
2617       default:
2618         event = RW_I93_MAX_EVT;
2619         break;
2620     }
2621 
2622     p_i93->state = RW_I93_STATE_IDLE;
2623     p_i93->sent_cmd = 0;
2624 
2625     if (event != RW_I93_MAX_EVT) {
2626       (*(rw_cb.p_cback))(event, &rw_data);
2627     }
2628   } else {
2629     p_i93->state = RW_I93_STATE_IDLE;
2630   }
2631 }
2632 
2633 /*******************************************************************************
2634 **
2635 ** Function         rw_i93_process_timeout
2636 **
2637 ** Description      process timeout event
2638 **
2639 ** Returns          none
2640 **
2641 *******************************************************************************/
rw_i93_process_timeout(TIMER_LIST_ENT * p_tle)2642 void rw_i93_process_timeout(TIMER_LIST_ENT* p_tle) {
2643   NFC_HDR* p_buf;
2644 
2645   RW_TRACE_DEBUG1("rw_i93_process_timeout () event=%d", p_tle->event);
2646 
2647   if (p_tle->event == NFC_TTYPE_RW_I93_RESPONSE) {
2648     if ((rw_cb.tcb.i93.retry_count < RW_MAX_RETRIES) &&
2649         (rw_cb.tcb.i93.p_retry_cmd) &&
2650         (rw_cb.tcb.i93.sent_cmd != I93_CMD_STAY_QUIET)) {
2651       rw_cb.tcb.i93.retry_count++;
2652       RW_TRACE_ERROR1("rw_i93_process_timeout (): retry_count = %d",
2653                       rw_cb.tcb.i93.retry_count);
2654 
2655       p_buf = rw_cb.tcb.i93.p_retry_cmd;
2656       rw_cb.tcb.i93.p_retry_cmd = NULL;
2657 
2658       if (rw_i93_send_to_lower(p_buf)) {
2659         return;
2660       }
2661     }
2662 
2663     /* all retrial is done or failed to send command to lower layer */
2664     if (rw_cb.tcb.i93.p_retry_cmd) {
2665       GKI_freebuf(rw_cb.tcb.i93.p_retry_cmd);
2666       rw_cb.tcb.i93.p_retry_cmd = NULL;
2667       rw_cb.tcb.i93.retry_count = 0;
2668     }
2669     rw_i93_handle_error(NFC_STATUS_TIMEOUT);
2670   } else {
2671     RW_TRACE_ERROR1("rw_i93_process_timeout () unknown event=%d", p_tle->event);
2672   }
2673 }
2674 
2675 /*******************************************************************************
2676 **
2677 ** Function         rw_i93_data_cback
2678 **
2679 ** Description      This callback function receives the data from NFCC.
2680 **
2681 ** Returns          none
2682 **
2683 *******************************************************************************/
rw_i93_data_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)2684 static void rw_i93_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
2685                               tNFC_CONN* p_data) {
2686   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
2687   NFC_HDR* p_resp;
2688   tRW_DATA rw_data;
2689 
2690 #if (BT_TRACE_VERBOSE == TRUE)
2691   uint8_t begin_state = p_i93->state;
2692 #endif
2693 
2694   RW_TRACE_DEBUG1("rw_i93_data_cback () event = 0x%X", event);
2695 
2696   if ((event == NFC_DEACTIVATE_CEVT) || (event == NFC_ERROR_CEVT)) {
2697     nfc_stop_quick_timer(&p_i93->timer);
2698 
2699     if (event == NFC_ERROR_CEVT) {
2700       if ((p_i93->retry_count < RW_MAX_RETRIES) && (p_i93->p_retry_cmd)) {
2701         p_i93->retry_count++;
2702 
2703         RW_TRACE_ERROR1("rw_i93_data_cback (): retry_count = %d",
2704                         p_i93->retry_count);
2705 
2706         p_resp = p_i93->p_retry_cmd;
2707         p_i93->p_retry_cmd = NULL;
2708         if (rw_i93_send_to_lower(p_resp)) {
2709           return;
2710         }
2711       }
2712 
2713       /* all retrial is done or failed to send command to lower layer */
2714       if (p_i93->p_retry_cmd) {
2715         GKI_freebuf(p_i93->p_retry_cmd);
2716         p_i93->p_retry_cmd = NULL;
2717         p_i93->retry_count = 0;
2718       }
2719 
2720       rw_i93_handle_error((tNFC_STATUS)(*(uint8_t*)p_data));
2721     } else {
2722       /* free retry buffer */
2723       if (p_i93->p_retry_cmd) {
2724         GKI_freebuf(p_i93->p_retry_cmd);
2725         p_i93->p_retry_cmd = NULL;
2726         p_i93->retry_count = 0;
2727       }
2728       NFC_SetStaticRfCback(NULL);
2729       p_i93->state = RW_I93_STATE_NOT_ACTIVATED;
2730     }
2731     return;
2732   }
2733 
2734   if (event != NFC_DATA_CEVT) {
2735     return;
2736   }
2737 
2738   p_resp = (NFC_HDR*)p_data->data.p_data;
2739 
2740   nfc_stop_quick_timer(&p_i93->timer);
2741 
2742   /* free retry buffer */
2743   if (p_i93->p_retry_cmd) {
2744     GKI_freebuf(p_i93->p_retry_cmd);
2745     p_i93->p_retry_cmd = NULL;
2746     p_i93->retry_count = 0;
2747   }
2748 
2749 #if (BT_TRACE_PROTOCOL == TRUE)
2750   DispRWI93Tag(p_resp, true, p_i93->sent_cmd);
2751 #endif
2752 
2753 #if (BT_TRACE_VERBOSE == TRUE)
2754   RW_TRACE_DEBUG2("RW I93 state: <%s (%d)>",
2755                   rw_i93_get_state_name(p_i93->state), p_i93->state);
2756 #else
2757   RW_TRACE_DEBUG1("RW I93 state: %d", p_i93->state);
2758 #endif
2759 
2760   switch (p_i93->state) {
2761     case RW_I93_STATE_IDLE:
2762       /* Unexpected Response from VICC, it should be raw frame response */
2763       /* forward to upper layer without parsing */
2764       p_i93->sent_cmd = 0;
2765       if (rw_cb.p_cback) {
2766         rw_data.raw_frame.status = p_data->data.status;
2767         rw_data.raw_frame.p_data = p_resp;
2768         (*(rw_cb.p_cback))(RW_I93_RAW_FRAME_EVT, &rw_data);
2769         p_resp = NULL;
2770       } else {
2771         GKI_freebuf(p_resp);
2772       }
2773       break;
2774     case RW_I93_STATE_BUSY:
2775       p_i93->state = RW_I93_STATE_IDLE;
2776       rw_i93_send_to_upper(p_resp);
2777       GKI_freebuf(p_resp);
2778       break;
2779 
2780     case RW_I93_STATE_DETECT_NDEF:
2781       rw_i93_sm_detect_ndef(p_resp);
2782       GKI_freebuf(p_resp);
2783       break;
2784 
2785     case RW_I93_STATE_READ_NDEF:
2786       rw_i93_sm_read_ndef(p_resp);
2787       /* p_resp may send upper lyaer */
2788       break;
2789 
2790     case RW_I93_STATE_UPDATE_NDEF:
2791       rw_i93_sm_update_ndef(p_resp);
2792       GKI_freebuf(p_resp);
2793       break;
2794 
2795     case RW_I93_STATE_FORMAT:
2796       rw_i93_sm_format(p_resp);
2797       GKI_freebuf(p_resp);
2798       break;
2799 
2800     case RW_I93_STATE_SET_READ_ONLY:
2801       rw_i93_sm_set_read_only(p_resp);
2802       GKI_freebuf(p_resp);
2803       break;
2804 
2805     case RW_I93_STATE_PRESENCE_CHECK:
2806       p_i93->state = RW_I93_STATE_IDLE;
2807       p_i93->sent_cmd = 0;
2808 
2809       /* if any response, send presence check with ok */
2810       rw_data.status = NFC_STATUS_OK;
2811       (*(rw_cb.p_cback))(RW_I93_PRESENCE_CHECK_EVT, &rw_data);
2812       GKI_freebuf(p_resp);
2813       break;
2814 
2815     default:
2816       RW_TRACE_ERROR1("rw_i93_data_cback (): invalid state=%d", p_i93->state);
2817       GKI_freebuf(p_resp);
2818       break;
2819   }
2820 
2821 #if (BT_TRACE_VERBOSE == TRUE)
2822   if (begin_state != p_i93->state) {
2823     RW_TRACE_DEBUG2("RW I93 state changed:<%s> -> <%s>",
2824                     rw_i93_get_state_name(begin_state),
2825                     rw_i93_get_state_name(p_i93->state));
2826   }
2827 #endif
2828 }
2829 
2830 /*******************************************************************************
2831 **
2832 ** Function         rw_i93_select
2833 **
2834 ** Description      Initialise ISO 15693 RW
2835 **
2836 ** Returns          NFC_STATUS_OK if success
2837 **
2838 *******************************************************************************/
rw_i93_select(uint8_t * p_uid)2839 tNFC_STATUS rw_i93_select(uint8_t* p_uid) {
2840   tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
2841   uint8_t uid[I93_UID_BYTE_LEN], *p;
2842 
2843   RW_TRACE_DEBUG0("rw_i93_select ()");
2844 
2845   NFC_SetStaticRfCback(rw_i93_data_cback);
2846 
2847   p_i93->state = RW_I93_STATE_IDLE;
2848 
2849   /* convert UID to big endian format - MSB(0xE0) in first byte */
2850   p = uid;
2851   STREAM_TO_ARRAY8(p, p_uid);
2852 
2853   rw_i93_get_product_version(uid);
2854 
2855   return NFC_STATUS_OK;
2856 }
2857 
2858 /*******************************************************************************
2859 **
2860 ** Function         RW_I93Inventory
2861 **
2862 ** Description      This function send Inventory command with/without AFI
2863 **                  If UID is provided then set UID[0]:MSB, ... UID[7]:LSB
2864 **
2865 **                  RW_I93_RESPONSE_EVT will be returned
2866 **
2867 ** Returns          NFC_STATUS_OK if success
2868 **                  NFC_STATUS_NO_BUFFERS if out of buffer
2869 **                  NFC_STATUS_BUSY if busy
2870 **                  NFC_STATUS_FAILED if other error
2871 **
2872 *******************************************************************************/
RW_I93Inventory(bool including_afi,uint8_t afi,uint8_t * p_uid)2873 tNFC_STATUS RW_I93Inventory(bool including_afi, uint8_t afi, uint8_t* p_uid) {
2874   tNFC_STATUS status;
2875 
2876   RW_TRACE_API2("RW_I93Inventory (), including_afi:%d, AFI:0x%02X",
2877                 including_afi, afi);
2878 
2879   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
2880     RW_TRACE_ERROR1(
2881         "RW_I93Inventory ():Unable to start command at state (0x%X)",
2882         rw_cb.tcb.i93.state);
2883     return NFC_STATUS_BUSY;
2884   }
2885 
2886   status = rw_i93_send_cmd_inventory(p_uid, including_afi, afi);
2887 
2888   if (status == NFC_STATUS_OK) {
2889     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
2890   }
2891 
2892   return (status);
2893 }
2894 
2895 /*******************************************************************************
2896 **
2897 ** Function         RW_I93StayQuiet
2898 **
2899 ** Description      This function send Inventory command
2900 **
2901 **                  RW_I93_CMD_CMPL_EVT will be returned
2902 **
2903 ** Returns          NFC_STATUS_OK if success
2904 **                  NFC_STATUS_NO_BUFFERS if out of buffer
2905 **                  NFC_STATUS_BUSY if busy
2906 **                  NFC_STATUS_FAILED if other error
2907 **
2908 *******************************************************************************/
RW_I93StayQuiet(void)2909 tNFC_STATUS RW_I93StayQuiet(void) {
2910   tNFC_STATUS status;
2911 
2912   RW_TRACE_API0("RW_I93StayQuiet ()");
2913 
2914   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
2915     RW_TRACE_ERROR1(
2916         "RW_I93StayQuiet ():Unable to start command at state (0x%X)",
2917         rw_cb.tcb.i93.state);
2918     return NFC_STATUS_BUSY;
2919   }
2920 
2921   status = rw_i93_send_cmd_stay_quiet();
2922   if (status == NFC_STATUS_OK) {
2923     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
2924   }
2925 
2926   return status;
2927 }
2928 
2929 /*******************************************************************************
2930 **
2931 ** Function         RW_I93ReadSingleBlock
2932 **
2933 ** Description      This function send Read Single Block command
2934 **
2935 **                  RW_I93_RESPONSE_EVT will be returned
2936 **
2937 ** Returns          NFC_STATUS_OK if success
2938 **                  NFC_STATUS_NO_BUFFERS if out of buffer
2939 **                  NFC_STATUS_BUSY if busy
2940 **                  NFC_STATUS_FAILED if other error
2941 **
2942 *******************************************************************************/
RW_I93ReadSingleBlock(uint16_t block_number)2943 tNFC_STATUS RW_I93ReadSingleBlock(uint16_t block_number) {
2944   tNFC_STATUS status;
2945 
2946   RW_TRACE_API1("RW_I93ReadSingleBlock () block_number:0x%02X", block_number);
2947 
2948   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
2949     RW_TRACE_ERROR1(
2950         "RW_I93ReadSingleBlock ():Unable to start command at state (0x%X)",
2951         rw_cb.tcb.i93.state);
2952     return NFC_STATUS_BUSY;
2953   }
2954 
2955   status = rw_i93_send_cmd_read_single_block(block_number, false);
2956   if (status == NFC_STATUS_OK) {
2957     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
2958   }
2959 
2960   return status;
2961 }
2962 
2963 /*******************************************************************************
2964 **
2965 ** Function         RW_I93WriteSingleBlock
2966 **
2967 ** Description      This function send Write Single Block command
2968 **                  Application must get block size first by calling
2969 **                  RW_I93GetSysInfo().
2970 **
2971 **                  RW_I93_CMD_CMPL_EVT will be returned
2972 **
2973 ** Returns          NFC_STATUS_OK if success
2974 **                  NFC_STATUS_NO_BUFFERS if out of buffer
2975 **                  NFC_STATUS_BUSY if busy
2976 **                  NFC_STATUS_FAILED if other error
2977 **
2978 *******************************************************************************/
RW_I93WriteSingleBlock(uint16_t block_number,uint8_t * p_data)2979 tNFC_STATUS RW_I93WriteSingleBlock(uint16_t block_number, uint8_t* p_data) {
2980   tNFC_STATUS status;
2981 
2982   RW_TRACE_API0("RW_I93WriteSingleBlock ()");
2983 
2984   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
2985     RW_TRACE_ERROR1(
2986         "RW_I93WriteSingleBlock ():Unable to start command at state (0x%X)",
2987         rw_cb.tcb.i93.state);
2988     return NFC_STATUS_BUSY;
2989   }
2990 
2991   if (rw_cb.tcb.i93.block_size == 0) {
2992     RW_TRACE_ERROR0("RW_I93WriteSingleBlock ():Block size is unknown");
2993     return NFC_STATUS_FAILED;
2994   }
2995 
2996   status = rw_i93_send_cmd_write_single_block(block_number, p_data);
2997   if (status == NFC_STATUS_OK) {
2998     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
2999   }
3000 
3001   return status;
3002 }
3003 
3004 /*******************************************************************************
3005 **
3006 ** Function         RW_I93LockBlock
3007 **
3008 ** Description      This function send Lock Block command
3009 **
3010 **                  RW_I93_CMD_CMPL_EVT will be returned
3011 **
3012 ** Returns          NFC_STATUS_OK if success
3013 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3014 **                  NFC_STATUS_BUSY if busy
3015 **                  NFC_STATUS_FAILED if other error
3016 **
3017 *******************************************************************************/
RW_I93LockBlock(uint8_t block_number)3018 tNFC_STATUS RW_I93LockBlock(uint8_t block_number) {
3019   tNFC_STATUS status;
3020 
3021   RW_TRACE_API0("RW_I93LockBlock ()");
3022 
3023   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3024     RW_TRACE_ERROR1(
3025         "RW_I93LockBlock ():Unable to start command at state (0x%X)",
3026         rw_cb.tcb.i93.state);
3027     return NFC_STATUS_BUSY;
3028   }
3029 
3030   status = rw_i93_send_cmd_lock_block(block_number);
3031   if (status == NFC_STATUS_OK) {
3032     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3033   }
3034 
3035   return status;
3036 }
3037 
3038 /*******************************************************************************
3039 **
3040 ** Function         RW_I93ReadMultipleBlocks
3041 **
3042 ** Description      This function send Read Multiple Blocks command
3043 **
3044 **                  RW_I93_RESPONSE_EVT will be returned
3045 **
3046 ** Returns          NFC_STATUS_OK if success
3047 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3048 **                  NFC_STATUS_BUSY if busy
3049 **                  NFC_STATUS_FAILED if other error
3050 **
3051 *******************************************************************************/
RW_I93ReadMultipleBlocks(uint16_t first_block_number,uint16_t number_blocks)3052 tNFC_STATUS RW_I93ReadMultipleBlocks(uint16_t first_block_number,
3053                                      uint16_t number_blocks) {
3054   tNFC_STATUS status;
3055 
3056   RW_TRACE_API0("RW_I93ReadMultipleBlocks ()");
3057 
3058   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3059     RW_TRACE_ERROR1(
3060         "RW_I93ReadMultipleBlocks ():Unable to start command at state (0x%X)",
3061         rw_cb.tcb.i93.state);
3062     return NFC_STATUS_BUSY;
3063   }
3064 
3065   status = rw_i93_send_cmd_read_multi_blocks(first_block_number, number_blocks);
3066   if (status == NFC_STATUS_OK) {
3067     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3068   }
3069 
3070   return status;
3071 }
3072 
3073 /*******************************************************************************
3074 **
3075 ** Function         RW_I93WriteMultipleBlocks
3076 **
3077 ** Description      This function send Write Multiple Blocks command
3078 **
3079 **                  RW_I93_CMD_CMPL_EVT will be returned
3080 **
3081 ** Returns          NFC_STATUS_OK if success
3082 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3083 **                  NFC_STATUS_BUSY if busy
3084 **                  NFC_STATUS_FAILED if other error
3085 **
3086 *******************************************************************************/
RW_I93WriteMultipleBlocks(uint8_t first_block_number,uint16_t number_blocks,uint8_t * p_data)3087 tNFC_STATUS RW_I93WriteMultipleBlocks(uint8_t first_block_number,
3088                                       uint16_t number_blocks, uint8_t* p_data) {
3089   tNFC_STATUS status;
3090 
3091   RW_TRACE_API0("RW_I93WriteMultipleBlocks ()");
3092 
3093   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3094     RW_TRACE_ERROR1(
3095         "RW_I93WriteMultipleBlocks ():Unable to start command at state (0x%X)",
3096         rw_cb.tcb.i93.state);
3097     return NFC_STATUS_BUSY;
3098   }
3099 
3100   if (rw_cb.tcb.i93.block_size == 0) {
3101     RW_TRACE_ERROR0("RW_I93WriteSingleBlock ():Block size is unknown");
3102     return NFC_STATUS_FAILED;
3103   }
3104 
3105   status = rw_i93_send_cmd_write_multi_blocks(first_block_number, number_blocks,
3106                                               p_data);
3107   if (status == NFC_STATUS_OK) {
3108     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3109   }
3110 
3111   return status;
3112 }
3113 
3114 /*******************************************************************************
3115 **
3116 ** Function         RW_I93Select
3117 **
3118 ** Description      This function send Select command
3119 **
3120 **                  UID[0]: 0xE0, MSB
3121 **                  UID[1]: IC Mfg Code
3122 **                  ...
3123 **                  UID[7]: LSB
3124 **
3125 **                  RW_I93_CMD_CMPL_EVT will be returned
3126 **
3127 ** Returns          NFC_STATUS_OK if success
3128 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3129 **                  NFC_STATUS_BUSY if busy
3130 **                  NFC_STATUS_FAILED if other error
3131 **
3132 *******************************************************************************/
RW_I93Select(uint8_t * p_uid)3133 tNFC_STATUS RW_I93Select(uint8_t* p_uid) {
3134   tNFC_STATUS status;
3135 
3136   RW_TRACE_API0("RW_I93Select ()");
3137 
3138   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3139     RW_TRACE_ERROR1("RW_I93Select ():Unable to start command at state (0x%X)",
3140                     rw_cb.tcb.i93.state);
3141     return NFC_STATUS_BUSY;
3142   }
3143 
3144   if (p_uid) {
3145     status = rw_i93_send_cmd_select(p_uid);
3146     if (status == NFC_STATUS_OK) {
3147       rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3148     }
3149   } else {
3150     RW_TRACE_ERROR0("RW_I93Select ():UID shall be provided");
3151     status = NFC_STATUS_FAILED;
3152   }
3153 
3154   return status;
3155 }
3156 
3157 /*******************************************************************************
3158 **
3159 ** Function         RW_I93ResetToReady
3160 **
3161 ** Description      This function send Reset To Ready command
3162 **
3163 **                  RW_I93_CMD_CMPL_EVT will be returned
3164 **
3165 ** Returns          NFC_STATUS_OK if success
3166 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3167 **                  NFC_STATUS_BUSY if busy
3168 **                  NFC_STATUS_FAILED if other error
3169 **
3170 *******************************************************************************/
RW_I93ResetToReady(void)3171 tNFC_STATUS RW_I93ResetToReady(void) {
3172   tNFC_STATUS status;
3173 
3174   RW_TRACE_API0("RW_I93ResetToReady ()");
3175 
3176   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3177     RW_TRACE_ERROR1(
3178         "RW_I93ResetToReady ():Unable to start command at state (0x%X)",
3179         rw_cb.tcb.i93.state);
3180     return NFC_STATUS_BUSY;
3181   }
3182 
3183   status = rw_i93_send_cmd_reset_to_ready();
3184   if (status == NFC_STATUS_OK) {
3185     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3186   }
3187 
3188   return status;
3189 }
3190 
3191 /*******************************************************************************
3192 **
3193 ** Function         RW_I93WriteAFI
3194 **
3195 ** Description      This function send Write AFI command
3196 **
3197 **                  RW_I93_CMD_CMPL_EVT will be returned
3198 **
3199 ** Returns          NFC_STATUS_OK if success
3200 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3201 **                  NFC_STATUS_BUSY if busy
3202 **                  NFC_STATUS_FAILED if other error
3203 **
3204 *******************************************************************************/
RW_I93WriteAFI(uint8_t afi)3205 tNFC_STATUS RW_I93WriteAFI(uint8_t afi) {
3206   tNFC_STATUS status;
3207 
3208   RW_TRACE_API0("RW_I93WriteAFI ()");
3209 
3210   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3211     RW_TRACE_ERROR1("RW_I93WriteAFI ():Unable to start command at state (0x%X)",
3212                     rw_cb.tcb.i93.state);
3213     return NFC_STATUS_BUSY;
3214   }
3215 
3216   status = rw_i93_send_cmd_write_afi(afi);
3217   if (status == NFC_STATUS_OK) {
3218     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3219   }
3220 
3221   return status;
3222 }
3223 
3224 /*******************************************************************************
3225 **
3226 ** Function         RW_I93LockAFI
3227 **
3228 ** Description      This function send Lock AFI command
3229 **
3230 **                  RW_I93_CMD_CMPL_EVT will be returned
3231 **
3232 ** Returns          NFC_STATUS_OK if success
3233 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3234 **                  NFC_STATUS_BUSY if busy
3235 **                  NFC_STATUS_FAILED if other error
3236 **
3237 *******************************************************************************/
RW_I93LockAFI(void)3238 tNFC_STATUS RW_I93LockAFI(void) {
3239   tNFC_STATUS status;
3240 
3241   RW_TRACE_API0("RW_I93LockAFI ()");
3242 
3243   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3244     RW_TRACE_ERROR1("RW_I93LockAFI ():Unable to start command at state (0x%X)",
3245                     rw_cb.tcb.i93.state);
3246     return NFC_STATUS_BUSY;
3247   }
3248 
3249   status = rw_i93_send_cmd_lock_afi();
3250   if (status == NFC_STATUS_OK) {
3251     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3252   }
3253 
3254   return status;
3255 }
3256 
3257 /*******************************************************************************
3258 **
3259 ** Function         RW_I93WriteDSFID
3260 **
3261 ** Description      This function send Write DSFID command
3262 **
3263 **                  RW_I93_CMD_CMPL_EVT will be returned
3264 **
3265 ** Returns          NFC_STATUS_OK if success
3266 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3267 **                  NFC_STATUS_BUSY if busy
3268 **                  NFC_STATUS_FAILED if other error
3269 **
3270 *******************************************************************************/
RW_I93WriteDSFID(uint8_t dsfid)3271 tNFC_STATUS RW_I93WriteDSFID(uint8_t dsfid) {
3272   tNFC_STATUS status;
3273 
3274   RW_TRACE_API0("RW_I93WriteDSFID ()");
3275 
3276   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3277     RW_TRACE_ERROR1(
3278         "RW_I93WriteDSFID ():Unable to start command at state (0x%X)",
3279         rw_cb.tcb.i93.state);
3280     return NFC_STATUS_BUSY;
3281   }
3282 
3283   status = rw_i93_send_cmd_write_dsfid(dsfid);
3284   if (status == NFC_STATUS_OK) {
3285     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3286   }
3287 
3288   return status;
3289 }
3290 
3291 /*******************************************************************************
3292 **
3293 ** Function         RW_I93LockDSFID
3294 **
3295 ** Description      This function send Lock DSFID command
3296 **
3297 **                  RW_I93_CMD_CMPL_EVT will be returned
3298 **
3299 ** Returns          NFC_STATUS_OK if success
3300 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3301 **                  NFC_STATUS_BUSY if busy
3302 **                  NFC_STATUS_FAILED if other error
3303 **
3304 *******************************************************************************/
RW_I93LockDSFID(void)3305 tNFC_STATUS RW_I93LockDSFID(void) {
3306   tNFC_STATUS status;
3307 
3308   RW_TRACE_API0("RW_I93LockDSFID ()");
3309 
3310   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3311     RW_TRACE_ERROR1(
3312         "RW_I93LockDSFID ():Unable to start command at state (0x%X)",
3313         rw_cb.tcb.i93.state);
3314     return NFC_STATUS_BUSY;
3315   }
3316 
3317   status = rw_i93_send_cmd_lock_dsfid();
3318   if (status == NFC_STATUS_OK) {
3319     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3320   }
3321 
3322   return status;
3323 }
3324 
3325 /*******************************************************************************
3326 **
3327 ** Function         RW_I93GetSysInfo
3328 **
3329 ** Description      This function send Get System Information command
3330 **
3331 **                  RW_I93_RESPONSE_EVT will be returned
3332 **
3333 ** Returns          NFC_STATUS_OK if success
3334 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3335 **                  NFC_STATUS_BUSY if busy
3336 **                  NFC_STATUS_FAILED if other error
3337 **
3338 *******************************************************************************/
RW_I93GetSysInfo(uint8_t * p_uid)3339 tNFC_STATUS RW_I93GetSysInfo(uint8_t* p_uid) {
3340   tNFC_STATUS status;
3341 
3342   RW_TRACE_API0("RW_I93GetSysInfo ()");
3343 
3344   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3345     RW_TRACE_ERROR1(
3346         "RW_I93GetSysInfo ():Unable to start command at state (0x%X)",
3347         rw_cb.tcb.i93.state);
3348     return NFC_STATUS_BUSY;
3349   }
3350 
3351   if (p_uid) {
3352     status = rw_i93_send_cmd_get_sys_info(p_uid, I93_FLAG_PROT_EXT_NO);
3353   } else {
3354     status = rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_NO);
3355   }
3356 
3357   if (status == NFC_STATUS_OK) {
3358     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3359   }
3360 
3361   return status;
3362 }
3363 
3364 /*******************************************************************************
3365 **
3366 ** Function         RW_I93GetMultiBlockSecurityStatus
3367 **
3368 ** Description      This function send Get Multiple Block Security Status
3369 **                  command
3370 **
3371 **                  RW_I93_RESPONSE_EVT will be returned
3372 **
3373 ** Returns          NFC_STATUS_OK if success
3374 **                  NFC_STATUS_NO_BUFFERS if out of buffer
3375 **                  NFC_STATUS_BUSY if busy
3376 **                  NFC_STATUS_FAILED if other error
3377 **
3378 *******************************************************************************/
RW_I93GetMultiBlockSecurityStatus(uint16_t first_block_number,uint16_t number_blocks)3379 tNFC_STATUS RW_I93GetMultiBlockSecurityStatus(uint16_t first_block_number,
3380                                               uint16_t number_blocks) {
3381   tNFC_STATUS status;
3382 
3383   RW_TRACE_API0("RW_I93GetMultiBlockSecurityStatus ()");
3384 
3385   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3386     RW_TRACE_ERROR1(
3387         "RW_I93GetMultiBlockSecurityStatus ():Unable to start command at state "
3388         "(0x%X)",
3389         rw_cb.tcb.i93.state);
3390     return NFC_STATUS_BUSY;
3391   }
3392 
3393   status =
3394       rw_i93_send_cmd_get_multi_block_sec(first_block_number, number_blocks);
3395   if (status == NFC_STATUS_OK) {
3396     rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
3397   }
3398 
3399   return status;
3400 }
3401 
3402 /*******************************************************************************
3403 **
3404 ** Function         RW_I93DetectNDef
3405 **
3406 ** Description      This function performs NDEF detection procedure
3407 **
3408 **                  RW_I93_NDEF_DETECT_EVT will be returned
3409 **
3410 ** Returns          NFC_STATUS_OK if success
3411 **                  NFC_STATUS_FAILED if busy or other error
3412 **
3413 *******************************************************************************/
RW_I93DetectNDef(void)3414 tNFC_STATUS RW_I93DetectNDef(void) {
3415   tNFC_STATUS status;
3416   tRW_I93_RW_SUBSTATE sub_state;
3417 
3418   RW_TRACE_API0("RW_I93DetectNDef ()");
3419 
3420   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3421     RW_TRACE_ERROR1(
3422         "RW_I93DetectNDef ():Unable to start command at state (0x%X)",
3423         rw_cb.tcb.i93.state);
3424     return NFC_STATUS_FAILED;
3425   }
3426 
3427   if (rw_cb.tcb.i93.uid[0] != I93_UID_FIRST_BYTE) {
3428     status = rw_i93_send_cmd_inventory(NULL, false, 0x00);
3429     sub_state = RW_I93_SUBSTATE_WAIT_UID;
3430   } else if ((rw_cb.tcb.i93.num_block == 0) ||
3431              (rw_cb.tcb.i93.block_size == 0)) {
3432     status =
3433         rw_i93_send_cmd_get_sys_info(rw_cb.tcb.i93.uid, I93_FLAG_PROT_EXT_NO);
3434     sub_state = RW_I93_SUBSTATE_WAIT_SYS_INFO;
3435 
3436     /* clear all flags */
3437     rw_cb.tcb.i93.intl_flags = 0;
3438   } else {
3439     /* read CC in the first block */
3440     status = rw_i93_send_cmd_read_single_block(0x0000, false);
3441     sub_state = RW_I93_SUBSTATE_WAIT_CC;
3442   }
3443 
3444   if (status == NFC_STATUS_OK) {
3445     rw_cb.tcb.i93.state = RW_I93_STATE_DETECT_NDEF;
3446     rw_cb.tcb.i93.sub_state = sub_state;
3447 
3448     /* clear flags except flag for 2 bytes of number of blocks */
3449     rw_cb.tcb.i93.intl_flags &= RW_I93_FLAG_16BIT_NUM_BLOCK;
3450   }
3451 
3452   return (status);
3453 }
3454 
3455 /*******************************************************************************
3456 **
3457 ** Function         RW_I93ReadNDef
3458 **
3459 ** Description      This function performs NDEF read procedure
3460 **                  Note: RW_I93DetectNDef () must be called before using this
3461 **
3462 **                  The following event will be returned
3463 **                      RW_I93_NDEF_READ_EVT for each segmented NDEF message
3464 **                      RW_I93_NDEF_READ_CPLT_EVT for the last segment or
3465 **                      complete NDEF
3466 **                      RW_I93_NDEF_READ_FAIL_EVT for failure
3467 **
3468 ** Returns          NFC_STATUS_OK if success
3469 **                  NFC_STATUS_FAILED if I93 is busy or other error
3470 **
3471 *******************************************************************************/
RW_I93ReadNDef(void)3472 tNFC_STATUS RW_I93ReadNDef(void) {
3473   RW_TRACE_API0("RW_I93ReadNDef ()");
3474 
3475   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3476     RW_TRACE_ERROR1("RW_I93ReadNDef ():Unable to start command at state (0x%X)",
3477                     rw_cb.tcb.i93.state);
3478     return NFC_STATUS_FAILED;
3479   }
3480 
3481   if ((rw_cb.tcb.i93.tlv_type == I93_ICODE_TLV_TYPE_NDEF) &&
3482       (rw_cb.tcb.i93.ndef_length > 0)) {
3483     rw_cb.tcb.i93.rw_offset = rw_cb.tcb.i93.ndef_tlv_start_offset;
3484     rw_cb.tcb.i93.rw_length = 0;
3485 
3486     if (rw_i93_get_next_blocks(rw_cb.tcb.i93.rw_offset) == NFC_STATUS_OK) {
3487       rw_cb.tcb.i93.state = RW_I93_STATE_READ_NDEF;
3488     } else {
3489       return NFC_STATUS_FAILED;
3490     }
3491   } else {
3492     RW_TRACE_ERROR0("RW_I93ReadNDef ():No NDEF detected");
3493     return NFC_STATUS_FAILED;
3494   }
3495 
3496   return NFC_STATUS_OK;
3497 }
3498 
3499 /*******************************************************************************
3500 **
3501 ** Function         RW_I93UpdateNDef
3502 **
3503 ** Description      This function performs NDEF update procedure
3504 **                  Note: RW_I93DetectNDef () must be called before using this
3505 **                        Updating data must not be removed until returning
3506 **                        event
3507 **
3508 **                  The following event will be returned
3509 **                      RW_I93_NDEF_UPDATE_CPLT_EVT for complete
3510 **                      RW_I93_NDEF_UPDATE_FAIL_EVT for failure
3511 **
3512 ** Returns          NFC_STATUS_OK if success
3513 **                  NFC_STATUS_FAILED if I93 is busy or other error
3514 **
3515 *******************************************************************************/
RW_I93UpdateNDef(uint16_t length,uint8_t * p_data)3516 tNFC_STATUS RW_I93UpdateNDef(uint16_t length, uint8_t* p_data) {
3517   uint16_t block_number;
3518 
3519   RW_TRACE_API1("RW_I93UpdateNDef () length:%d", length);
3520 
3521   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3522     RW_TRACE_ERROR1(
3523         "RW_I93UpdateNDef ():Unable to start command at state (0x%X)",
3524         rw_cb.tcb.i93.state);
3525     return NFC_STATUS_FAILED;
3526   }
3527 
3528   if (rw_cb.tcb.i93.tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
3529     if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_READ_ONLY) {
3530       RW_TRACE_ERROR0("RW_I93UpdateNDef ():NDEF is read-only");
3531       return NFC_STATUS_FAILED;
3532     }
3533     if (rw_cb.tcb.i93.max_ndef_length < length) {
3534       RW_TRACE_ERROR2(
3535           "RW_I93UpdateNDef ():data (%d bytes) is more than max NDEF length "
3536           "(%d)",
3537           length, rw_cb.tcb.i93.max_ndef_length);
3538       return NFC_STATUS_FAILED;
3539     }
3540 
3541     rw_cb.tcb.i93.ndef_length = length;
3542     rw_cb.tcb.i93.p_update_data = p_data;
3543 
3544     /* read length field */
3545     rw_cb.tcb.i93.rw_offset = rw_cb.tcb.i93.ndef_tlv_start_offset + 1;
3546     rw_cb.tcb.i93.rw_length = 0;
3547 
3548     block_number = rw_cb.tcb.i93.rw_offset / rw_cb.tcb.i93.block_size;
3549 
3550     if (rw_i93_send_cmd_read_single_block(block_number, false) ==
3551         NFC_STATUS_OK) {
3552       rw_cb.tcb.i93.state = RW_I93_STATE_UPDATE_NDEF;
3553       rw_cb.tcb.i93.sub_state = RW_I93_SUBSTATE_RESET_LEN;
3554     } else {
3555       return NFC_STATUS_FAILED;
3556     }
3557   } else {
3558     RW_TRACE_ERROR0("RW_I93ReadNDef ():No NDEF detected");
3559     return NFC_STATUS_FAILED;
3560   }
3561 
3562   return NFC_STATUS_OK;
3563 }
3564 
3565 /*******************************************************************************
3566 **
3567 ** Function         RW_I93FormatNDef
3568 **
3569 ** Description      This function performs formatting procedure
3570 **
3571 **                  RW_I93_FORMAT_CPLT_EVT will be returned
3572 **
3573 ** Returns          NFC_STATUS_OK if success
3574 **                  NFC_STATUS_FAILED if busy or other error
3575 **
3576 *******************************************************************************/
RW_I93FormatNDef(void)3577 tNFC_STATUS RW_I93FormatNDef(void) {
3578   tNFC_STATUS status;
3579   tRW_I93_RW_SUBSTATE sub_state;
3580 
3581   RW_TRACE_API0("RW_I93FormatNDef ()");
3582 
3583   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3584     RW_TRACE_ERROR1(
3585         "RW_I93FormatNDef ():Unable to start command at state (0x%X)",
3586         rw_cb.tcb.i93.state);
3587     return NFC_STATUS_FAILED;
3588   }
3589 
3590   if ((rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
3591       (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
3592     /* These don't support GetSystemInformation and GetMultiBlockSecurityStatus
3593      */
3594     rw_cb.tcb.i93.rw_offset = 0;
3595 
3596     /* read blocks with option flag to get block security status */
3597     status = rw_i93_send_cmd_read_single_block(0x0000, true);
3598     sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
3599   } else {
3600     status = rw_i93_send_cmd_inventory(rw_cb.tcb.i93.uid, false, 0x00);
3601     sub_state = RW_I93_SUBSTATE_WAIT_UID;
3602   }
3603 
3604   if (status == NFC_STATUS_OK) {
3605     rw_cb.tcb.i93.state = RW_I93_STATE_FORMAT;
3606     rw_cb.tcb.i93.sub_state = sub_state;
3607     rw_cb.tcb.i93.intl_flags = 0;
3608   }
3609 
3610   return (status);
3611 }
3612 
3613 /*******************************************************************************
3614 **
3615 ** Function         RW_I93SetTagReadOnly
3616 **
3617 ** Description      This function performs NDEF read-only procedure
3618 **                  Note: RW_I93DetectNDef () must be called before using this
3619 **                        Updating data must not be removed until returning
3620 **                        event
3621 **
3622 **                  The RW_I93_SET_TAG_RO_EVT event will be returned.
3623 **
3624 ** Returns          NFC_STATUS_OK if success
3625 **                  NFC_STATUS_FAILED if I93 is busy or other error
3626 **
3627 *******************************************************************************/
RW_I93SetTagReadOnly(void)3628 tNFC_STATUS RW_I93SetTagReadOnly(void) {
3629   RW_TRACE_API0("RW_I93SetTagReadOnly ()");
3630 
3631   if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3632     RW_TRACE_ERROR1(
3633         "RW_I93SetTagReadOnly ():Unable to start command at state (0x%X)",
3634         rw_cb.tcb.i93.state);
3635     return NFC_STATUS_FAILED;
3636   }
3637 
3638   if (rw_cb.tcb.i93.tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
3639     if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_READ_ONLY) {
3640       RW_TRACE_ERROR0("RW_I93SetTagReadOnly ():NDEF is already read-only");
3641       return NFC_STATUS_FAILED;
3642     }
3643 
3644     /* get CC in the first block */
3645     if (rw_i93_send_cmd_read_single_block(0, false) == NFC_STATUS_OK) {
3646       rw_cb.tcb.i93.state = RW_I93_STATE_SET_READ_ONLY;
3647       rw_cb.tcb.i93.sub_state = RW_I93_SUBSTATE_WAIT_CC;
3648     } else {
3649       return NFC_STATUS_FAILED;
3650     }
3651   } else {
3652     RW_TRACE_ERROR0("RW_I93SetTagReadOnly ():No NDEF detected");
3653     return NFC_STATUS_FAILED;
3654   }
3655 
3656   return NFC_STATUS_OK;
3657 }
3658 
3659 /*****************************************************************************
3660 **
3661 ** Function         RW_I93PresenceCheck
3662 **
3663 ** Description      Check if the tag is still in the field.
3664 **
3665 **                  The RW_I93_PRESENCE_CHECK_EVT w/ status is used to indicate
3666 **                  presence or non-presence.
3667 **
3668 ** Returns          NFC_STATUS_OK, if raw data frame sent
3669 **                  NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this
3670 **                  operation
3671 **                  NFC_STATUS_FAILED: other error
3672 **
3673 *****************************************************************************/
RW_I93PresenceCheck(void)3674 tNFC_STATUS RW_I93PresenceCheck(void) {
3675   tNFC_STATUS status;
3676   tRW_DATA evt_data;
3677 
3678   RW_TRACE_API0("RW_I93PresenceCheck ()");
3679 
3680   if (!rw_cb.p_cback) {
3681     return NFC_STATUS_FAILED;
3682   } else if (rw_cb.tcb.i93.state == RW_I93_STATE_NOT_ACTIVATED) {
3683     evt_data.status = NFC_STATUS_FAILED;
3684     (*rw_cb.p_cback)(RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
3685 
3686     return NFC_STATUS_OK;
3687   } else if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
3688     return NFC_STATUS_BUSY;
3689   } else {
3690     /* The support of AFI by the VICC is optional, so do not include AFI */
3691     status = rw_i93_send_cmd_inventory(rw_cb.tcb.i93.uid, false, 0x00);
3692 
3693     if (status == NFC_STATUS_OK) {
3694       /* do not retry during presence check */
3695       rw_cb.tcb.i93.retry_count = RW_MAX_RETRIES;
3696       rw_cb.tcb.i93.state = RW_I93_STATE_PRESENCE_CHECK;
3697     }
3698   }
3699 
3700   return (status);
3701 }
3702 
3703 #if (BT_TRACE_VERBOSE == TRUE)
3704 /*******************************************************************************
3705 **
3706 ** Function         rw_i93_get_state_name
3707 **
3708 ** Description      This function returns the state name.
3709 **
3710 ** NOTE             conditionally compiled to save memory.
3711 **
3712 ** Returns          pointer to the name
3713 **
3714 *******************************************************************************/
rw_i93_get_state_name(uint8_t state)3715 static char* rw_i93_get_state_name(uint8_t state) {
3716   switch (state) {
3717     case RW_I93_STATE_NOT_ACTIVATED:
3718       return ("NOT_ACTIVATED");
3719     case RW_I93_STATE_IDLE:
3720       return ("IDLE");
3721     case RW_I93_STATE_BUSY:
3722       return ("BUSY");
3723 
3724     case RW_I93_STATE_DETECT_NDEF:
3725       return ("NDEF_DETECTION");
3726     case RW_I93_STATE_READ_NDEF:
3727       return ("READ_NDEF");
3728     case RW_I93_STATE_UPDATE_NDEF:
3729       return ("UPDATE_NDEF");
3730     case RW_I93_STATE_FORMAT:
3731       return ("FORMAT");
3732     case RW_I93_STATE_SET_READ_ONLY:
3733       return ("SET_READ_ONLY");
3734 
3735     case RW_I93_STATE_PRESENCE_CHECK:
3736       return ("PRESENCE_CHECK");
3737     default:
3738       return ("???? UNKNOWN STATE");
3739   }
3740 }
3741 
3742 /*******************************************************************************
3743 **
3744 ** Function         rw_i93_get_sub_state_name
3745 **
3746 ** Description      This function returns the sub_state name.
3747 **
3748 ** NOTE             conditionally compiled to save memory.
3749 **
3750 ** Returns          pointer to the name
3751 **
3752 *******************************************************************************/
rw_i93_get_sub_state_name(uint8_t sub_state)3753 static char* rw_i93_get_sub_state_name(uint8_t sub_state) {
3754   switch (sub_state) {
3755     case RW_I93_SUBSTATE_WAIT_UID:
3756       return ("WAIT_UID");
3757     case RW_I93_SUBSTATE_WAIT_SYS_INFO:
3758       return ("WAIT_SYS_INFO");
3759     case RW_I93_SUBSTATE_WAIT_CC:
3760       return ("WAIT_CC");
3761     case RW_I93_SUBSTATE_SEARCH_NDEF_TLV:
3762       return ("SEARCH_NDEF_TLV");
3763     case RW_I93_SUBSTATE_CHECK_LOCK_STATUS:
3764       return ("CHECK_LOCK_STATUS");
3765     case RW_I93_SUBSTATE_RESET_LEN:
3766       return ("RESET_LEN");
3767     case RW_I93_SUBSTATE_WRITE_NDEF:
3768       return ("WRITE_NDEF");
3769     case RW_I93_SUBSTATE_UPDATE_LEN:
3770       return ("UPDATE_LEN");
3771     case RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI:
3772       return ("WAIT_RESET_DSFID_AFI");
3773     case RW_I93_SUBSTATE_CHECK_READ_ONLY:
3774       return ("CHECK_READ_ONLY");
3775     case RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV:
3776       return ("WRITE_CC_NDEF_TLV");
3777     case RW_I93_SUBSTATE_WAIT_UPDATE_CC:
3778       return ("WAIT_UPDATE_CC");
3779     case RW_I93_SUBSTATE_LOCK_NDEF_TLV:
3780       return ("LOCK_NDEF_TLV");
3781     case RW_I93_SUBSTATE_WAIT_LOCK_CC:
3782       return ("WAIT_LOCK_CC");
3783     default:
3784       return ("???? UNKNOWN SUBSTATE");
3785   }
3786 }
3787 
3788 /*******************************************************************************
3789 **
3790 ** Function         rw_i93_get_tag_name
3791 **
3792 ** Description      This function returns the tag name.
3793 **
3794 ** NOTE             conditionally compiled to save memory.
3795 **
3796 ** Returns          pointer to the name
3797 **
3798 *******************************************************************************/
rw_i93_get_tag_name(uint8_t product_version)3799 static char* rw_i93_get_tag_name(uint8_t product_version) {
3800   switch (product_version) {
3801     case RW_I93_ICODE_SLI:
3802       return ("SLI/SLIX");
3803     case RW_I93_ICODE_SLI_S:
3804       return ("SLI-S/SLIX-S");
3805     case RW_I93_ICODE_SLI_L:
3806       return ("SLI-L/SLIX-L");
3807     case RW_I93_TAG_IT_HF_I_PLUS_INLAY:
3808       return ("Tag-it HF-I Plus Inlay");
3809     case RW_I93_TAG_IT_HF_I_PLUS_CHIP:
3810       return ("Tag-it HF-I Plus Chip");
3811     case RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY:
3812       return ("Tag-it HF-I Standard Chip/Inlyas");
3813     case RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY:
3814       return ("Tag-it HF-I Pro Chip/Inlays");
3815     case RW_I93_STM_LRI1K:
3816       return ("LRi1K");
3817     case RW_I93_STM_LRI2K:
3818       return ("LRi2K");
3819     case RW_I93_STM_LRIS2K:
3820       return ("LRiS2K");
3821     case RW_I93_STM_LRIS64K:
3822       return ("LRiS64K");
3823     case RW_I93_STM_M24LR64_R:
3824       return ("M24LR64");
3825     case RW_I93_STM_M24LR04E_R:
3826       return ("M24LR04E");
3827     case RW_I93_STM_M24LR16E_R:
3828       return ("M24LR16E");
3829     case RW_I93_STM_M24LR64E_R:
3830       return ("M24LR64E");
3831     case RW_I93_UNKNOWN_PRODUCT:
3832     default:
3833       return ("UNKNOWN");
3834   }
3835 }
3836 
3837 #endif
3838