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