rw_t2t.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 2 tag in Reader/Writer
22 *  mode.
23 *
24 ******************************************************************************/
25#include <string.h>
26#include "nfc_target.h"
27#include "bt_types.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/* Static local functions */
38static void rw_t2t_proc_data (UINT8 conn_id, tNFC_CONN_EVT event, BT_HDR *p_pkt);
39static tNFC_STATUS rw_t2t_send_cmd (UINT8 opcode, UINT8 *p_dat);
40static void rw_t2t_process_error (void);
41static void rw_t2t_process_frame_error (void);
42static void rw_t2t_handle_presence_check_rsp (tNFC_STATUS status);
43static void rw_t2t_resume_op (void);
44
45#if (BT_TRACE_VERBOSE == TRUE)
46static char *rw_t2t_get_state_name (UINT8 state);
47static char *rw_t2t_get_substate_name (UINT8 substate);
48#endif
49
50/*******************************************************************************
51**
52** Function         rw_t2t_proc_data
53**
54** Description      This function handles data evt received from NFC Controller.
55**
56** Returns          none
57**
58*******************************************************************************/
59static void rw_t2t_proc_data (UINT8 conn_id, tNFC_CONN_EVT event, BT_HDR *p_pkt)
60{
61    tRW_EVENT               rw_event    = RW_RAW_FRAME_EVT;
62    tRW_T2T_CB              *p_t2t      = &rw_cb.tcb.t2t;
63    BOOLEAN                 b_notify    = TRUE;
64    BOOLEAN                 b_release   = TRUE;
65    UINT8                   *p;
66    tRW_READ_DATA           evt_data = {0};
67    tT2T_CMD_RSP_INFO       *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info;
68    tRW_DETECT_NDEF_DATA    ndef_data;
69
70    if (  (p_t2t->state == RW_T2T_STATE_IDLE)
71        ||(p_cmd_rsp_info == NULL)  )
72    {
73        RW_TRACE_DEBUG2 ("rw_t2t_proc_data - Raw frame event! state: IDLE, conn_id: %u  event: %u",
74                           conn_id, event);
75
76        evt_data.status = NFC_STATUS_OK;
77        evt_data.p_data = p_pkt;
78        (*rw_cb.p_cback) (RW_T2T_RAW_FRAME_EVT, (tRW_DATA *)&evt_data);
79        return;
80    }
81#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
82    /* Update rx stats */
83    rw_main_update_rx_stats (p_pkt->len);
84#endif
85    /* Stop timer as response is received */
86    nfc_stop_quick_timer (&p_t2t->t2_timer);
87
88    RW_TRACE_EVENT2 ("RW RECV [%s]:0x%x RSP", t2t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode);
89
90    if (  (p_pkt->len != p_cmd_rsp_info->rsp_len)
91        &&(p_pkt->len != p_cmd_rsp_info->nack_rsp_len)
92        &&(p_t2t->substate != RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR)  )
93    {
94#if (BT_TRACE_VERBOSE == TRUE)
95        RW_TRACE_ERROR1 ("T2T Frame error. state=%s ", rw_t2t_get_state_name (p_t2t->state));
96#else
97        RW_TRACE_ERROR1 ("T2T Frame error. state=0x%02X command=0x%02X ", p_t2t->state);
98#endif
99        /* Retrasmit the last sent command if retry-count < max retry */
100        rw_t2t_process_frame_error ();
101        GKI_freebuf (p_pkt);
102        return;
103    }
104    rw_cb.cur_retry = 0;
105
106    /* Assume the data is just the response byte sequence */
107    p = (UINT8 *) (p_pkt + 1) + p_pkt->offset;
108
109
110    RW_TRACE_EVENT5 ("rw_t2t_proc_data State: %u  conn_id: %u  event: %u  len: %u  data[0]: 0x%02x",
111                      p_t2t->state, conn_id, event, p_pkt->len, *p);
112
113    evt_data.p_data     = NULL;
114
115    if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT)
116    {
117        /* The select process happens in two steps */
118        if ((*p & 0x0f) == T2T_RSP_ACK)
119        {
120            if (rw_t2t_sector_change (p_t2t->select_sector) == NFC_STATUS_OK)
121                b_notify = FALSE;
122            else
123                evt_data.status = NFC_STATUS_FAILED;
124        }
125        else
126        {
127            evt_data.status = NFC_STATUS_FAILED;
128        }
129    }
130    else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR)
131    {
132        evt_data.status = NFC_STATUS_FAILED;
133    }
134    else if (p_pkt->len == p_cmd_rsp_info->rsp_len)
135    {
136        /* If the response length indicates positive response or cannot be known from length then assume success */
137        evt_data.status  = NFC_STATUS_OK;
138
139        /* The response data depends on what the current operation was */
140        switch (p_t2t->state)
141        {
142        case RW_T2T_STATE_CHECK_PRESENCE:
143            b_notify = FALSE;
144            rw_t2t_handle_presence_check_rsp (NFC_STATUS_OK);
145            break;
146
147        case RW_T2T_STATE_READ:
148            evt_data.p_data = p_pkt;
149            b_release = FALSE;
150            if (p_t2t->block_read == 0)
151            {
152                p_t2t->b_read_hdr = TRUE;
153                memcpy (p_t2t->tag_hdr,  p, T2T_READ_DATA_LEN);
154
155                /* On Ultralight - C tag, if CC is corrupt, correct it */
156                if (  (p_t2t->tag_hdr[0] == TAG_MIFARE_MID)
157                    &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] >= T2T_INVALID_CC_TMS_VAL0)
158                    &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] <= T2T_INVALID_CC_TMS_VAL1)  )
159                {
160                    p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] = T2T_CC2_TMS_MULC;
161                }
162            }
163            break;
164
165        case RW_T2T_STATE_WRITE:
166            /* Check positive or negative acknowledgment */
167            if ((*p & 0x0f) != T2T_RSP_ACK)
168                evt_data.status = NFC_STATUS_FAILED;
169            break;
170
171        default:
172            /* NDEF/other Tlv Operation/Format Tag/Config Tag as Read only
173             * Check if Positive response to previous write command */
174            if (  (p_cmd_rsp_info->opcode == T2T_CMD_WRITE)
175                &&((*p & 0x0f) != T2T_RSP_ACK)  )
176                evt_data.status = NFC_STATUS_FAILED;
177            else
178            {
179                b_notify = FALSE;
180                rw_t2t_handle_rsp (p);
181            }
182            break;
183        }
184    }
185    else
186    {
187        evt_data.p_data = p_pkt;
188        if (p_t2t->state == RW_T2T_STATE_READ)
189            b_release = FALSE;
190
191        /* Negative response to the command sent */
192        evt_data.status = NFC_STATUS_FAILED;
193    }
194
195    if (b_notify)
196    {
197        rw_event = rw_t2t_info_to_event (p_cmd_rsp_info);
198        /* Move back to idle state */
199        rw_t2t_handle_op_complete ();
200        if (rw_event == RW_T2T_NDEF_DETECT_EVT)
201        {
202            ndef_data.status    = evt_data.status;
203            ndef_data.protocol  = NFC_PROTOCOL_T2T;
204            ndef_data.flags     = RW_NDEF_FL_UNKNOWN;
205            ndef_data.max_size  = 0;
206            ndef_data.cur_size  = 0;
207            (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &ndef_data);
208        }
209        else
210            (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data);
211    }
212
213    if (b_release)
214        GKI_freebuf (p_pkt);
215}
216
217/*******************************************************************************
218**
219** Function         rw_t2t_conn_cback
220**
221** Description      This callback function receives events/data from NFCC.
222**
223** Returns          none
224**
225*******************************************************************************/
226void rw_t2t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
227{
228    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
229    tRW_READ_DATA       evt_data;
230
231    RW_TRACE_DEBUG2 ("rw_t2t_conn_cback: conn_id=%i, evt=%i", conn_id, event);
232    /* Only handle static conn_id */
233    if (conn_id != NFC_RF_CONN_ID)
234    {
235        return;
236    }
237
238    switch (event)
239    {
240    case NFC_CONN_CREATE_CEVT:
241    case NFC_CONN_CLOSE_CEVT:
242        break;
243
244    case NFC_DEACTIVATE_CEVT:
245#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
246        /* Display stats */
247        rw_main_log_stats ();
248#endif
249        /* Stop t2t timer (if started) */
250        nfc_stop_quick_timer (&p_t2t->t2_timer);
251
252        /* Free cmd buf for retransmissions */
253        if (p_t2t->p_cur_cmd_buf)
254        {
255            GKI_freebuf (p_t2t->p_cur_cmd_buf);
256            p_t2t->p_cur_cmd_buf = NULL;
257        }
258        /* Free cmd buf used to hold command before sector change */
259        if (p_t2t->p_sec_cmd_buf)
260        {
261            GKI_freebuf (p_t2t->p_sec_cmd_buf);
262            p_t2t->p_sec_cmd_buf = NULL;
263        }
264
265        p_t2t->state = RW_T2T_STATE_NOT_ACTIVATED;
266        NFC_SetStaticRfCback (NULL);
267        break;
268
269    case NFC_DATA_CEVT:
270        if (  (p_data != NULL)
271            &&(p_data->data.status == NFC_STATUS_OK)  )
272        {
273            rw_t2t_proc_data (conn_id, event, (BT_HDR *) (p_data->data.p_data));
274            break;
275        }
276        /* Data event with error status...fall through to NFC_ERROR_CEVT case */
277
278    case NFC_ERROR_CEVT:
279        if (  (p_t2t->state == RW_T2T_STATE_NOT_ACTIVATED)
280            ||(p_t2t->state == RW_T2T_STATE_IDLE)  )
281        {
282#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
283            rw_main_update_trans_error_stats ();
284#endif  /* RW_STATS_INCLUDED */
285            if (event == NFC_ERROR_CEVT)
286                evt_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
287            else if (p_data)
288                evt_data.status = p_data->status;
289            else
290                evt_data.status = NFC_STATUS_FAILED;
291
292            evt_data.p_data = NULL;
293            (*rw_cb.p_cback) (RW_T2T_INTF_ERROR_EVT, (tRW_DATA *) &evt_data);
294            break;
295        }
296        nfc_stop_quick_timer (&p_t2t->t2_timer);
297#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
298        rw_main_update_trans_error_stats ();
299#endif
300        if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE)
301        {
302            rw_t2t_handle_presence_check_rsp (NFC_STATUS_FAILED);
303        }
304        else
305        {
306            rw_t2t_process_error ();
307        }
308        break;
309
310    default:
311        break;
312
313    }
314}
315
316/*******************************************************************************
317**
318** Function         rw_t2t_send_cmd
319**
320** Description      This function composes a Type 2 Tag command and send it via
321**                  NCI to NFCC.
322**
323** Returns          NFC_STATUS_OK if the command is successfuly sent to NCI
324**                  otherwise, error status
325**
326*******************************************************************************/
327tNFC_STATUS rw_t2t_send_cmd (UINT8 opcode, UINT8 *p_dat)
328{
329    tNFC_STATUS             status  = NFC_STATUS_FAILED;
330    tRW_T2T_CB              *p_t2t  = &rw_cb.tcb.t2t;
331    const tT2T_CMD_RSP_INFO *p_cmd_rsp_info = t2t_cmd_to_rsp_info (opcode);
332    BT_HDR                  *p_data;
333    UINT8                   *p;
334
335    if (p_cmd_rsp_info)
336    {
337        /* a valid opcode for RW */
338        p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
339        if (p_data)
340        {
341            p_t2t->p_cmd_rsp_info   = (tT2T_CMD_RSP_INFO *) p_cmd_rsp_info;
342            p_data->offset  = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
343            p               = (UINT8 *) (p_data + 1) + p_data->offset;
344
345            UINT8_TO_STREAM (p, opcode);
346
347            if (p_dat)
348            {
349                ARRAY_TO_STREAM (p, p_dat, (p_cmd_rsp_info->cmd_len - 1));
350            }
351
352            p_data->len     = p_cmd_rsp_info->cmd_len;
353
354            /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */
355            rw_cb.cur_retry = 0;
356            memcpy (p_t2t->p_cur_cmd_buf, p_data, sizeof (BT_HDR) + p_data->offset + p_data->len);
357
358#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
359            /* Update stats */
360            rw_main_update_tx_stats (p_data->len, FALSE);
361#endif
362            RW_TRACE_EVENT2 ("RW SENT [%s]:0x%x CMD", t2t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode);
363
364            if ((status = NFC_SendData (NFC_RF_CONN_ID, p_data)) == NFC_STATUS_OK)
365            {
366                nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
367                       (RW_T2T_TOUT_RESP*QUICK_TIMER_TICKS_PER_SEC) / 1000);
368            }
369            else
370            {
371#if (BT_TRACE_VERBOSE == TRUE)
372                RW_TRACE_ERROR2 ("T2T NFC Send data failed. state=%s substate=%s ", rw_t2t_get_state_name (p_t2t->state), rw_t2t_get_substate_name (p_t2t->substate));
373#else
374                RW_TRACE_ERROR2 ("T2T NFC Send data failed. state=0x%02X substate=0x%02X ", p_t2t->state, p_t2t->substate);
375#endif
376            }
377        }
378        else
379        {
380            status = NFC_STATUS_NO_BUFFERS;
381        }
382    }
383    return status;
384}
385
386/*******************************************************************************
387**
388** Function         rw_t2t_process_timeout
389**
390** Description      handles timeout event
391**
392** Returns          none
393**
394*******************************************************************************/
395void rw_t2t_process_timeout (TIMER_LIST_ENT *p_tle)
396{
397    tRW_READ_DATA       evt_data;
398    tRW_T2T_CB          *p_t2t          = &rw_cb.tcb.t2t;
399
400    if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE)
401    {
402        /* Move back to idle state */
403        rw_t2t_handle_presence_check_rsp (NFC_STATUS_FAILED);
404        return;
405    }
406
407    if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR)
408    {
409        p_t2t->sector   = p_t2t->select_sector;
410        /* Here timeout is an acknowledgment for successfull sector change */
411        if (p_t2t->state == RW_T2T_STATE_SELECT_SECTOR)
412        {
413            /* Notify that select sector op is successfull */
414            rw_t2t_handle_op_complete ();
415            evt_data.status = NFC_STATUS_OK;
416            evt_data.p_data = NULL;
417            (*rw_cb.p_cback) (RW_T2T_SELECT_CPLT_EVT, (tRW_DATA *) &evt_data);
418        }
419        else
420        {
421            /* Resume operation from where we stopped before sector change */
422            rw_t2t_resume_op ();
423        }
424    }
425    else if (p_t2t->state != RW_T2T_STATE_IDLE)
426    {
427#if (BT_TRACE_VERBOSE == TRUE)
428        RW_TRACE_ERROR1 ("T2T timeout. state=%s ", rw_t2t_get_state_name (p_t2t->state));
429#else
430        RW_TRACE_ERROR1 ("T2T timeout. state=0x%02X ", p_t2t->state);
431#endif
432        /* Handle timeout error as no response to the command sent */
433        rw_t2t_process_error ();
434    }
435}
436
437/*******************************************************************************
438**
439** Function         rw_t2t_process_frame_error
440**
441** Description      handles frame crc error
442**
443** Returns          none
444**
445*******************************************************************************/
446static void rw_t2t_process_frame_error (void)
447{
448#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
449    /* Update stats */
450    rw_main_update_crc_error_stats ();
451#endif
452    /* Process the error */
453    rw_t2t_process_error ();
454}
455
456/*******************************************************************************
457**
458** Function         rw_t2t_process_error
459**
460** Description      Process error including Timeout, Frame error. This function
461**                  will retry atleast till RW_MAX_RETRIES before give up and
462**                  sending negative notification to upper layer
463**
464** Returns          none
465**
466*******************************************************************************/
467static void rw_t2t_process_error (void)
468{
469    tRW_READ_DATA           evt_data;
470    tRW_EVENT               rw_event;
471    BT_HDR                  *p_cmd_buf;
472    tRW_T2T_CB              *p_t2t          = &rw_cb.tcb.t2t;
473    tT2T_CMD_RSP_INFO       *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info;
474    tRW_DETECT_NDEF_DATA    ndef_data;
475
476    RW_TRACE_DEBUG1 ("rw_t2t_process_error () State: %u", p_t2t->state);
477
478    /* Retry sending command if retry-count < max */
479    if (rw_cb.cur_retry < RW_MAX_RETRIES)
480    {
481        /* retry sending the command */
482        rw_cb.cur_retry++;
483
484        RW_TRACE_DEBUG2 ("T2T retransmission attempt %i of %i", rw_cb.cur_retry, RW_MAX_RETRIES);
485
486        /* allocate a new buffer for message */
487        if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL)
488        {
489            memcpy (p_cmd_buf, p_t2t->p_cur_cmd_buf, sizeof (BT_HDR) + p_t2t->p_cur_cmd_buf->offset + p_t2t->p_cur_cmd_buf->len);
490#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
491            /* Update stats */
492            rw_main_update_tx_stats (p_cmd_buf->len, TRUE);
493#endif
494            if (NFC_SendData (NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK)
495            {
496                /* Start timer for waiting for response */
497                nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
498                                       (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
499
500                return;
501            }
502        }
503    }
504    else
505    {
506        RW_TRACE_DEBUG1 ("T2T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES);
507    }
508    rw_event = rw_t2t_info_to_event (p_cmd_rsp_info);
509#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
510    /* update failure count */
511    rw_main_update_fail_stats ();
512#endif
513    /* If not activated remain in non activated state, otherwise move to idle state */
514    if (p_t2t->state != RW_T2T_STATE_NOT_ACTIVATED)
515        rw_t2t_handle_op_complete ();
516
517    p_t2t->substate = RW_T2T_SUBSTATE_NONE;
518    evt_data.status = NFC_STATUS_TIMEOUT;
519    if (rw_event == RW_T2T_NDEF_DETECT_EVT)
520    {
521        ndef_data.status    = evt_data.status;
522        ndef_data.protocol  = NFC_PROTOCOL_T2T;
523        ndef_data.flags     = RW_NDEF_FL_UNKNOWN;
524        ndef_data.max_size  = 0;
525        ndef_data.cur_size  = 0;
526        (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &ndef_data);
527    }
528    else
529    {
530        evt_data.p_data = NULL;
531        (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data);
532    }
533}
534
535/*****************************************************************************
536**
537** Function         rw_t2t_handle_presence_check_rsp
538**
539** Description      Handle response to presence check
540**
541** Returns          Nothing
542**
543*****************************************************************************/
544void rw_t2t_handle_presence_check_rsp (tNFC_STATUS status)
545{
546    tRW_READ_DATA   evt_data;
547
548    /* Notify, Tag is present or not */
549    evt_data.status = status;
550    rw_t2t_handle_op_complete ();
551
552    (*rw_cb.p_cback) (RW_T2T_PRESENCE_CHECK_EVT, (tRW_DATA *) &evt_data);
553}
554
555/*******************************************************************************
556**
557** Function         rw_t2t_resume_op
558**
559** Description      This function will continue operation after moving to new
560**                  sector
561**
562** Returns          tNFC_STATUS
563**
564*******************************************************************************/
565static void rw_t2t_resume_op (void)
566{
567    tRW_T2T_CB          *p_t2t = &rw_cb.tcb.t2t;
568    tRW_READ_DATA       evt_data;
569    BT_HDR              *p_cmd_buf;
570    tRW_EVENT           event;
571    const tT2T_CMD_RSP_INFO   *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info;
572    UINT8               *p;
573
574    /* Move back to the substate where we were before changing sector */
575    p_t2t->substate = p_t2t->prev_substate;
576
577    p              = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset;
578    p_cmd_rsp_info = t2t_cmd_to_rsp_info ((UINT8) *p);
579    p_t2t->p_cmd_rsp_info   = (tT2T_CMD_RSP_INFO *) p_cmd_rsp_info;
580
581    /* allocate a new buffer for message */
582    if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL)
583    {
584        memcpy (p_cmd_buf, p_t2t->p_sec_cmd_buf, sizeof (BT_HDR) + p_t2t->p_sec_cmd_buf->offset + p_t2t->p_sec_cmd_buf->len);
585        memcpy (p_t2t->p_cur_cmd_buf, p_t2t->p_sec_cmd_buf, sizeof (BT_HDR) + p_t2t->p_sec_cmd_buf->offset + p_t2t->p_sec_cmd_buf->len);
586
587#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
588        /* Update stats */
589         rw_main_update_tx_stats (p_cmd_buf->len, TRUE);
590#endif
591        if (NFC_SendData (NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK)
592        {
593            /* Start timer for waiting for response */
594            nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
595                                   (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
596        }
597        else
598        {
599            /* failure - could not send buffer */
600            evt_data.p_data = NULL;
601            evt_data.status = NFC_STATUS_FAILED;
602            event = rw_t2t_info_to_event (p_cmd_rsp_info);
603            rw_t2t_handle_op_complete ();
604            (*rw_cb.p_cback) (event, (tRW_DATA *) &evt_data);
605        }
606    }
607}
608
609/*******************************************************************************
610**
611** Function         rw_t2t_sector_change
612**
613** Description      This function issues Type 2 Tag SECTOR-SELECT command
614**                  packet 1.
615**
616** Returns          tNFC_STATUS
617**
618*******************************************************************************/
619tNFC_STATUS rw_t2t_sector_change (UINT8 sector)
620{
621    tNFC_STATUS status;
622    BT_HDR      *p_data;
623    UINT8       *p;
624    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
625
626    if ((p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
627    {
628        RW_TRACE_ERROR0 ("rw_t2t_sector_change - No buffer");
629         return (NFC_STATUS_NO_BUFFERS);
630    }
631
632    p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
633    p = (UINT8 *) (p_data + 1) + p_data->offset;
634
635    UINT8_TO_BE_STREAM (p, sector);
636    UINT8_TO_BE_STREAM (p, 0x00);
637    UINT8_TO_BE_STREAM (p, 0x00);
638    UINT8_TO_BE_STREAM (p, 0x00);
639
640    p_data->len = 4;
641
642    if ((status = NFC_SendData (NFC_RF_CONN_ID , p_data)) == NFC_STATUS_OK)
643    {
644        /* Passive rsp command and suppose not to get response to this command */
645        p_t2t->p_cmd_rsp_info = NULL;
646        p_t2t->substate       = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR;
647
648        RW_TRACE_EVENT0 ("rw_t2t_sector_change Sent Second Command");
649        nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
650                               (RW_T2T_SEC_SEL_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
651    }
652    else
653    {
654        RW_TRACE_ERROR1 ("rw_t2t_sector_change Send failed at rw_t2t_send_cmd, error: %u", status);
655    }
656
657    return status;
658}
659
660/*******************************************************************************
661**
662** Function         rw_t2t_read
663**
664** Description      This function issues Type 2 Tag READ command for the
665**                  specified block. If the specified block is in different
666**                  sector then it first sends command to move to new sector
667**                  and after the tag moves to new sector it issues the read
668**                  command for the block.
669**
670** Returns          tNFC_STATUS
671**
672*******************************************************************************/
673tNFC_STATUS rw_t2t_read (UINT16 block)
674{
675    tNFC_STATUS status;
676    UINT8       *p;
677    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
678    UINT8       sector_byte2[1];
679    UINT8       read_cmd[1];
680
681
682    read_cmd[0] = block % T2T_BLOCKS_PER_SECTOR;
683    if (p_t2t->sector != block/T2T_BLOCKS_PER_SECTOR)
684    {
685        sector_byte2[0] = 0xFF;
686        /* First Move to new sector before sending Read command */
687        if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL,sector_byte2)) == NFC_STATUS_OK)
688        {
689            /* Prepare command that needs to be sent after sector change op is completed */
690            p_t2t->select_sector         = (UINT8) (block/T2T_BLOCKS_PER_SECTOR);
691            p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
692
693            p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset;
694            UINT8_TO_BE_STREAM (p, T2T_CMD_READ);
695            UINT8_TO_BE_STREAM (p, read_cmd[0]);
696            p_t2t->p_sec_cmd_buf->len = 2;
697            p_t2t->block_read = block;
698
699            /* Backup the current substate to move back to this substate after changing sector */
700            p_t2t->prev_substate = p_t2t->substate;
701            p_t2t->substate      = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT;
702            return NFC_STATUS_OK;
703        }
704        return NFC_STATUS_FAILED;
705    }
706
707    /* Send Read command as sector change is not needed */
708    if ((status = rw_t2t_send_cmd (T2T_CMD_READ, (UINT8 *) read_cmd)) == NFC_STATUS_OK)
709    {
710        p_t2t->block_read = block;
711        RW_TRACE_EVENT1 ("rw_t2t_read Sent Command for Block: %u", block);
712    }
713
714    return status;
715}
716
717/*******************************************************************************
718**
719** Function         rw_t2t_write
720**
721** Description      This function issues Type 2 Tag WRITE command for the
722**                  specified block.  If the specified block is in different
723**                  sector then it first sends command to move to new sector
724**                  and after the tag moves to new sector it issues the write
725**                  command for the block.
726**
727** Returns          tNFC_STATUS
728**
729*******************************************************************************/
730tNFC_STATUS rw_t2t_write (UINT16 block, UINT8 *p_write_data)
731{
732    tNFC_STATUS status;
733    UINT8       *p;
734    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
735    UINT8       write_cmd[T2T_WRITE_DATA_LEN + 1];
736    UINT8       sector_byte2[1];
737
738    p_t2t->block_written = block;
739    write_cmd[0] = (UINT8) (block%T2T_BLOCKS_PER_SECTOR);
740    memcpy (&write_cmd[1], p_write_data, T2T_WRITE_DATA_LEN);
741
742    if (p_t2t->sector != block/T2T_BLOCKS_PER_SECTOR)
743    {
744        sector_byte2[0] = 0xFF;
745        /* First Move to new sector before sending Write command */
746        if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL, sector_byte2)) == NFC_STATUS_OK)
747        {
748            /* Prepare command that needs to be sent after sector change op is completed */
749            p_t2t->select_sector         = (UINT8) (block/T2T_BLOCKS_PER_SECTOR);
750            p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
751            p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset;
752            UINT8_TO_BE_STREAM (p, T2T_CMD_WRITE);
753            memcpy (p, write_cmd, T2T_WRITE_DATA_LEN + 1);
754            p_t2t->p_sec_cmd_buf->len   = 2 + T2T_WRITE_DATA_LEN;
755            p_t2t->block_written  = block;
756
757            /* Backup the current substate to move back to this substate after changing sector */
758            p_t2t->prev_substate        = p_t2t->substate;
759            p_t2t->substate             = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT;
760            return NFC_STATUS_OK;
761        }
762        return NFC_STATUS_FAILED;
763    }
764
765    /* Send Write command as sector change is not needed */
766    if ((status = rw_t2t_send_cmd (T2T_CMD_WRITE, write_cmd)) == NFC_STATUS_OK)
767    {
768        RW_TRACE_EVENT1 ("rw_t2t_write Sent Command for Block: %u", block);
769    }
770
771    return status;
772}
773
774/*******************************************************************************
775**
776** Function         rw_t2t_select
777**
778** Description      This function selects type 2 tag.
779**
780** Returns          Tag selection status
781**
782*******************************************************************************/
783tNFC_STATUS rw_t2t_select (void)
784{
785    tRW_T2T_CB    *p_t2t = &rw_cb.tcb.t2t;
786
787    p_t2t->state       = RW_T2T_STATE_IDLE;
788    p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
789
790
791    /* Alloc cmd buf for retransmissions */
792    if (p_t2t->p_cur_cmd_buf ==  NULL)
793    {
794        if ((p_t2t->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
795        {
796            RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer for retransmission");
797            return (NFC_STATUS_FAILED);
798        }
799    }
800    /* Alloc cmd buf for holding a command untill sector changes */
801    if (p_t2t->p_sec_cmd_buf ==  NULL)
802    {
803        if ((p_t2t->p_sec_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
804        {
805            RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer used during sector change");
806            return (NFC_STATUS_FAILED);
807        }
808    }
809
810    NFC_SetStaticRfCback (rw_t2t_conn_cback);
811    rw_t2t_handle_op_complete ();
812
813    return NFC_STATUS_OK;
814}
815
816/*****************************************************************************
817**
818** Function         rw_t2t_handle_op_complete
819**
820** Description      Reset to IDLE state
821**
822** Returns          Nothing
823**
824*****************************************************************************/
825void rw_t2t_handle_op_complete (void)
826{
827    tRW_T2T_CB      *p_t2t  = &rw_cb.tcb.t2t;
828
829    p_t2t->state    = RW_T2T_STATE_IDLE;
830    p_t2t->substate = RW_T2T_SUBSTATE_NONE;
831    return;
832}
833
834/*****************************************************************************
835**
836** Function         RW_T2tPresenceCheck
837**
838** Description
839**      Check if the tag is still in the field.
840**
841**      The RW_T2T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
842**      or non-presence.
843**
844** Returns
845**      NFC_STATUS_OK, if raw data frame sent
846**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
847**      NFC_STATUS_FAILED: other error
848**
849*****************************************************************************/
850tNFC_STATUS RW_T2tPresenceCheck (void)
851{
852    tNFC_STATUS retval = NFC_STATUS_OK;
853    tRW_DATA evt_data;
854    tRW_CB *p_rw_cb = &rw_cb;
855    UINT8 sector_blk = 0;           /* block 0 of current sector */
856
857    RW_TRACE_API0 ("RW_T2tPresenceCheck");
858
859    /* If RW_SelectTagType was not called (no conn_callback) return failure */
860    if (!p_rw_cb->p_cback)
861    {
862        retval = NFC_STATUS_FAILED;
863    }
864    /* If we are not activated, then RW_T2T_PRESENCE_CHECK_EVT status=FAIL */
865    else if (p_rw_cb->tcb.t2t.state == RW_T2T_STATE_NOT_ACTIVATED)
866    {
867        evt_data.status = NFC_STATUS_FAILED;
868        (*p_rw_cb->p_cback) (RW_T2T_PRESENCE_CHECK_EVT, &evt_data);
869    }
870    /* If command is pending, assume tag is still present */
871    else if (p_rw_cb->tcb.t2t.state != RW_T2T_STATE_IDLE)
872    {
873        evt_data.status = NFC_STATUS_OK;
874        (*p_rw_cb->p_cback) (RW_T2T_PRESENCE_CHECK_EVT, &evt_data);
875    }
876    else
877    {
878        /* IDLE state: send a READ command to block 0 of the current sector */
879        if((retval = rw_t2t_send_cmd (T2T_CMD_READ, &sector_blk))== NFC_STATUS_OK)
880        {
881            p_rw_cb->tcb.t2t.state = RW_T2T_STATE_CHECK_PRESENCE;
882        }
883    }
884
885    return (retval);
886}
887
888/*******************************************************************************
889**
890** Function         RW_T2tRead
891**
892** Description      This function issues the Type 2 Tag READ command. When the
893**                  operation is complete the callback function will be called
894**                  with a RW_T2T_READ_EVT.
895**
896** Returns          tNFC_STATUS
897**
898*******************************************************************************/
899tNFC_STATUS RW_T2tRead (UINT16 block)
900{
901    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
902    tNFC_STATUS status;
903
904    if (p_t2t->state != RW_T2T_STATE_IDLE)
905    {
906        RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
907        return (NFC_STATUS_FAILED);
908    }
909
910    if ((status = rw_t2t_read (block)) == NFC_STATUS_OK)
911    {
912        p_t2t->state    = RW_T2T_STATE_READ;
913        RW_TRACE_EVENT0 ("RW_T2tRead Sent Read command");
914    }
915
916    return status;
917
918}
919
920/*******************************************************************************
921**
922** Function         RW_T2tWrite
923**
924** Description      This function issues the Type 2 Tag WRITE command. When the
925**                  operation is complete the callback function will be called
926**                  with a RW_T2T_WRITE_EVT.
927**
928**                  p_new_bytes points to the array of 4 bytes to be written
929**
930** Returns          tNFC_STATUS
931**
932*******************************************************************************/
933tNFC_STATUS RW_T2tWrite (UINT16 block, UINT8 *p_write_data)
934{
935    tRW_T2T_CB  *p_t2t = &rw_cb.tcb.t2t;
936    tNFC_STATUS status;
937
938    if (p_t2t->state != RW_T2T_STATE_IDLE)
939    {
940        RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
941        return (NFC_STATUS_FAILED);
942    }
943
944    if ((status = rw_t2t_write (block, p_write_data)) == NFC_STATUS_OK)
945    {
946        p_t2t->state    = RW_T2T_STATE_WRITE;
947        if (block < T2T_FIRST_DATA_BLOCK)
948            p_t2t->b_read_hdr = FALSE;
949        else if (block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS))
950            p_t2t->b_read_data = FALSE;
951        RW_TRACE_EVENT0 ("RW_T2tWrite Sent Write command");
952    }
953
954    return status;
955}
956
957/*******************************************************************************
958**
959** Function         RW_T2tSectorSelect
960**
961** Description      This function issues the Type 2 Tag SECTOR-SELECT command
962**                  packet 1. If a NACK is received as the response, the callback
963**                  function will be called with a RW_T2T_SECTOR_SELECT_EVT. If
964**                  an ACK is received as the response, the command packet 2 with
965**                  the given sector number is sent to the peer device. When the
966**                  response for packet 2 is received, the callback function will
967**                  be called with a RW_T2T_SECTOR_SELECT_EVT.
968**
969**                  A sector is 256 contiguous blocks (1024 bytes).
970**
971** Returns          tNFC_STATUS
972**
973*******************************************************************************/
974tNFC_STATUS RW_T2tSectorSelect (UINT8 sector)
975{
976    tNFC_STATUS status;
977    tRW_T2T_CB  *p_t2t       = &rw_cb.tcb.t2t;
978    UINT8       sector_byte2[1];
979
980    if (p_t2t->state != RW_T2T_STATE_IDLE)
981    {
982        RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
983        return (NFC_STATUS_FAILED);
984    }
985
986    if (sector >= T2T_MAX_SECTOR)
987    {
988        RW_TRACE_ERROR2 ("RW_T2tSectorSelect - Invalid sector: %u, T2 Max supported sector value: %u", sector, T2T_MAX_SECTOR - 1);
989        return (NFC_STATUS_FAILED);
990    }
991
992    sector_byte2[0] = 0xFF;
993
994    if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL, sector_byte2)) == NFC_STATUS_OK)
995    {
996        p_t2t->state         = RW_T2T_STATE_SELECT_SECTOR;
997        p_t2t->select_sector = sector;
998        p_t2t->substate      = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT;
999
1000        RW_TRACE_EVENT0 ("RW_T2tSectorSelect Sent Sector select first command");
1001    }
1002
1003    return status;
1004}
1005
1006#if (BT_TRACE_VERBOSE == TRUE)
1007/*******************************************************************************
1008**
1009** Function         rw_t2t_get_state_name
1010**
1011** Description      This function returns the state name.
1012**
1013** NOTE             conditionally compiled to save memory.
1014**
1015** Returns          pointer to the name
1016**
1017*******************************************************************************/
1018static char *rw_t2t_get_state_name (UINT8 state)
1019{
1020    switch (state)
1021    {
1022    case RW_T2T_STATE_NOT_ACTIVATED:
1023        return ("NOT_ACTIVATED");
1024    case RW_T2T_STATE_IDLE:
1025        return ("IDLE");
1026    case RW_T2T_STATE_READ:
1027        return ("APP_READ");
1028    case RW_T2T_STATE_WRITE:
1029        return ("APP_WRITE");
1030    case RW_T2T_STATE_SELECT_SECTOR:
1031        return ("SECTOR_SELECT");
1032    case RW_T2T_STATE_DETECT_TLV:
1033        return ("TLV_DETECT");
1034    case RW_T2T_STATE_READ_NDEF:
1035        return ("READ_NDEF");
1036    case RW_T2T_STATE_WRITE_NDEF:
1037        return ("WRITE_NDEF");
1038    case RW_T2T_STATE_SET_TAG_RO:
1039        return ("SET_TAG_RO");
1040    case RW_T2T_STATE_CHECK_PRESENCE:
1041        return ("CHECK_PRESENCE");
1042    default:
1043        return ("???? UNKNOWN STATE");
1044    }
1045}
1046
1047/*******************************************************************************
1048**
1049** Function         rw_t2t_get_substate_name
1050**
1051** Description      This function returns the substate name.
1052**
1053** NOTE             conditionally compiled to save memory.
1054**
1055** Returns          pointer to the name
1056**
1057*******************************************************************************/
1058static char *rw_t2t_get_substate_name (UINT8 substate)
1059{
1060    switch (substate)
1061    {
1062    case RW_T2T_SUBSTATE_NONE:
1063        return ("RW_T2T_SUBSTATE_NONE");
1064    case RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT:
1065        return ("RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT");
1066    case RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR:
1067        return ("RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR");
1068    case RW_T2T_SUBSTATE_WAIT_READ_CC:
1069        return ("RW_T2T_SUBSTATE_WAIT_READ_CC");
1070    case RW_T2T_SUBSTATE_WAIT_TLV_DETECT:
1071        return ("RW_T2T_SUBSTATE_WAIT_TLV_DETECT");
1072    case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
1073        return ("RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN");
1074    case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0:
1075        return ("RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0");
1076    case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1:
1077        return ("RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1");
1078    case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE:
1079        return ("RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE");
1080    case RW_T2T_SUBSTATE_WAIT_READ_LOCKS:
1081        return ("RW_T2T_SUBSTATE_WAIT_READ_LOCKS");
1082    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1083        return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK");
1084    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1085        return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK");
1086    case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1087        return ("RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK");
1088    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1089        return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK");
1090    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1091        return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK");
1092    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
1093        return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK");
1094    case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
1095        return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK");
1096    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
1097        return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK");
1098    case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
1099        return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK");
1100    case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
1101        return ("RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT");
1102    default:
1103        return ("???? UNKNOWN SUBSTATE");
1104    }
1105}
1106
1107#endif /* (BT_TRACE_VERBOSE == TRUE) */
1108
1109#endif /* NFC_INCLUDED == TRUE*/
1110