1 /******************************************************************************
2  *
3  *  Copyright (C) 2010-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  *
22  *  This file contains the implementation for Type 1 tag in Reader/Writer
23  *  mode.
24  *
25  ******************************************************************************/
26 #include <string.h>
27 #include "nfc_target.h"
28 
29 #if (NFC_INCLUDED == TRUE)
30 #include "nfc_api.h"
31 #include "nci_hmsgs.h"
32 #include "rw_api.h"
33 #include "rw_int.h"
34 #include "nfc_int.h"
35 #include "gki.h"
36 
37 /* Local Functions */
38 static tRW_EVENT rw_t1t_handle_rid_rsp (BT_HDR *p_pkt);
39 static void rw_t1t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data);
40 static void rw_t1t_process_frame_error (void);
41 static void rw_t1t_process_error (void);
42 static void rw_t1t_handle_presence_check_rsp (tNFC_STATUS status);
43 #if (BT_TRACE_VERBOSE == TRUE)
44 static char *rw_t1t_get_state_name (UINT8 state);
45 static char *rw_t1t_get_sub_state_name (UINT8 sub_state);
46 static char *rw_t1t_get_event_name (UINT8 event);
47 #endif
48 
49 /*******************************************************************************
50 **
51 ** Function         rw_t1t_data_cback
52 **
53 ** Description      This callback function handles data from NFCC.
54 **
55 ** Returns          none
56 **
57 *******************************************************************************/
rw_t1t_data_cback(UINT8 conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)58 static void rw_t1t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
59 {
60     tRW_T1T_CB              *p_t1t      = &rw_cb.tcb.t1t;
61     tRW_EVENT               rw_event    = RW_RAW_FRAME_EVT;
62     BOOLEAN                 b_notify    = TRUE;
63     tRW_DATA                evt_data;
64     BT_HDR                  *p_pkt;
65     UINT8                   *p;
66     tT1T_CMD_RSP_INFO       *p_cmd_rsp_info     = (tT1T_CMD_RSP_INFO *) rw_cb.tcb.t1t.p_cmd_rsp_info;
67 #if (BT_TRACE_VERBOSE == TRUE)
68     UINT8                   begin_state         = p_t1t->state;
69 #endif
70 
71     p_pkt = (BT_HDR *) (p_data->data.p_data);
72     if (p_pkt == NULL)
73         return;
74     /* Assume the data is just the response byte sequence */
75     p = (UINT8 *) (p_pkt + 1) + p_pkt->offset;
76 
77 #if (BT_TRACE_VERBOSE == TRUE)
78     RW_TRACE_DEBUG2 ("rw_t1t_data_cback (): state:%s (%d)", rw_t1t_get_state_name (p_t1t->state), p_t1t->state);
79 #else
80     RW_TRACE_DEBUG1 ("rw_t1t_data_cback (): state=%d", p_t1t->state);
81 #endif
82 
83     evt_data.status = NFC_STATUS_OK;
84 
85     if(  (p_t1t->state == RW_T1T_STATE_IDLE)
86        ||(!p_cmd_rsp_info)  )
87     {
88         /* If previous command was retransmitted and if response is pending to previous command retransmission,
89          * check if lenght and ADD/ADD8/ADDS field matches the expected value of previous
90          * retransmited command response. However, ignore ADD field if the command was RALL/RID
91          */
92         if (  (p_t1t->prev_cmd_rsp_info.pend_retx_rsp)
93             &&(p_t1t->prev_cmd_rsp_info.rsp_len == p_pkt->len)
94             &&((p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RID) || (p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RALL) || (p_t1t->prev_cmd_rsp_info.addr == *p))  )
95         {
96             /* Response to previous command retransmission */
97             RW_TRACE_ERROR2 ("T1T Response to previous command in Idle state. command=0x%02x, Remaining max retx rsp:0x%02x ", p_t1t->prev_cmd_rsp_info.op_code, p_t1t->prev_cmd_rsp_info.pend_retx_rsp - 1);
98             p_t1t->prev_cmd_rsp_info.pend_retx_rsp--;
99             GKI_freebuf (p_pkt);
100         }
101         else
102         {
103             /* Raw frame event */
104             evt_data.data.p_data = p_pkt;
105             (*rw_cb.p_cback) (RW_T1T_RAW_FRAME_EVT, (tRW_DATA *) &evt_data);
106         }
107         return;
108     }
109 
110 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
111     /* Update rx stats */
112     rw_main_update_rx_stats (p_pkt->len);
113 #endif  /* RW_STATS_INCLUDED */
114 
115 
116     if (  (p_pkt->len != p_cmd_rsp_info->rsp_len)
117         ||((p_cmd_rsp_info->opcode != T1T_CMD_RALL) && (p_cmd_rsp_info->opcode != T1T_CMD_RID) && (*p != p_t1t->addr))  )
118 
119     {
120         /* If previous command was retransmitted and if response is pending to previous command retransmission,
121          * then check if lenght and ADD/ADD8/ADDS field matches the expected value of previous
122          * retransmited command response. However, ignore ADD field if the command was RALL/RID
123          */
124         if (  (p_t1t->prev_cmd_rsp_info.pend_retx_rsp)
125             &&(p_t1t->prev_cmd_rsp_info.rsp_len == p_pkt->len)
126             &&((p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RID) || (p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RALL) || (p_t1t->prev_cmd_rsp_info.addr == *p))  )
127         {
128             RW_TRACE_ERROR2 ("T1T Response to previous command. command=0x%02x, Remaining max retx rsp:0x%02x", p_t1t->prev_cmd_rsp_info.op_code, p_t1t->prev_cmd_rsp_info.pend_retx_rsp - 1);
129             p_t1t->prev_cmd_rsp_info.pend_retx_rsp--;
130         }
131         else
132         {
133             /* Stop timer as some response to current command is received */
134             nfc_stop_quick_timer (&p_t1t->timer);
135             /* Retrasmit the last sent command if retry-count < max retry */
136 #if (BT_TRACE_VERBOSE == TRUE)
137             RW_TRACE_ERROR2 ("T1T Frame error. state=%s command (opcode) = 0x%02x", rw_t1t_get_state_name (p_t1t->state), p_cmd_rsp_info->opcode);
138 #else
139             RW_TRACE_ERROR2 ("T1T Frame error. state=0x%02x command = 0x%02x ", p_t1t->state, p_cmd_rsp_info->opcode);
140 #endif
141             rw_t1t_process_frame_error ();
142         }
143         GKI_freebuf (p_pkt);
144         return;
145     }
146 
147     /* Stop timer as response to current command is received */
148     nfc_stop_quick_timer (&p_t1t->timer);
149 
150     RW_TRACE_EVENT2 ("RW RECV [%s]:0x%x RSP", t1t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode);
151 
152     /* If we did not receive response to all retransmitted previous command,
153      * dont expect that as response have come for the current command itself.
154      */
155     if (p_t1t->prev_cmd_rsp_info.pend_retx_rsp)
156         memset (&(p_t1t->prev_cmd_rsp_info), 0, sizeof (tRW_T1T_PREV_CMD_RSP_INFO));
157 
158     if (rw_cb.cur_retry)
159     {
160     /* If the current command was retransmitted to get this response, we might get
161        response later to all or some of the retrasnmission of the current command
162      */
163         p_t1t->prev_cmd_rsp_info.addr          = ((p_cmd_rsp_info->opcode != T1T_CMD_RALL) && (p_cmd_rsp_info->opcode != T1T_CMD_RID))? p_t1t->addr:0;
164         p_t1t->prev_cmd_rsp_info.rsp_len       = p_cmd_rsp_info->rsp_len;
165         p_t1t->prev_cmd_rsp_info.op_code       = p_cmd_rsp_info->opcode;
166         p_t1t->prev_cmd_rsp_info.pend_retx_rsp = (UINT8) rw_cb.cur_retry;
167     }
168 
169     rw_cb.cur_retry = 0;
170 
171     if (p_cmd_rsp_info->opcode == T1T_CMD_RID)
172     {
173         rw_event = rw_t1t_handle_rid_rsp (p_pkt);
174     }
175     else
176     {
177         rw_event = rw_t1t_handle_rsp (p_cmd_rsp_info, &b_notify, p, &evt_data.status);
178     }
179 
180     if (b_notify)
181     {
182         if(  (p_t1t->state != RW_T1T_STATE_READ)
183            &&(p_t1t->state != RW_T1T_STATE_WRITE)  )
184         {
185             GKI_freebuf (p_pkt);
186             evt_data.data.p_data = NULL;
187         }
188         else
189         {
190             evt_data.data.p_data = p_pkt;
191         }
192         rw_t1t_handle_op_complete ();
193         (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data);
194     }
195     else
196         GKI_freebuf (p_pkt);
197 
198 #if (BT_TRACE_VERBOSE == TRUE)
199     if (begin_state != p_t1t->state)
200     {
201         RW_TRACE_DEBUG2 ("RW T1T state changed:<%s> -> <%s>",
202                           rw_t1t_get_state_name (begin_state),
203                           rw_t1t_get_state_name (p_t1t->state));
204     }
205 #endif
206 }
207 
208 /*******************************************************************************
209 **
210 ** Function         rw_t1t_conn_cback
211 **
212 ** Description      This callback function receives the events/data from NFCC.
213 **
214 ** Returns          none
215 **
216 *******************************************************************************/
rw_t1t_conn_cback(UINT8 conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)217 void rw_t1t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
218 {
219     tRW_T1T_CB          *p_t1t  = &rw_cb.tcb.t1t;
220     tRW_READ_DATA       evt_data;
221 
222     RW_TRACE_DEBUG2 ("rw_t1t_conn_cback: conn_id=%i, evt=0x%x", conn_id, event);
223     /* Only handle static conn_id */
224     if (conn_id != NFC_RF_CONN_ID)
225     {
226         RW_TRACE_WARNING1 ("rw_t1t_conn_cback - Not static connection id: =%i", conn_id);
227         return;
228     }
229 
230     switch (event)
231     {
232     case NFC_CONN_CREATE_CEVT:
233     case NFC_CONN_CLOSE_CEVT:
234         break;
235 
236     case NFC_DEACTIVATE_CEVT:
237 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
238         /* Display stats */
239         rw_main_log_stats ();
240 #endif  /* RW_STATS_INCLUDED */
241 
242         /* Stop t1t timer (if started) */
243         nfc_stop_quick_timer (&p_t1t->timer);
244 
245         /* Free cmd buf for retransmissions */
246         if (p_t1t->p_cur_cmd_buf)
247         {
248             GKI_freebuf (p_t1t->p_cur_cmd_buf);
249             p_t1t->p_cur_cmd_buf = NULL;
250         }
251 
252         p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED;
253         NFC_SetStaticRfCback (NULL);
254         break;
255 
256     case NFC_DATA_CEVT:
257         if (p_data != NULL)
258         {
259             if (p_data->data.status == NFC_STATUS_OK)
260             {
261                 rw_t1t_data_cback (conn_id, event, p_data);
262                 break;
263             }
264             else if (p_data->data.p_data != NULL)
265             {
266                 /* Free the response buffer in case of error response */
267                 GKI_freebuf ((BT_HDR *) (p_data->data.p_data));
268                 p_data->data.p_data = NULL;
269             }
270         }
271         /* Data event with error status...fall through to NFC_ERROR_CEVT case */
272 
273     case NFC_ERROR_CEVT:
274         if (  (p_t1t->state == RW_T1T_STATE_NOT_ACTIVATED)
275             ||(p_t1t->state == RW_T1T_STATE_IDLE)  )
276         {
277 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
278             rw_main_update_trans_error_stats ();
279 #endif  /* RW_STATS_INCLUDED */
280 
281             if (event == NFC_ERROR_CEVT)
282                 evt_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
283             else if (p_data)
284                 evt_data.status = p_data->status;
285             else
286                 evt_data.status = NFC_STATUS_FAILED;
287 
288             evt_data.p_data = NULL;
289             (*rw_cb.p_cback) (RW_T1T_INTF_ERROR_EVT, (tRW_DATA *) &evt_data);
290             break;
291         }
292         nfc_stop_quick_timer (&p_t1t->timer);
293 
294 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
295         rw_main_update_trans_error_stats ();
296 #endif  /* RW_STATS_INCLUDED */
297 
298         if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE)
299         {
300             rw_t1t_handle_presence_check_rsp (NFC_STATUS_FAILED);
301         }
302         else
303         {
304             rw_t1t_process_error ();
305         }
306         break;
307 
308     default:
309         break;
310 
311     }
312 }
313 
314 /*******************************************************************************
315 **
316 ** Function         rw_t1t_send_static_cmd
317 **
318 ** Description      This function composes a Type 1 Tag command for static
319 **                  memory and send through NCI to NFCC.
320 **
321 ** Returns          NFC_STATUS_OK if the command is successfuly sent to NCI
322 **                  otherwise, error status
323 **
324 *******************************************************************************/
rw_t1t_send_static_cmd(UINT8 opcode,UINT8 add,UINT8 dat)325 tNFC_STATUS rw_t1t_send_static_cmd (UINT8 opcode, UINT8 add, UINT8 dat)
326 {
327     tNFC_STATUS             status  = NFC_STATUS_FAILED;
328     tRW_T1T_CB              *p_t1t  = &rw_cb.tcb.t1t;
329     const tT1T_CMD_RSP_INFO *p_cmd_rsp_info = t1t_cmd_to_rsp_info (opcode);
330     BT_HDR                  *p_data;
331     UINT8                   *p;
332 
333     if (p_cmd_rsp_info)
334     {
335         /* a valid opcode for RW */
336         p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
337         if (p_data)
338         {
339             p_t1t->p_cmd_rsp_info   = (tT1T_CMD_RSP_INFO *) p_cmd_rsp_info;
340             p_t1t->addr             = add;
341             p_data->offset          = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
342             p                       = (UINT8 *) (p_data + 1) + p_data->offset;
343             UINT8_TO_BE_STREAM (p, opcode);
344             UINT8_TO_BE_STREAM (p, add);
345             UINT8_TO_BE_STREAM (p, dat);
346 
347             ARRAY_TO_STREAM (p, p_t1t->mem, T1T_CMD_UID_LEN);
348             p_data->len     = p_cmd_rsp_info->cmd_len;
349 
350             /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */
351             rw_cb.cur_retry = 0;
352             memcpy (p_t1t->p_cur_cmd_buf, p_data, sizeof (BT_HDR) + p_data->offset + p_data->len);
353 
354 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
355             /* Update stats */
356             rw_main_update_tx_stats (p_data->len, FALSE);
357 #endif  /* RW_STATS_INCLUDED */
358 
359             RW_TRACE_EVENT2 ("RW SENT [%s]:0x%x CMD", t1t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode);
360             if ((status = NFC_SendData (NFC_RF_CONN_ID, p_data)) == NFC_STATUS_OK)
361             {
362                 nfc_start_quick_timer (&p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE,
363                        (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
364             }
365         }
366         else
367         {
368             status = NFC_STATUS_NO_BUFFERS;
369         }
370     }
371     return status;
372 }
373 
374 /*******************************************************************************
375 **
376 ** Function         rw_t1t_send_dyn_cmd
377 **
378 ** Description      This function composes a Type 1 Tag command for dynamic memory
379 **                  and send through NCI to NFCC.
380 **
381 ** Returns          NFC_STATUS_OK if the command is successfuly sent to NCI
382 **                  otherwise, error status
383 **
384 *******************************************************************************/
rw_t1t_send_dyn_cmd(UINT8 opcode,UINT8 add,UINT8 * p_dat)385 tNFC_STATUS rw_t1t_send_dyn_cmd (UINT8 opcode, UINT8 add, UINT8 *p_dat)
386 {
387     tNFC_STATUS             status  = NFC_STATUS_FAILED;
388     tRW_T1T_CB              *p_t1t  = &rw_cb.tcb.t1t;
389     const tT1T_CMD_RSP_INFO *p_cmd_rsp_info = t1t_cmd_to_rsp_info (opcode);
390     BT_HDR                  *p_data;
391     UINT8                   *p;
392 
393     if (p_cmd_rsp_info)
394     {
395         /* a valid opcode for RW */
396         p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
397         if (p_data)
398         {
399             p_t1t->p_cmd_rsp_info   = (tT1T_CMD_RSP_INFO *) p_cmd_rsp_info;
400             p_t1t->addr             = add;
401             p_data->offset          = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
402             p                       = (UINT8 *) (p_data + 1) + p_data->offset;
403             UINT8_TO_BE_STREAM (p, opcode);
404             UINT8_TO_BE_STREAM (p, add);
405 
406             if (p_dat)
407             {
408                 ARRAY_TO_STREAM (p, p_dat, 8);
409             }
410             else
411             {
412                 memset (p, 0, 8);
413                 p += 8;
414             }
415             ARRAY_TO_STREAM (p, p_t1t->mem, T1T_CMD_UID_LEN);
416             p_data->len     = p_cmd_rsp_info->cmd_len;
417 
418             /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */
419             rw_cb.cur_retry = 0;
420             memcpy (p_t1t->p_cur_cmd_buf, p_data, sizeof (BT_HDR) + p_data->offset + p_data->len);
421 
422 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
423             /* Update stats */
424             rw_main_update_tx_stats (p_data->len, FALSE);
425 #endif  /* RW_STATS_INCLUDED */
426 
427             RW_TRACE_EVENT2 ("RW SENT [%s]:0x%x CMD", t1t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode);
428 
429             if ((status = NFC_SendData (NFC_RF_CONN_ID, p_data)) == NFC_STATUS_OK)
430             {
431                 nfc_start_quick_timer (&p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE,
432                        (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
433             }
434         }
435         else
436         {
437             status = NFC_STATUS_NO_BUFFERS;
438         }
439     }
440     return status;
441 }
442 
443 /*****************************************************************************
444 **
445 ** Function         rw_t1t_handle_rid_rsp
446 **
447 ** Description      Handles response to RID: Collects HR, UID, notify up the
448 **                  stack
449 **
450 ** Returns          event to notify application
451 **
452 *****************************************************************************/
rw_t1t_handle_rid_rsp(BT_HDR * p_pkt)453 static tRW_EVENT rw_t1t_handle_rid_rsp (BT_HDR *p_pkt)
454 {
455     tRW_T1T_CB  *p_t1t   = &rw_cb.tcb.t1t;
456     tRW_DATA    evt_data;
457     UINT8       *p_rid_rsp;
458 
459     evt_data.status      = NFC_STATUS_OK;
460     evt_data.data.p_data = p_pkt;
461 
462     /* Assume the data is just the response byte sequence */
463     p_rid_rsp = (UINT8 *) (p_pkt + 1) + p_pkt->offset;
464 
465     /* Response indicates tag is present */
466     if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE)
467     {
468         /* If checking for the presence of the tag then just notify */
469         return RW_T1T_PRESENCE_CHECK_EVT;
470     }
471 
472     /* Extract HR and UID from response */
473     STREAM_TO_ARRAY (p_t1t->hr,  p_rid_rsp, T1T_HR_LEN);
474 
475 #if (BT_TRACE_VERBOSE == TRUE)
476     RW_TRACE_DEBUG2 ("hr0:0x%x, hr1:0x%x", p_t1t->hr[0], p_t1t->hr[1]);
477     RW_TRACE_DEBUG4 ("rw_t1t_handle_rid_rsp (): UID0-3=%02x%02x%02x%02x", p_rid_rsp[0], p_rid_rsp[1], p_rid_rsp[2], p_rid_rsp[3]);
478 #else
479     RW_TRACE_DEBUG0 ("rw_t1t_handle_rid_rsp ()");
480 #endif
481 
482     /* Fetch UID0-3 from RID response message */
483     STREAM_TO_ARRAY (p_t1t->mem,  p_rid_rsp, T1T_CMD_UID_LEN);
484 
485     /* Notify RID response Event */
486     return RW_T1T_RID_EVT;
487 }
488 
489 /*******************************************************************************
490 **
491 ** Function         rw_t1t_select
492 **
493 ** Description      This function will set the callback function to
494 **                  receive data from lower layers and also send rid command
495 **
496 ** Returns          none
497 **
498 *******************************************************************************/
rw_t1t_select(UINT8 hr[T1T_HR_LEN],UINT8 uid[T1T_CMD_UID_LEN])499 tNFC_STATUS rw_t1t_select (UINT8 hr[T1T_HR_LEN], UINT8 uid[T1T_CMD_UID_LEN])
500 {
501     tNFC_STATUS status  = NFC_STATUS_FAILED;
502     tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
503 
504     p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED;
505 
506     /* Alloc cmd buf for retransmissions */
507     if (p_t1t->p_cur_cmd_buf ==  NULL)
508     {
509         if ((p_t1t->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
510         {
511             RW_TRACE_ERROR0 ("rw_t1t_select: unable to allocate buffer for retransmission");
512             return status;
513         }
514     }
515 
516     memcpy (p_t1t->hr, hr, T1T_HR_LEN);
517     memcpy (p_t1t->mem, uid, T1T_CMD_UID_LEN);
518 
519     NFC_SetStaticRfCback (rw_t1t_conn_cback);
520 
521     p_t1t->state    = RW_T1T_STATE_IDLE;
522 
523     return NFC_STATUS_OK;
524 }
525 
526 /*******************************************************************************
527 **
528 ** Function         rw_t1t_process_timeout
529 **
530 ** Description      process timeout event
531 **
532 ** Returns          none
533 **
534 *******************************************************************************/
rw_t1t_process_timeout(TIMER_LIST_ENT * p_tle)535 void rw_t1t_process_timeout (TIMER_LIST_ENT *p_tle)
536 {
537     tRW_T1T_CB        *p_t1t  = &rw_cb.tcb.t1t;
538 
539 #if (BT_TRACE_VERBOSE == TRUE)
540     RW_TRACE_ERROR2 ("T1T timeout. state=%s command (opcode)=0x%02x ", rw_t1t_get_state_name (p_t1t->state), (rw_cb.tcb.t1t.p_cmd_rsp_info)->opcode);
541 #else
542     RW_TRACE_ERROR2 ("T1T timeout. state=0x%02x command=0x%02x ", p_t1t->state, (rw_cb.tcb.t1t.p_cmd_rsp_info)->opcode);
543 #endif
544 
545     if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE)
546     {
547         /* Tag has moved from range */
548         rw_t1t_handle_presence_check_rsp (NFC_STATUS_FAILED);
549     }
550     else if (p_t1t->state != RW_T1T_STATE_IDLE)
551     {
552         rw_t1t_process_error ();
553     }
554 }
555 
556 
557 /*******************************************************************************
558 **
559 ** Function         rw_t1t_process_frame_error
560 **
561 ** Description      Process frame crc error
562 **
563 ** Returns          none
564 **
565 *******************************************************************************/
rw_t1t_process_frame_error(void)566 static void rw_t1t_process_frame_error (void)
567 {
568 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
569     /* Update stats */
570     rw_main_update_crc_error_stats ();
571 #endif  /* RW_STATS_INCLUDED */
572 
573     /* Process the error */
574     rw_t1t_process_error ();
575 }
576 
577 /*******************************************************************************
578 **
579 ** Function         rw_t1t_process_error
580 **
581 ** Description      process timeout event
582 **
583 ** Returns          none
584 **
585 *******************************************************************************/
rw_t1t_process_error(void)586 static void rw_t1t_process_error (void)
587 {
588     tRW_READ_DATA           evt_data;
589     tRW_EVENT               rw_event;
590     BT_HDR                  *p_cmd_buf;
591     tRW_T1T_CB              *p_t1t  = &rw_cb.tcb.t1t;
592     tT1T_CMD_RSP_INFO       *p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *) rw_cb.tcb.t1t.p_cmd_rsp_info;
593     tRW_DETECT_NDEF_DATA    ndef_data;
594 
595     RW_TRACE_DEBUG1 ("rw_t1t_process_error () State: %u", p_t1t->state);
596 
597     /* Retry sending command if retry-count < max */
598     if (rw_cb.cur_retry < RW_MAX_RETRIES)
599     {
600         /* retry sending the command */
601         rw_cb.cur_retry++;
602 
603         RW_TRACE_DEBUG2 ("T1T retransmission attempt %i of %i", rw_cb.cur_retry, RW_MAX_RETRIES);
604 
605         /* allocate a new buffer for message */
606         if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL)
607         {
608             memcpy (p_cmd_buf, p_t1t->p_cur_cmd_buf, sizeof (BT_HDR) + p_t1t->p_cur_cmd_buf->offset + p_t1t->p_cur_cmd_buf->len);
609 
610 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
611             /* Update stats */
612             rw_main_update_tx_stats (p_cmd_buf->len, TRUE);
613 #endif  /* RW_STATS_INCLUDED */
614 
615             if (NFC_SendData (NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK)
616             {
617                 /* Start timer for waiting for response */
618                 nfc_start_quick_timer (&p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE,
619                                        (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC)/1000);
620 
621                 return;
622             }
623         }
624     }
625     else
626     {
627     /* we might get response later to all or some of the retrasnmission
628      * of the current command, update previous command response information */
629         RW_TRACE_DEBUG1 ("T1T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES);
630         p_t1t->prev_cmd_rsp_info.addr          = ((p_cmd_rsp_info->opcode != T1T_CMD_RALL) && (p_cmd_rsp_info->opcode != T1T_CMD_RID))? p_t1t->addr:0;
631         p_t1t->prev_cmd_rsp_info.rsp_len       = p_cmd_rsp_info->rsp_len;
632         p_t1t->prev_cmd_rsp_info.op_code       = p_cmd_rsp_info->opcode;
633         p_t1t->prev_cmd_rsp_info.pend_retx_rsp = RW_MAX_RETRIES;
634     }
635 
636 #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
637     /* update failure count */
638     rw_main_update_fail_stats ();
639 #endif  /* RW_STATS_INCLUDED */
640 
641     rw_event        = rw_t1t_info_to_event (p_cmd_rsp_info);
642     if (p_t1t->state != RW_T1T_STATE_NOT_ACTIVATED)
643         rw_t1t_handle_op_complete ();
644 
645     evt_data.status = NFC_STATUS_TIMEOUT;
646     if (rw_event == RW_T2T_NDEF_DETECT_EVT)
647     {
648         ndef_data.status    = evt_data.status;
649         ndef_data.protocol  = NFC_PROTOCOL_T1T;
650         ndef_data.flags     = RW_NDEF_FL_UNKNOWN;
651         ndef_data.max_size  = 0;
652         ndef_data.cur_size  = 0;
653         (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &ndef_data);
654     }
655     else
656     {
657         evt_data.p_data = NULL;
658         (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data);
659     }
660 }
661 
662 /*****************************************************************************
663 **
664 ** Function         rw_t1t_handle_presence_check_rsp
665 **
666 ** Description      Handle response to presence check
667 **
668 ** Returns          Nothing
669 **
670 *****************************************************************************/
rw_t1t_handle_presence_check_rsp(tNFC_STATUS status)671 void rw_t1t_handle_presence_check_rsp (tNFC_STATUS status)
672 {
673     tRW_READ_DATA   evt_data;
674 
675     /* Notify, Tag is present or not */
676     evt_data.status = status;
677     rw_t1t_handle_op_complete ();
678 
679     (*(rw_cb.p_cback)) (RW_T1T_PRESENCE_CHECK_EVT, (tRW_DATA *) &evt_data);
680 }
681 
682 /*****************************************************************************
683 **
684 ** Function         rw_t1t_handle_op_complete
685 **
686 ** Description      Reset to IDLE state
687 **
688 ** Returns          Nothing
689 **
690 *****************************************************************************/
rw_t1t_handle_op_complete(void)691 void rw_t1t_handle_op_complete (void)
692 {
693     tRW_T1T_CB      *p_t1t  = &rw_cb.tcb.t1t;
694 
695     p_t1t->state    = RW_T1T_STATE_IDLE;
696 #if (defined (RW_NDEF_INCLUDED) && (RW_NDEF_INCLUDED == TRUE))
697     if (p_t1t->state != RW_T1T_STATE_READ_NDEF)
698     {
699         p_t1t->b_update = FALSE;
700         p_t1t->b_rseg   = FALSE;
701     }
702     p_t1t->substate = RW_T1T_SUBSTATE_NONE;
703 #endif
704     return;
705 }
706 
707 /*****************************************************************************
708 **
709 ** Function         RW_T1tPresenceCheck
710 **
711 ** Description
712 **      Check if the tag is still in the field.
713 **
714 **      The RW_T1T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
715 **      or non-presence.
716 **
717 ** Returns
718 **      NFC_STATUS_OK, if raw data frame sent
719 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
720 **      NFC_STATUS_FAILED: other error
721 **
722 *****************************************************************************/
RW_T1tPresenceCheck(void)723 tNFC_STATUS RW_T1tPresenceCheck (void)
724 {
725     tNFC_STATUS retval = NFC_STATUS_OK;
726     tRW_DATA evt_data;
727     tRW_CB *p_rw_cb = &rw_cb;
728 
729     RW_TRACE_API0 ("RW_T1tPresenceCheck");
730 
731     /* If RW_SelectTagType was not called (no conn_callback) return failure */
732     if (!p_rw_cb->p_cback)
733     {
734         retval = NFC_STATUS_FAILED;
735     }
736     /* If we are not activated, then RW_T1T_PRESENCE_CHECK_EVT status=FAIL */
737     else if (p_rw_cb->tcb.t1t.state == RW_T1T_STATE_NOT_ACTIVATED)
738     {
739         evt_data.status = NFC_STATUS_FAILED;
740         (*p_rw_cb->p_cback) (RW_T1T_PRESENCE_CHECK_EVT, &evt_data);
741     }
742     /* If command is pending, assume tag is still present */
743     else if (p_rw_cb->tcb.t1t.state != RW_T1T_STATE_IDLE)
744     {
745         evt_data.status = NFC_STATUS_OK;
746         (*p_rw_cb->p_cback) (RW_T1T_PRESENCE_CHECK_EVT, &evt_data);
747     }
748     else
749     {
750         /* IDLE state: send a RID command to the tag to see if it responds */
751         if((retval = rw_t1t_send_static_cmd (T1T_CMD_RID, 0, 0))== NFC_STATUS_OK)
752         {
753             p_rw_cb->tcb.t1t.state = RW_T1T_STATE_CHECK_PRESENCE;
754         }
755     }
756 
757     return (retval);
758 }
759 
760 /*****************************************************************************
761 **
762 ** Function         RW_T1tRid
763 **
764 ** Description
765 **      This function sends a RID command for Reader/Writer mode.
766 **
767 ** Returns
768 **      NFC_STATUS_OK, if raw data frame sent
769 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
770 **      NFC_STATUS_FAILED: other error
771 **
772 *****************************************************************************/
RW_T1tRid(void)773 tNFC_STATUS RW_T1tRid (void)
774 {
775     tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
776     tNFC_STATUS status  = NFC_STATUS_FAILED;
777 
778     RW_TRACE_API0 ("RW_T1tRid");
779 
780     if (p_t1t->state != RW_T1T_STATE_IDLE)
781     {
782         RW_TRACE_WARNING1 ("RW_T1tRid - Busy - State: %u", p_t1t->state);
783         return (NFC_STATUS_BUSY);
784     }
785 
786     /* send a RID command */
787     if((status = rw_t1t_send_static_cmd (T1T_CMD_RID, 0, 0))== NFC_STATUS_OK)
788     {
789         p_t1t->state = RW_T1T_STATE_READ;
790     }
791 
792     return (status);
793 }
794 
795 /*******************************************************************************
796 **
797 ** Function         RW_T1tReadAll
798 **
799 ** Description      This function sends a RALL command for Reader/Writer mode.
800 **
801 ** Returns          tNFC_STATUS
802 **
803 *******************************************************************************/
RW_T1tReadAll(void)804 tNFC_STATUS RW_T1tReadAll (void)
805 {
806     tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
807     tNFC_STATUS status  = NFC_STATUS_FAILED;
808 
809     RW_TRACE_API0 ("RW_T1tReadAll");
810 
811     if (p_t1t->state != RW_T1T_STATE_IDLE)
812     {
813         RW_TRACE_WARNING1 ("RW_T1tReadAll - Busy - State: %u", p_t1t->state);
814         return (NFC_STATUS_BUSY);
815     }
816 
817     /* send RALL command */
818     if ((status = rw_t1t_send_static_cmd (T1T_CMD_RALL, 0, 0)) == NFC_STATUS_OK)
819     {
820         p_t1t->state = RW_T1T_STATE_READ;
821     }
822 
823     return status;
824 }
825 
826 /*******************************************************************************
827 **
828 ** Function         RW_T1tRead
829 **
830 ** Description      This function sends a READ command for Reader/Writer mode.
831 **
832 ** Returns          tNFC_STATUS
833 **
834 *******************************************************************************/
RW_T1tRead(UINT8 block,UINT8 byte)835 tNFC_STATUS RW_T1tRead (UINT8 block, UINT8 byte)
836 {
837     tNFC_STATUS status  = NFC_STATUS_FAILED;
838     tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
839     UINT8       addr;
840 
841     if (p_t1t->state != RW_T1T_STATE_IDLE)
842     {
843         RW_TRACE_WARNING1 ("RW_T1tRead - Busy - State: %u", p_t1t->state);
844         return (NFC_STATUS_BUSY);
845     }
846 
847     /* send READ command */
848     RW_T1T_BLD_ADD ((addr), (block), (byte));
849     if ((status = rw_t1t_send_static_cmd (T1T_CMD_READ, addr, 0)) == NFC_STATUS_OK)
850     {
851         p_t1t->state = RW_T1T_STATE_READ;
852     }
853     return status;
854 }
855 
856 /*******************************************************************************
857 **
858 ** Function         RW_T1tWriteErase
859 **
860 ** Description      This function sends a WRITE-E command for Reader/Writer mode.
861 **
862 ** Returns          tNFC_STATUS
863 **
864 *******************************************************************************/
RW_T1tWriteErase(UINT8 block,UINT8 byte,UINT8 new_byte)865 tNFC_STATUS RW_T1tWriteErase (UINT8 block, UINT8 byte, UINT8 new_byte)
866 {
867     tNFC_STATUS status  = NFC_STATUS_FAILED;
868     tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
869     UINT8       addr;
870 
871     if (p_t1t->state != RW_T1T_STATE_IDLE)
872     {
873         RW_TRACE_WARNING1 ("RW_T1tWriteErase - Busy - State: %u", p_t1t->state);
874         return (NFC_STATUS_BUSY);
875     }
876     if (  (p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY)
877         &&(block != T1T_CC_BLOCK)
878         &&(byte  != T1T_CC_RWA_OFFSET)  )
879     {
880         RW_TRACE_ERROR0 ("RW_T1tWriteErase - Tag is in Read only state");
881         return (NFC_STATUS_REFUSED);
882     }
883     if (  (block >= T1T_STATIC_BLOCKS)
884         ||(byte  >= T1T_BLOCK_SIZE   )  )
885     {
886         RW_TRACE_ERROR2 ("RW_T1tWriteErase - Invalid Block/byte: %u / %u", block, byte);
887         return (NFC_STATUS_REFUSED);
888     }
889     if(  (block == T1T_UID_BLOCK)
890        ||(block == T1T_RES_BLOCK)  )
891     {
892         RW_TRACE_WARNING1 ("RW_T1tWriteErase - Cannot write to Locked block: %u", block);
893         return (NFC_STATUS_REFUSED);
894     }
895     /* send WRITE-E command */
896     RW_T1T_BLD_ADD ((addr), (block), (byte));
897     if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_E, addr, new_byte)) == NFC_STATUS_OK)
898     {
899         p_t1t->state = RW_T1T_STATE_WRITE;
900         if (block < T1T_BLOCKS_PER_SEGMENT)
901         {
902             p_t1t->b_update = FALSE;
903             p_t1t->b_rseg   = FALSE;
904         }
905     }
906     return status;
907 }
908 
909 /*******************************************************************************
910 **
911 ** Function         RW_T1tWriteNoErase
912 **
913 ** Description      This function sends a WRITE-NE command for Reader/Writer mode.
914 **
915 ** Returns          tNFC_STATUS
916 **
917 *******************************************************************************/
RW_T1tWriteNoErase(UINT8 block,UINT8 byte,UINT8 new_byte)918 tNFC_STATUS RW_T1tWriteNoErase (UINT8 block, UINT8 byte, UINT8 new_byte)
919 {
920     tNFC_STATUS status  = NFC_STATUS_FAILED;
921     tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
922     UINT8       addr;
923 
924     if (p_t1t->state != RW_T1T_STATE_IDLE)
925     {
926         RW_TRACE_WARNING1 ("RW_T1tWriteNoErase - Busy - State: %u", p_t1t->state);
927         return (NFC_STATUS_BUSY);
928     }
929     if (  (p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY)
930         &&(block != T1T_CC_BLOCK)
931         &&(byte  != T1T_CC_RWA_OFFSET)  )
932     {
933         RW_TRACE_ERROR0 ("RW_T1tWriteErase - Tag is in Read only state");
934         return (NFC_STATUS_REFUSED);
935     }
936     if (  (block >= T1T_STATIC_BLOCKS)
937         ||(byte  >= T1T_BLOCK_SIZE   )  )
938     {
939         RW_TRACE_ERROR2 ("RW_T1tWriteErase - Invalid Block/byte: %u / %u", block, byte);
940         return (NFC_STATUS_REFUSED);
941     }
942     if(  (block == T1T_UID_BLOCK)
943        ||(block == T1T_RES_BLOCK)  )
944     {
945         RW_TRACE_WARNING1 ("RW_T1tWriteNoErase - Cannot write to Locked block: %u", block);
946         return (NFC_STATUS_REFUSED);
947     }
948     /* send WRITE-NE command */
949     RW_T1T_BLD_ADD ((addr), (block), (byte));
950     if ((status = rw_t1t_send_static_cmd (T1T_CMD_WRITE_NE, addr, new_byte)) == NFC_STATUS_OK)
951     {
952         p_t1t->state = RW_T1T_STATE_WRITE;
953         if (block < T1T_BLOCKS_PER_SEGMENT)
954         {
955             p_t1t->b_update = FALSE;
956             p_t1t->b_rseg   = FALSE;
957         }
958     }
959     return status;
960 }
961 
962 /*******************************************************************************
963 **
964 ** Function         RW_T1tReadSeg
965 **
966 ** Description      This function sends a RSEG command for Reader/Writer mode.
967 **
968 ** Returns          tNFC_STATUS
969 **
970 *******************************************************************************/
RW_T1tReadSeg(UINT8 segment)971 tNFC_STATUS RW_T1tReadSeg (UINT8 segment)
972 {
973     tNFC_STATUS status  = NFC_STATUS_FAILED;
974     tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;
975     UINT8       adds;
976 
977     if (p_t1t->state != RW_T1T_STATE_IDLE)
978     {
979         RW_TRACE_WARNING1 ("RW_T1tReadSeg - Busy - State: %u", p_t1t->state);
980         return (NFC_STATUS_BUSY);
981     }
982     if (segment >=  T1T_MAX_SEGMENTS)
983     {
984         RW_TRACE_ERROR1 ("RW_T1tReadSeg - Invalid Segment: %u", segment);
985         return (NFC_STATUS_REFUSED);
986     }
987     if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0)
988     {
989         /* send RSEG command */
990         RW_T1T_BLD_ADDS ((adds), (segment));
991         if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_RSEG, adds, NULL)) == NFC_STATUS_OK)
992         {
993             p_t1t->state = RW_T1T_STATE_READ;
994         }
995     }
996     return status;
997 }
998 
999 /*******************************************************************************
1000 **
1001 ** Function         RW_T1tRead8
1002 **
1003 ** Description      This function sends a READ8 command for Reader/Writer mode.
1004 **
1005 ** Returns          tNFC_STATUS
1006 **
1007 *******************************************************************************/
RW_T1tRead8(UINT8 block)1008 tNFC_STATUS RW_T1tRead8 (UINT8 block)
1009 {
1010     tNFC_STATUS status = NFC_STATUS_FAILED;
1011     tRW_T1T_CB  *p_t1t= &rw_cb.tcb.t1t;
1012 
1013     if (p_t1t->state != RW_T1T_STATE_IDLE)
1014     {
1015         RW_TRACE_WARNING1 ("RW_T1tRead8 - Busy - State: %u", p_t1t->state);
1016         return (NFC_STATUS_BUSY);
1017     }
1018 
1019     if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN)
1020     {
1021         /* send READ8 command */
1022         if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_READ8, block, NULL)) == NFC_STATUS_OK)
1023         {
1024             p_t1t->state = RW_T1T_STATE_READ;
1025         }
1026     }
1027     return status;
1028 }
1029 
1030 /*******************************************************************************
1031 **
1032 ** Function         RW_T1tWriteErase8
1033 **
1034 ** Description      This function sends a WRITE-E8 command for Reader/Writer mode.
1035 **
1036 ** Returns          tNFC_STATUS
1037 **
1038 *******************************************************************************/
RW_T1tWriteErase8(UINT8 block,UINT8 * p_new_dat)1039 tNFC_STATUS RW_T1tWriteErase8 (UINT8 block, UINT8 *p_new_dat)
1040 {
1041     tRW_T1T_CB  *p_t1t= &rw_cb.tcb.t1t;
1042     tNFC_STATUS status = NFC_STATUS_FAILED;
1043 
1044     if (p_t1t->state != RW_T1T_STATE_IDLE)
1045     {
1046         RW_TRACE_WARNING1 ("RW_T1tWriteErase8 - Busy - State: %u", p_t1t->state);
1047         return (NFC_STATUS_BUSY);
1048     }
1049 
1050     if (  (p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY)
1051         &&(block != T1T_CC_BLOCK)  )
1052     {
1053         RW_TRACE_ERROR0 ("RW_T1tWriteErase8 - Tag is in Read only state");
1054         return (NFC_STATUS_REFUSED);
1055     }
1056 
1057     if(  (block == T1T_UID_BLOCK)
1058        ||(block == T1T_RES_BLOCK)  )
1059     {
1060         RW_TRACE_WARNING1 ("RW_T1tWriteErase8 - Cannot write to Locked block: %u", block);
1061         return (NFC_STATUS_REFUSED);
1062     }
1063 
1064     if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN)
1065     {
1066         /* send WRITE-E8 command */
1067         if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_WRITE_E8, block, p_new_dat)) == NFC_STATUS_OK)
1068         {
1069             p_t1t->state = RW_T1T_STATE_WRITE;
1070             if (block < T1T_BLOCKS_PER_SEGMENT)
1071             {
1072                 p_t1t->b_update = FALSE;
1073                 p_t1t->b_rseg   = FALSE;
1074             }
1075         }
1076     }
1077     return status;
1078 }
1079 
1080 /*******************************************************************************
1081 **
1082 ** Function         RW_T1tWriteNoErase8
1083 **
1084 ** Description      This function sends a WRITE-NE8 command for Reader/Writer mode.
1085 **
1086 ** Returns          tNFC_STATUS
1087 **
1088 *******************************************************************************/
RW_T1tWriteNoErase8(UINT8 block,UINT8 * p_new_dat)1089 tNFC_STATUS RW_T1tWriteNoErase8 (UINT8 block, UINT8 *p_new_dat)
1090 {
1091     tNFC_STATUS status = NFC_STATUS_FAILED;
1092     tRW_T1T_CB  *p_t1t= &rw_cb.tcb.t1t;
1093 
1094     if (p_t1t->state != RW_T1T_STATE_IDLE)
1095     {
1096         RW_TRACE_WARNING1 ("RW_T1tWriteNoErase8 - Busy - State: %u", p_t1t->state);
1097         return (NFC_STATUS_BUSY);
1098     }
1099 
1100     if (  (p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY)
1101         &&(block != T1T_CC_BLOCK)  )
1102     {
1103         RW_TRACE_ERROR0 ("RW_T1tWriteNoErase8 - Tag is in Read only state");
1104         return (NFC_STATUS_REFUSED);
1105     }
1106 
1107     if(  (block == T1T_UID_BLOCK)
1108        ||(block == T1T_RES_BLOCK)  )
1109     {
1110         RW_TRACE_WARNING1 ("RW_T1tWriteNoErase8 - Cannot write to Locked block: %u", block);
1111         return (NFC_STATUS_REFUSED);
1112     }
1113 
1114     if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN)
1115     {
1116         /* send WRITE-NE command */
1117         if ((status = rw_t1t_send_dyn_cmd (T1T_CMD_WRITE_NE8, block, p_new_dat)) == NFC_STATUS_OK)
1118         {
1119             p_t1t->state    = RW_T1T_STATE_WRITE;
1120             if (block < T1T_BLOCKS_PER_SEGMENT)
1121             {
1122                 p_t1t->b_update = FALSE;
1123                 p_t1t->b_rseg   = FALSE;
1124             }
1125         }
1126     }
1127     return status;
1128 }
1129 
1130 #if (BT_TRACE_VERBOSE == TRUE)
1131 /*******************************************************************************
1132 **
1133 ** Function         rw_t1t_get_state_name
1134 **
1135 ** Description      This function returns the state name.
1136 **
1137 ** NOTE             conditionally compiled to save memory.
1138 **
1139 ** Returns          pointer to the name
1140 **
1141 *******************************************************************************/
rw_t1t_get_state_name(UINT8 state)1142 static char *rw_t1t_get_state_name (UINT8 state)
1143 {
1144     switch (state)
1145     {
1146     case RW_T1T_STATE_IDLE:
1147         return ("IDLE");
1148     case RW_T1T_STATE_NOT_ACTIVATED:
1149         return ("NOT_ACTIVATED");
1150     case RW_T1T_STATE_READ:
1151         return ("APP_READ");
1152     case RW_T1T_STATE_WRITE:
1153         return ("APP_WRITE");
1154     case RW_T1T_STATE_TLV_DETECT:
1155         return ("TLV_DETECTION");
1156     case RW_T1T_STATE_READ_NDEF:
1157         return ("READING_NDEF");
1158     case RW_T1T_STATE_WRITE_NDEF:
1159         return ("WRITING_NDEF");
1160     case RW_T1T_STATE_SET_TAG_RO:
1161         return ("SET_TAG_RO");
1162     case RW_T1T_STATE_CHECK_PRESENCE:
1163         return ("CHECK_PRESENCE");
1164     case RW_T1T_STATE_FORMAT_TAG:
1165         return ("FORMAT_TAG");
1166     default:
1167         return ("???? UNKNOWN STATE");
1168     }
1169 }
1170 
1171 #endif /* (BT_TRACE_VERBOSE == TRUE) */
1172 
1173 #endif /* (NFC_INCLUDED == TRUE) */
1174