rw_t3t.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 3 tag in Reader/Writer
22 *  mode.
23 *
24 ******************************************************************************/
25#include <string.h>
26#include "nfc_target.h"
27#include "bt_types.h"
28#include "trace_api.h"
29
30#include "nfc_api.h"
31#include "nfc_int.h"
32#include "nci_hmsgs.h"
33#include "rw_api.h"
34#include "rw_int.h"
35#include "tags_int.h"
36#include "gki.h"
37
38/* Definitions for constructing t3t command messages */
39#define RW_T3T_FL_PADDING   0x01        /* Padding needed for last NDEF block */
40#define RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_1_BYTE_FORMAT (13)    /* Maximum number of NDEF blocks updates that can fit into one command (when all block-numbers are < 256) */
41#define RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_2_BYTE_FORMAT (12)    /* Maximum number of NDEF blocks updates that can fit into one command (when all block-numbers are >= 256) */
42
43/* Definitions for SENSF_RES */
44#define RW_T3T_SENSF_RES_RD_OFFSET      17  /* Offset of RD in SENSF_RES from NCI_POLL NTF (includes 1 byte SENSF_RES length) */
45#define RW_T3T_SENSF_RES_RD_LEN         2   /* Size of RD in SENSF_RES   */
46
47/* Timeout definitions for commands */
48#define RW_T3T_POLL_CMD_TIMEOUT_TICKS                               ((RW_T3T_TOUT_RESP*2*QUICK_TIMER_TICKS_PER_SEC) / 1000)
49#define RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS                            ((RW_T3T_TOUT_RESP*QUICK_TIMER_TICKS_PER_SEC) / 1000)
50#define RW_T3T_RAW_FRAME_CMD_TIMEOUT_TICKS                          (RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * 4)
51
52/* Macro to extract major version from NDEF version byte */
53#define T3T_GET_MAJOR_VERSION(ver)      (ver>>4)
54
55/* Enumeration of API commands */
56enum
57{
58    RW_T3T_CMD_DETECT_NDEF,
59    RW_T3T_CMD_CHECK_NDEF,
60    RW_T3T_CMD_UPDATE_NDEF,
61    RW_T3T_CMD_CHECK,
62    RW_T3T_CMD_UPDATE,
63    RW_T3T_CMD_SEND_RAW_FRAME,
64    RW_T3T_CMD_GET_SYSTEM_CODES,
65    RW_T3T_CMD_FORMAT,
66
67    RW_T3T_CMD_MAX
68};
69
70/* RW_CBACK events corresponding to API comands */
71const UINT8 rw_t3t_api_res_evt[RW_T3T_CMD_MAX] =
72{
73    RW_T3T_NDEF_DETECT_EVT,         /* RW_T3T_CMD_DETECT_NDEF */
74    RW_T3T_CHECK_CPLT_EVT,          /* RW_T3T_CMD_CHECK_NDEF  */
75    RW_T3T_UPDATE_CPLT_EVT,         /* RW_T3T_CMD_UPDATE_NDEF */
76    RW_T3T_CHECK_CPLT_EVT,          /* RW_T3T_CMD_CHECK */
77    RW_T3T_UPDATE_CPLT_EVT,         /* RW_T3T_CMD_UPDATE */
78    RW_T3T_RAW_FRAME_EVT,           /* RW_T3T_CMD_SEND_RAW_FRAME */
79    RW_T3T_GET_SYSTEM_CODES_EVT,    /* RW_T3T_CMD_GET_SYSTEM_CODES */
80    RW_T3T_FORMAT_CPLT_EVT          /* RW_T3T_CMD_FORMAT */
81};
82
83/* States */
84enum
85{
86    RW_T3T_STATE_NOT_ACTIVATED,
87    RW_T3T_STATE_IDLE,
88    RW_T3T_STATE_COMMAND_PENDING
89};
90
91/* Sub-states */
92enum
93{
94    /* Sub states for getting system codes */
95    RW_T3T_GET_SC_SST_POLL_WILDCARD,        /* Waiting for wilcard poll response */
96    RW_T3T_GET_SC_SST_POLL_NDEF,            /* Waiting for NDEF poll response */
97    RW_T3T_GET_SC_SST_REQUEST_SC,           /* Waiting for REQUEST_SYSTEM_CODE response */
98
99    /* Sub states for formatting Felica-Lite */
100    RW_T3T_FMT_SST_POLL_FELICA_LITE,        /* Waiting for POLL Felica-Lite response (for formatting) */
101    RW_T3T_FMT_SST_CHECK_MC_BLK,            /* Waiting for Felica-Lite MC (MemoryControl) block-read to complete */
102    RW_T3T_FMT_SST_UPDATE_MC_BLK,           /* Waiting for Felica-Lite MC (MemoryControl) block-write to complete */
103    RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB       /* Waiting for NDEF attribute block-write to complete */
104};
105
106#if (BT_TRACE_VERBOSE == TRUE)
107static char *rw_t3t_cmd_str (UINT8 cmd_id);
108static char *rw_t3t_state_str (UINT8 state_id);
109#endif
110
111
112/* Local static functions */
113static tNFC_STATUS rw_t3t_unselect (UINT8 peer_nfcid2[]);
114static BT_HDR *rw_t3t_get_cmd_buf (void);
115static tNFC_STATUS rw_t3t_send_to_lower (BT_HDR *p_msg);
116static void rw_t3t_handle_get_system_codes_cplt (void);
117static void rw_t3t_handle_get_sc_poll_rsp (tRW_T3T_CB *p_cb, UINT8 nci_status, UINT8 num_responses, UINT8 sensf_res_buf_size, UINT8 *p_sensf_res_buf);
118static void rw_t3t_handle_ndef_detect_poll_rsp (tRW_T3T_CB *p_cb, UINT8 nci_status, UINT8 num_responses, UINT8 sensf_res_buf_size, UINT8 *p_sensf_res_buf);
119static void rw_t3t_handle_fmt_poll_rsp (tRW_T3T_CB *p_cb, UINT8 nci_status, UINT8 num_responses, UINT8 sensf_res_buf_size, UINT8 *p_sensf_res_buf);
120
121
122/* Default NDEF attribute information block (used when formatting Felica-Lite tags) */
123#define RW_T3T_DEFAULT_FELICALITE_NBR       4   /* NBr (max block reads per cmd)*/
124#define RW_T3T_DEFAULT_FELICALITE_NBW       1   /* NBw (max block write per cmd)*/
125#define RW_T3T_DEFAULT_FELICALITE_NMAXB     13  /* Nmaxb (max size in blocks)   */
126#define RW_T3T_DEFAULT_FELICALITE_ATTRIB_INFO_CHECKSUM  ((T3T_MSG_NDEF_VERSION +                    \
127                                                            RW_T3T_DEFAULT_FELICALITE_NBR +         \
128                                                            RW_T3T_DEFAULT_FELICALITE_NBW +         \
129                                                            (RW_T3T_DEFAULT_FELICALITE_NMAXB>>8) +  \
130                                                            (RW_T3T_DEFAULT_FELICALITE_NMAXB&0xFF) +\
131                                                            T3T_MSG_NDEF_WRITEF_OFF +               \
132                                                            T3T_MSG_NDEF_RWFLAG_RW) & 0xFFFF)
133
134const UINT8 rw_t3t_default_attrib_info[T3T_MSG_BLOCKSIZE] =
135{
136    T3T_MSG_NDEF_VERSION,                   /* Ver                          */
137    RW_T3T_DEFAULT_FELICALITE_NBR,          /* NBr (max block reads per cmd)*/
138    RW_T3T_DEFAULT_FELICALITE_NBW,          /* NBw (max block write per cmd)*/
139    (RW_T3T_DEFAULT_FELICALITE_NMAXB>>8),   /* Nmaxb (max size in blocks)   */
140    (RW_T3T_DEFAULT_FELICALITE_NMAXB&0xFF), /* Nmaxb (max size in blocks)   */
141    0, 0, 0, 0,                             /* Unused                       */
142    T3T_MSG_NDEF_WRITEF_OFF,                /* WriteF                       */
143    T3T_MSG_NDEF_RWFLAG_RW,                 /* RW Flag                      */
144    0, 0, 0,                                /* Ln (current size in bytes)   */
145
146    (RW_T3T_DEFAULT_FELICALITE_ATTRIB_INFO_CHECKSUM >> 8),     /* checksum (high-byte) */
147    (RW_T3T_DEFAULT_FELICALITE_ATTRIB_INFO_CHECKSUM & 0xFF)    /* checksum (low-byte)  */
148
149};
150
151/*****************************************************************************
152**  Type3 TAG COMMANDS
153*****************************************************************************/
154
155/*******************************************************************************
156**
157** Function         rw_t3t_process_error
158**
159** Description      Process error (timeout or CRC error)
160**
161** Returns          none
162**
163*******************************************************************************/
164void rw_t3t_process_error (tNFC_STATUS status)
165{
166    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
167    UINT8 evt;
168    tRW_DATA evt_data;
169    BT_HDR *p_cmd_buf;
170
171    if (p_cb->rw_state == RW_T3T_STATE_COMMAND_PENDING)
172    {
173        if (p_cb->cur_cmd == RW_T3T_CMD_GET_SYSTEM_CODES)
174        {
175            /* For GetSystemCode: either tag did not respond to requested POLL, or REQUEST_SYSTEM_CODE command */
176            rw_t3t_handle_get_system_codes_cplt ();
177            return;
178        }
179        /* Retry sending command if retry-count < max */
180        else if (rw_cb.cur_retry < RW_MAX_RETRIES)
181        {
182            /* retry sending the command */
183            rw_cb.cur_retry++;
184
185            RW_TRACE_DEBUG2 ("T3T retransmission attempt %i of %i", rw_cb.cur_retry, RW_MAX_RETRIES);
186
187            /* allocate a new buffer for message */
188            if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
189            {
190                memcpy (p_cmd_buf, p_cb->p_cur_cmd_buf, sizeof (BT_HDR) + p_cb->p_cur_cmd_buf->offset + p_cb->p_cur_cmd_buf->len);
191
192                if (rw_t3t_send_to_lower (p_cmd_buf) == NFC_STATUS_OK)
193                {
194                    /* Start timer for waiting for response */
195                    nfc_start_quick_timer (&p_cb->timer, NFC_TTYPE_RW_T3T_RESPONSE, p_cb->cur_tout);
196                    return;
197                }
198                else
199                {
200                    /* failure - could not send buffer */
201                    GKI_freebuf (p_cmd_buf);
202                }
203            }
204        }
205        else
206        {
207            RW_TRACE_DEBUG1 ("T3T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES);
208        }
209
210#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
211        /* update failure count */
212        rw_main_update_fail_stats ();
213#endif  /* RW_STATS_INCLUDED */
214
215        p_cb->rw_state = RW_T3T_STATE_IDLE;
216
217        /* Notify app of result (if there was a pending command) */
218        if (p_cb->cur_cmd < RW_T3T_CMD_MAX)
219        {
220            /* If doing presence check, use status=NFC_STATUS_FAILED, otherwise NFC_STATUS_TIMEOUT */
221            evt_data.status = status;
222            evt = rw_t3t_api_res_evt[p_cb->cur_cmd];
223
224            /* Set additional flags for RW_T3T_NDEF_DETECT_EVT */
225            if (evt == RW_T3T_NDEF_DETECT_EVT)
226            {
227                evt_data.ndef.flags = RW_NDEF_FL_UNKNOWN;
228            }
229
230            (*(rw_cb.p_cback)) (evt, &evt_data);
231        }
232    }
233    else
234    {
235        evt_data.status = status;
236        (*(rw_cb.p_cback)) (RW_T3T_INTF_ERROR_EVT, &evt_data);
237    }
238}
239
240/*******************************************************************************
241**
242** Function         rw_t3t_start_poll_timer
243**
244** Description      Start the timer for T3T POLL Command
245**
246** Returns          none
247**
248*******************************************************************************/
249void rw_t3t_start_poll_timer (tRW_T3T_CB *p_cb)
250{
251    nfc_start_quick_timer (&p_cb->poll_timer, NFC_TTYPE_RW_T3T_RESPONSE, RW_T3T_POLL_CMD_TIMEOUT_TICKS);
252}
253
254/*******************************************************************************
255**
256** Function         rw_t3t_handle_nci_poll_ntf
257**
258** Description      Handle NCI_T3T_POLLING_NTF
259**
260** Returns          none
261**
262*******************************************************************************/
263void rw_t3t_handle_nci_poll_ntf (UINT8 nci_status, UINT8 num_responses, UINT8 sensf_res_buf_size, UINT8 *p_sensf_res_buf)
264{
265    tRW_DATA evt_data;
266    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
267
268    /* stop timer for poll response */
269    nfc_stop_quick_timer (&p_cb->poll_timer);
270
271    /* Stop t3t timer (if started) */
272    if (p_cb->flags & RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP)
273    {
274        p_cb->flags &= ~RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP;
275        evt_data.status = nci_status;
276        p_cb->rw_state = RW_T3T_STATE_IDLE;
277        (*(rw_cb.p_cback)) (RW_T3T_PRESENCE_CHECK_EVT, (tRW_DATA *) &evt_data);
278    }
279    else if (p_cb->flags & RW_T3T_FL_W4_GET_SC_POLL_RSP)
280    {
281        /* Handle POLL ntf in response to get system codes */
282        p_cb->flags &= ~RW_T3T_FL_W4_GET_SC_POLL_RSP;
283        rw_t3t_handle_get_sc_poll_rsp (p_cb, nci_status, num_responses, sensf_res_buf_size, p_sensf_res_buf);
284    }
285    else if (p_cb->flags & RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP)
286    {
287        /* Handle POLL ntf in response to get system codes */
288        p_cb->flags &= ~RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP;
289        rw_t3t_handle_fmt_poll_rsp (p_cb, nci_status, num_responses, sensf_res_buf_size, p_sensf_res_buf);
290    }
291    else if (p_cb->flags & RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP)
292    {
293        /* Handle POLL ntf in response to ndef detection */
294        p_cb->flags &= ~RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP;
295        rw_t3t_handle_ndef_detect_poll_rsp (p_cb, nci_status, num_responses, sensf_res_buf_size, p_sensf_res_buf);
296    }
297    else
298    {
299        /* Handle POLL ntf in response to RW_T3tPoll */
300        if ((evt_data.t3t_poll.status = nci_status) == NCI_STATUS_OK)
301        {
302            evt_data.t3t_poll.rc = p_cb->cur_poll_rc;
303            evt_data.t3t_poll.response_num = num_responses;
304            evt_data.t3t_poll.response_bufsize = sensf_res_buf_size;
305            evt_data.t3t_poll.response_buf = p_sensf_res_buf;
306        }
307
308        p_cb->rw_state = RW_T3T_STATE_IDLE;
309        (*(rw_cb.p_cback)) (RW_T3T_POLL_EVT, &evt_data);
310    }
311}
312
313
314/*******************************************************************************
315**
316** Function         rw_t3t_handle_get_system_codes_cplt
317**
318** Description      Notify upper layer of system codes
319**
320** Returns          none
321**
322*******************************************************************************/
323void rw_t3t_handle_get_system_codes_cplt (void)
324{
325    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
326    tRW_DATA evt_data;
327    UINT8 i;
328
329    evt_data.t3t_sc.status = NFC_STATUS_OK;
330    evt_data.t3t_sc.num_system_codes = p_cb->num_system_codes;
331    evt_data.t3t_sc.p_system_codes   = p_cb->system_codes;
332
333    RW_TRACE_DEBUG1 ("rw_t3t_handle_get_system_codes_cplt, number of systems: %i", evt_data.t3t_sc.num_system_codes);
334    for (i = 0; i < evt_data.t3t_sc.num_system_codes; i++)
335    {
336        RW_TRACE_DEBUG2 ("   system %i: %04X", i, evt_data.t3t_sc.p_system_codes[i]);
337    }
338
339    p_cb->rw_state = RW_T3T_STATE_IDLE;
340    (*(rw_cb.p_cback)) (RW_T3T_GET_SYSTEM_CODES_EVT, &evt_data);
341
342
343}
344
345/*******************************************************************************
346**
347** Function         rw_t3t_format_cplt
348**
349** Description      Notify upper layer of format complete
350**
351** Returns          none
352**
353*******************************************************************************/
354void rw_t3t_format_cplt (tNFC_STATUS status)
355{
356    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
357    tRW_DATA evt_data;
358
359    p_cb->rw_state = RW_T3T_STATE_IDLE;
360
361    /* Notify upper layer of format complete */
362    evt_data.status = status;
363    (*(rw_cb.p_cback)) (RW_T3T_FORMAT_CPLT_EVT, &evt_data);
364}
365
366/*******************************************************************************
367**
368** Function         rw_t3t_process_timeout
369**
370** Description      Process timeout
371**
372** Returns          none
373**
374*******************************************************************************/
375void rw_t3t_process_timeout (TIMER_LIST_ENT *p_tle)
376{
377    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
378    tRW_DATA evt_data;
379
380    /* Check which timer timed out */
381    if (p_tle == &p_cb->timer)
382    {
383        /* UPDATE/CHECK response timeout */
384#if (BT_TRACE_VERBOSE == TRUE)
385        RW_TRACE_ERROR3 ("T3T timeout. state=%s cur_cmd=0x%02X (%s)", rw_t3t_state_str (rw_cb.tcb.t3t.rw_state), rw_cb.tcb.t3t.cur_cmd, rw_t3t_cmd_str (rw_cb.tcb.t3t.cur_cmd));
386#else
387        RW_TRACE_ERROR2 ("T3T timeout. state=0x%02X cur_cmd=0x%02X", rw_cb.tcb.t3t.rw_state, rw_cb.tcb.t3t.cur_cmd);
388#endif
389
390        rw_t3t_process_error (NFC_STATUS_TIMEOUT);
391    }
392    else
393    {
394        RW_TRACE_ERROR0 ("T3T POLL timeout.");
395
396        /* POLL response timeout */
397        if (p_cb->flags & RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP)
398        {
399            /* POLL timeout for presence check */
400            p_cb->flags &= ~RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP;
401            evt_data.status = NFC_STATUS_FAILED;
402            p_cb->rw_state = RW_T3T_STATE_IDLE;
403            (*(rw_cb.p_cback)) (RW_T3T_PRESENCE_CHECK_EVT, (tRW_DATA *) &evt_data);
404        }
405        else if (p_cb->flags & RW_T3T_FL_W4_GET_SC_POLL_RSP)
406        {
407            /* POLL timeout for getting system codes */
408            p_cb->flags &= ~RW_T3T_FL_W4_GET_SC_POLL_RSP;
409            rw_t3t_handle_get_system_codes_cplt ();
410        }
411        else if (p_cb->flags & RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP)
412        {
413            /* POLL timeout for formatting Felica Lite */
414            p_cb->flags &= ~RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP;
415            RW_TRACE_ERROR0 ("Felica-Lite tag not detected");
416            rw_t3t_format_cplt (NFC_STATUS_FAILED);
417        }
418        else if (p_cb->flags & RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP)
419        {
420            /* POLL timeout for ndef detection */
421            p_cb->flags &= ~RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP;
422            rw_t3t_handle_ndef_detect_poll_rsp (p_cb, NFC_STATUS_TIMEOUT, 0, 0, NULL);
423        }
424        else
425        {
426            /* Timeout waiting for response for RW_T3tPoll */
427            evt_data.t3t_poll.status = NFC_STATUS_FAILED;
428            p_cb->rw_state = RW_T3T_STATE_IDLE;
429            (*(rw_cb.p_cback)) (RW_T3T_POLL_EVT, (tRW_DATA *) &evt_data);
430        }
431    }
432}
433
434
435/*******************************************************************************
436**
437** Function         rw_t3t_process_frame_error
438**
439** Description      Process frame crc error
440**
441** Returns          none
442**
443*******************************************************************************/
444void rw_t3t_process_frame_error (void)
445{
446#if (BT_TRACE_VERBOSE == TRUE)
447    RW_TRACE_ERROR3 ("T3T frame error. state=%s cur_cmd=0x%02X (%s)", rw_t3t_state_str (rw_cb.tcb.t3t.rw_state), rw_cb.tcb.t3t.cur_cmd, rw_t3t_cmd_str (rw_cb.tcb.t3t.cur_cmd));
448#else
449    RW_TRACE_ERROR2 ("T3T frame error. state=0x%02X cur_cmd=0x%02X", rw_cb.tcb.t3t.rw_state, rw_cb.tcb.t3t.cur_cmd);
450#endif
451
452#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
453    /* Update stats */
454    rw_main_update_crc_error_stats ();
455#endif  /* RW_STATS_INCLUDED */
456
457    /* Process the error */
458    rw_t3t_process_error (NFC_STATUS_MSG_CORRUPTED);
459}
460
461/*******************************************************************************
462**
463** Function         rw_t3t_send_to_lower
464**
465** Description      Send command to lower layer
466**
467** Returns          status of the send
468**
469*******************************************************************************/
470tNFC_STATUS rw_t3t_send_to_lower (BT_HDR *p_msg)
471{
472    UINT8 *p;
473
474#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
475    BOOLEAN is_retry;
476    /* Update stats */
477    rw_main_update_tx_stats (p_msg->len, ((rw_cb.cur_retry==0) ? FALSE : TRUE));
478#endif  /* RW_STATS_INCLUDED */
479
480    /* Set NFC-F SoD field (payload len + 1) */
481    p_msg->offset -= 1;         /* Point to SoD field */
482    p = (UINT8 *) (p_msg+1) + p_msg->offset;
483    UINT8_TO_STREAM (p, (p_msg->len+1));
484    p_msg->len += 1;            /* Increment len to include SoD */
485
486#if (BT_TRACE_PROTOCOL == TRUE)
487    DispT3TagMessage (p_msg, FALSE);
488#endif
489
490    return (NFC_SendData (NFC_RF_CONN_ID, p_msg));
491}
492
493/*****************************************************************************
494**
495** Function         rw_t3t_get_cmd_buf
496**
497** Description      Get a buffer for sending T3T messages
498**
499** Returns          BT_HDR *
500**
501*****************************************************************************/
502BT_HDR *rw_t3t_get_cmd_buf (void)
503{
504    BT_HDR *p_cmd_buf;
505
506    if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL)
507    {
508        /* Reserve offset for NCI_DATA_HDR and NFC-F Sod (LEN) field */
509        p_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + 1;
510        p_cmd_buf->len = 0;
511    }
512
513    return (p_cmd_buf);
514}
515
516/*****************************************************************************
517**
518** Function         rw_t3t_send_cmd
519**
520** Description      Send command to tag, and start timer for response
521**
522** Returns          tNFC_STATUS
523**
524*****************************************************************************/
525tNFC_STATUS rw_t3t_send_cmd (tRW_T3T_CB *p_cb, UINT8 rw_t3t_cmd, BT_HDR *p_cmd_buf, UINT32 timeout_ms)
526{
527    tNFC_STATUS retval;
528
529    /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */
530    rw_cb.cur_retry = 0;
531    memcpy (p_cb->p_cur_cmd_buf, p_cmd_buf, sizeof (BT_HDR) + p_cmd_buf->offset + p_cmd_buf->len);
532
533    p_cb->cur_cmd = rw_t3t_cmd;
534    p_cb->cur_tout = timeout_ms;
535    p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
536
537    if ((retval = rw_t3t_send_to_lower (p_cmd_buf)) == NFC_STATUS_OK)
538    {
539        /* Start timer for waiting for response */
540        nfc_start_quick_timer (&p_cb->timer, NFC_TTYPE_RW_T3T_RESPONSE, timeout_ms);
541    }
542    else
543    {
544        /* Error sending */
545        p_cb->rw_state = RW_T3T_STATE_IDLE;
546    }
547
548    return (retval);
549}
550
551/*****************************************************************************
552**
553** Function         rw_t3t_send_update_ndef_attribute_cmd
554**
555** Description      Send UPDATE command for Attribute Information
556**
557** Returns          tNFC_STATUS
558**
559*****************************************************************************/
560tNFC_STATUS rw_t3t_send_update_ndef_attribute_cmd (tRW_T3T_CB *p_cb, BOOLEAN write_in_progress)
561{
562    tNFC_STATUS retval = NFC_STATUS_OK;
563    BT_HDR *p_cmd_buf;
564    UINT8 *p_cmd_start, *p;
565    UINT16 checksum, i;
566    UINT8 write_f;
567    UINT32 ln;
568    UINT8 *p_ndef_attr_info_start;
569
570    if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
571    {
572        /* Construct T3T message */
573        p = p_cmd_start  = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
574
575        /* Add UPDATE opcode to message  */
576        UINT8_TO_STREAM (p, T3T_MSG_OPC_UPDATE_CMD);
577
578        /* Add IDm to message */
579        ARRAY_TO_STREAM (p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
580
581        /* Add Service code list */
582        UINT8_TO_STREAM (p, 1);                       /* Number of services (only 1 service: NDEF) */
583        UINT16_TO_STREAM (p, T3T_MSG_NDEF_SC_RW);     /* Service code (little-endian format) */
584
585        /* Add number of blocks in this UPDATE command */
586        UINT8_TO_STREAM (p, 1);                      /* Number of blocks to write in this command */
587
588        /* Block List element: the NDEF attribute information block (block 0) */
589        UINT8_TO_STREAM (p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
590        UINT8_TO_STREAM (p, 0);
591
592        /* Add payload (Attribute information block) */
593        p_ndef_attr_info_start = p;                              /* Save start of a NDEF attribute info block for checksum */
594        UINT8_TO_STREAM (p, T3T_MSG_NDEF_VERSION);
595        UINT8_TO_STREAM (p, p_cb->ndef_attrib.nbr);
596        UINT8_TO_STREAM (p, p_cb->ndef_attrib.nbw);
597        UINT16_TO_BE_STREAM (p, p_cb->ndef_attrib.nmaxb);
598        UINT32_TO_STREAM (p, 0);
599
600        /* If starting NDEF write: set WriteF=ON, and ln=current ndef length */
601        if (write_in_progress)
602        {
603            write_f = T3T_MSG_NDEF_WRITEF_ON;
604            ln = p_cb->ndef_attrib.ln;
605        }
606        /* If finishing NDEF write: set WriteF=OFF, and ln=new ndef len */
607        else
608        {
609            write_f = T3T_MSG_NDEF_WRITEF_OFF;
610            ln = p_cb->ndef_msg_len;
611        }
612        UINT8_TO_STREAM (p, write_f);
613        UINT8_TO_STREAM (p, p_cb->ndef_attrib.rwflag);
614        UINT8_TO_STREAM (p, (ln>>16) & 0xFF);    /* High byte (of 3) of Ln */
615        UINT8_TO_STREAM (p, (ln>>8) & 0xFF);     /* Middle byte (of 3) of Ln */
616        UINT8_TO_STREAM (p, (ln) & 0xFF);        /* Low byte (of 3) of Ln */
617
618        /* Calculate and append Checksum */
619        checksum = 0;
620        for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++)
621        {
622            checksum+=p_ndef_attr_info_start[i];
623        }
624        UINT16_TO_BE_STREAM (p, checksum);
625
626
627        /* Calculate length of message */
628        p_cmd_buf->len = (UINT16) (p - p_cmd_start);
629
630        /* Send the T3T message */
631        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_UPDATE_NDEF, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS);
632    }
633    else
634    {
635        retval = NFC_STATUS_NO_BUFFERS;
636    }
637
638    return (retval);
639}
640
641/*****************************************************************************
642**
643** Function         rw_t3t_send_next_ndef_update_cmd
644**
645** Description      Send next segment of NDEF message to update
646**
647** Returns          tNFC_STATUS
648**
649*****************************************************************************/
650tNFC_STATUS rw_t3t_send_next_ndef_update_cmd (tRW_T3T_CB *p_cb)
651{
652    tNFC_STATUS retval = NFC_STATUS_OK;
653    UINT16 block_id;
654    UINT16 first_block_to_write;
655    UINT16 ndef_blocks_to_write, ndef_blocks_remaining;
656    UINT32 ndef_bytes_remaining, ndef_padding = 0;
657    UINT8 flags = 0;
658    UINT8 *p_cur_ndef_src_offset;
659    BT_HDR *p_cmd_buf;
660    UINT8 *p_cmd_start, *p;
661    UINT8 blocks_per_update;
662    UINT32 timeout;
663
664    if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
665    {
666        /* Construct T3T message */
667        p = p_cmd_start  = (UINT8 *) (p_cmd_buf + 1) + p_cmd_buf->offset;
668
669        /* Calculate number of ndef bytes remaining to write */
670        ndef_bytes_remaining = p_cb->ndef_msg_len - p_cb->ndef_msg_bytes_sent;
671
672        /* Calculate number of blocks remaining to write */
673        ndef_blocks_remaining = (UINT16) ((ndef_bytes_remaining+15) >> 4);      /* ndef blocks remaining (rounded upward) */
674
675        /* Calculate first NDEF block ID for this UPDATE command */
676        first_block_to_write = (UINT16) ((p_cb->ndef_msg_bytes_sent >> 4) + 1);
677
678        /* Calculate max number of blocks per write. */
679        if ((first_block_to_write + RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_1_BYTE_FORMAT) < 0x100)
680        {
681            /* All block-numbers are < 0x100 (i.e. can be specified using one-byte format) */
682            blocks_per_update = RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_1_BYTE_FORMAT;
683        }
684        else
685        {
686            /* Block-numbers are >= 0x100 (i.e. need to be specified using two-byte format) */
687            blocks_per_update = RW_T3T_MAX_NDEF_BLOCKS_PER_UPDATE_2_BYTE_FORMAT;
688        }
689
690        /* Check if blocks_per_update is bigger than what peer allows */
691        if (blocks_per_update > p_cb->ndef_attrib.nbw)
692            blocks_per_update = p_cb->ndef_attrib.nbw;
693
694        /* Check if remaining blocks can fit into one UPDATE command */
695        if (ndef_blocks_remaining <= blocks_per_update)
696        {
697            /* remaining blocks can fit into one UPDATE command */
698            ndef_blocks_to_write = ndef_blocks_remaining;
699        }
700        else
701        {
702            /* Remaining blocks cannot fit into one UPDATE command */
703            ndef_blocks_to_write = blocks_per_update;
704        }
705
706
707        /* Write to command header for UPDATE */
708
709        /* Add UPDATE opcode to message  */
710        UINT8_TO_STREAM (p, T3T_MSG_OPC_UPDATE_CMD);
711
712        /* Add IDm to message */
713        ARRAY_TO_STREAM (p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
714
715        /* Add Service code list */
716        UINT8_TO_STREAM (p, 1);                       /* Number of services (only 1 service: NDEF) */
717        UINT16_TO_STREAM (p, T3T_MSG_NDEF_SC_RW);     /* Service code (little-endian format) */
718
719
720        /* Add number of blocks in this UPDATE command */
721        UINT8_TO_STREAM (p, ndef_blocks_to_write);   /* Number of blocks to write in this command */
722        timeout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) ndef_blocks_to_write;
723
724        for (block_id = first_block_to_write; block_id < (first_block_to_write + ndef_blocks_to_write); block_id++)
725        {
726            if (block_id<256)
727            {
728                /* Block IDs 0-255 can be specified in '2-byte' format: byte0=0, byte1=blocknumber */
729                UINT8_TO_STREAM (p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);    /* byte0: len=1; access-mode=0; service code list order=0 */
730                UINT8_TO_STREAM (p, block_id);                                   /* byte1: block number */
731            }
732            else
733            {
734                /* Block IDs 256+ must be specified in '3-byte' format: byte0=80h, followed by blocknumber */
735                UINT8_TO_STREAM (p, 0x00);               /* byte0: len=0; access-mode=0; service code list order=0 */
736                UINT16_TO_STREAM (p, block_id);          /* byte1-2: block number in little-endian format */
737            }
738
739        }
740
741        /* Add NDEF payload */
742
743        /* If this sending last block of NDEF,  check if padding is needed to make payload a multiple of 16 bytes */
744        if (ndef_blocks_to_write == ndef_blocks_remaining)
745        {
746            ndef_padding = (16 - (ndef_bytes_remaining & 0x0F)) & 0x0F;
747            if (ndef_padding)
748            {
749                flags |= RW_T3T_FL_PADDING;
750                ndef_blocks_to_write--;         /* handle the last block separately if it needs padding */
751            }
752        }
753
754        /* Add NDEF payload to the message */
755        p_cur_ndef_src_offset = &p_cb->ndef_msg[p_cb->ndef_msg_bytes_sent];
756
757
758        ARRAY_TO_STREAM (p, p_cur_ndef_src_offset, (ndef_blocks_to_write * 16));
759        p_cb->ndef_msg_bytes_sent += ((UINT32) ndef_blocks_to_write * 16);
760
761        if (flags & RW_T3T_FL_PADDING)
762        {
763            /* Add last of the NDEF message */
764            p_cur_ndef_src_offset = &p_cb->ndef_msg[p_cb->ndef_msg_bytes_sent];
765            ARRAY_TO_STREAM (p, p_cur_ndef_src_offset, (int) (16-ndef_padding));
766            p_cb->ndef_msg_bytes_sent += (16-ndef_padding);
767
768            /* Add padding */
769            memset (p, 0, ndef_padding);
770            p+=ndef_padding;
771        }
772
773        /* Calculate length of message */
774        p_cmd_buf->len = (UINT16) (p - p_cmd_start);
775
776        /* Send the T3T message */
777        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_UPDATE_NDEF, p_cmd_buf, timeout);
778    }
779    else
780    {
781        retval = NFC_STATUS_NO_BUFFERS;
782    }
783
784    return (retval);
785}
786
787
788
789/*****************************************************************************
790**
791** Function         rw_t3t_send_next_ndef_check_cmd
792**
793** Description      Send command for reading next segment of NDEF message
794**
795** Returns          tNFC_STATUS
796**
797*****************************************************************************/
798tNFC_STATUS rw_t3t_send_next_ndef_check_cmd (tRW_T3T_CB *p_cb)
799{
800    tNFC_STATUS retval = NFC_STATUS_OK;
801    UINT16 block_id;
802    UINT16 ndef_blocks_remaining, first_block_to_read, cur_blocks_to_read;
803    UINT32 ndef_bytes_remaining;
804    BT_HDR *p_cmd_buf;
805    UINT8 *p_cmd_start, *p;
806
807    if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
808    {
809        /* Construct T3T message */
810        p = p_cmd_start  = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
811
812        /* Calculate number of ndef bytes remaining to read */
813        ndef_bytes_remaining = p_cb->ndef_attrib.ln - p_cb->ndef_rx_offset;
814
815        /* Calculate number of blocks remaining to read */
816        ndef_blocks_remaining = (UINT16) ((ndef_bytes_remaining+15) >> 4);      /* ndef blocks remaining (rounded upward) */
817
818        /* Calculate first NDEF block ID */
819        first_block_to_read = (UINT16) ((p_cb->ndef_rx_offset >> 4) + 1);
820
821        /* Check if remaining blocks can fit into one CHECK command */
822        if (ndef_blocks_remaining <= p_cb->ndef_attrib.nbr)
823        {
824            /* remaining blocks can fit into one CHECK command */
825            cur_blocks_to_read = ndef_blocks_remaining;
826            p_cb->ndef_rx_readlen = ndef_bytes_remaining;
827            p_cb->flags |= RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
828        }
829        else
830        {
831            /* Remaining blocks cannot fit into one CHECK command */
832            cur_blocks_to_read = p_cb->ndef_attrib.nbr;            /* Read maximum number of blocks allowed by the peer */
833            p_cb->ndef_rx_readlen = ((UINT32) p_cb->ndef_attrib.nbr * 16);
834        }
835
836        RW_TRACE_DEBUG3 ("rw_t3t_send_next_ndef_check_cmd: bytes_remaining: %i, cur_blocks_to_read: %i, is_final: %i",
837            ndef_bytes_remaining, cur_blocks_to_read, (p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT));
838
839        /* Write to command header for UPDATE */
840
841        /* Add UPDATE opcode to message  */
842        UINT8_TO_STREAM (p, T3T_MSG_OPC_CHECK_CMD);
843
844        /* Add IDm to message */
845        ARRAY_TO_STREAM (p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
846
847        /* Add Service code list */
848        UINT8_TO_STREAM (p, 1);                       /* Number of services (only 1 service: NDEF) */
849
850        /* Service code (little-endian format) . If NDEF is read-only, then use T3T_MSG_NDEF_SC_RO, otherwise use T3T_MSG_NDEF_SC_RW */
851        if (p_cb->ndef_attrib.rwflag == T3T_MSG_NDEF_RWFLAG_RO)
852        {
853            UINT16_TO_STREAM (p, T3T_MSG_NDEF_SC_RO);
854        }
855        else
856        {
857            UINT16_TO_STREAM (p, T3T_MSG_NDEF_SC_RW);
858        }
859
860        /* Add number of blocks in this UPDATE command */
861        UINT8_TO_STREAM (p, cur_blocks_to_read);     /* Number of blocks to check in this command */
862
863        for (block_id = first_block_to_read; block_id < (first_block_to_read + cur_blocks_to_read); block_id++)
864        {
865            if (block_id<256)
866            {
867                /* Block IDs 0-255 can be specified in '2-byte' format: byte0=0, byte1=blocknumber */
868                UINT8_TO_STREAM (p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);    /* byte1: len=0; access-mode=0; service code list order=0 */
869                UINT8_TO_STREAM (p, block_id);                                   /* byte1: block number */
870            }
871            else
872            {
873                /* Block IDs 256+ must be specified in '3-byte' format: byte0=80h, followed by blocknumber */
874                UINT8_TO_STREAM (p, 0x00);           /* byte0: len=1; access-mode=0; service code list order=0 */
875                UINT16_TO_STREAM (p, block_id);      /* byte1-2: block number in little-endian format */
876            }
877
878        }
879
880        /* Calculate length of message */
881        p_cmd_buf->len = (UINT16) (p - p_cmd_start);
882
883        /* Send the T3T message */
884        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_CHECK_NDEF, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) cur_blocks_to_read);
885    }
886    else
887    {
888        retval = NFC_STATUS_NO_BUFFERS;
889    }
890
891    return(retval);
892}
893
894
895/*****************************************************************************
896**
897** Function         rw_t3t_message_set_block_list
898**
899** Description      Add block list to T3T message
900**
901** Returns          Number of bytes added to message
902**
903*****************************************************************************/
904void rw_t3t_message_set_block_list (tRW_T3T_CB *p_cb, UINT8 **p, UINT8 num_blocks, tT3T_BLOCK_DESC *p_t3t_blocks)
905{
906    UINT16 i, cur_service_code;
907    UINT8 service_code_idx, num_services = 0;
908    UINT8 *p_msg_num_services;
909    UINT16 service_list[T3T_MSG_SERVICE_LIST_MAX];
910
911    /* Add CHECK or UPDATE opcode to message  */
912    UINT8_TO_STREAM ((*p), ((p_cb->cur_cmd == RW_T3T_CMD_CHECK) ? T3T_MSG_OPC_CHECK_CMD:T3T_MSG_OPC_UPDATE_CMD));
913
914    /* Add IDm to message */
915    ARRAY_TO_STREAM ((*p), p_cb->peer_nfcid2, NCI_NFCID2_LEN);
916
917    /* Skip over Number of Services field */
918    p_msg_num_services = (*p);      /* pointer to Number of Services offset */
919    (*p)++;
920
921    /* Count number of different services are specified in the list, and add services to Service Code list */
922    for (i = 0; i < num_blocks; i++)
923    {
924        cur_service_code = p_t3t_blocks[i].service_code;
925
926        /* Check if current service_code is already in the service_list */
927        for (service_code_idx=0; service_code_idx<num_services; service_code_idx++)
928        {
929            if (service_list[service_code_idx] == cur_service_code)
930                break;
931        }
932
933        if (service_code_idx == num_services)
934        {
935            /* Service not in the list yet. Add it. */
936            service_list[service_code_idx] = cur_service_code;
937            num_services++;
938
939            /* Add service code to T3T message */
940            UINT16_TO_STREAM ((*p), cur_service_code);
941        }
942    }
943
944    /* Add 'Number of Sservices' to the message */
945    *p_msg_num_services = num_services;
946
947    /* Add 'number of blocks' to the message */
948    UINT8_TO_STREAM ((*p), num_blocks);
949
950    /* Add block descriptors */
951    for (i = 0; i < num_blocks; i++)
952    {
953        cur_service_code = p_t3t_blocks[i].service_code;
954
955        /* Check if current service_code is already in the service_list */
956        for (service_code_idx=0; service_code_idx<num_services; service_code_idx++)
957        {
958            if (service_list[service_code_idx] == cur_service_code)
959                break;
960        }
961
962        /* Add decriptor to T3T message */
963        if (p_t3t_blocks[i].block_number > 0xFF)
964        {
965            UINT8_TO_STREAM ((*p), service_code_idx);
966            UINT16_TO_STREAM ((*p), p_t3t_blocks[i].block_number);
967        }
968        else
969        {
970            service_code_idx |= T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT;
971            UINT8_TO_STREAM ((*p), service_code_idx);
972            UINT8_TO_STREAM ((*p), p_t3t_blocks[i].block_number);
973        }
974    }
975}
976
977/*****************************************************************************
978**
979** Function         rw_t3t_send_check_cmd
980**
981** Description      Send CHECK command
982**
983** Returns          tNFC_STATUS
984**
985*****************************************************************************/
986tNFC_STATUS rw_t3t_send_check_cmd (tRW_T3T_CB *p_cb, UINT8 num_blocks, tT3T_BLOCK_DESC *p_t3t_blocks)
987{
988    BT_HDR *p_cmd_buf;
989    UINT8 *p, *p_cmd_start;
990    tNFC_STATUS retval = NFC_STATUS_OK;
991
992    p_cb->cur_cmd = RW_T3T_CMD_CHECK;
993    if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
994    {
995        /* Construct T3T message */
996        p = p_cmd_start = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
997        rw_t3t_message_set_block_list (p_cb, &p, num_blocks, p_t3t_blocks);
998
999        /* Calculate length of message */
1000        p_cmd_buf->len = (UINT16) (p - p_cmd_start);
1001
1002        /* Send the T3T message */
1003        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_CHECK, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) num_blocks);
1004    }
1005    else
1006    {
1007        retval = NFC_STATUS_NO_BUFFERS;
1008    }
1009
1010    return(retval);
1011}
1012
1013/*****************************************************************************
1014**
1015** Function         rw_t3t_send_update_cmd
1016**
1017** Description      Send UPDATE command
1018**
1019** Returns          tNFC_STATUS
1020**
1021*****************************************************************************/
1022tNFC_STATUS rw_t3t_send_update_cmd (tRW_T3T_CB *p_cb, UINT8 num_blocks, tT3T_BLOCK_DESC *p_t3t_blocks, UINT8 *p_data)
1023{
1024    BT_HDR *p_cmd_buf;
1025    UINT8 *p, *p_cmd_start;
1026    tNFC_STATUS retval = NFC_STATUS_OK;
1027
1028    p_cb->cur_cmd = RW_T3T_CMD_UPDATE;
1029    if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
1030    {
1031        /* Construct T3T message */
1032        p = p_cmd_start = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
1033        rw_t3t_message_set_block_list (p_cb, &p, num_blocks, p_t3t_blocks);
1034
1035        /* Add data blocks to the message */
1036        ARRAY_TO_STREAM (p, p_data, num_blocks*16);
1037
1038        /* Calculate length of message */
1039        p_cmd_buf->len = (UINT16) (p - p_cmd_start);
1040
1041        /* Send the T3T message */
1042        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_UPDATE, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) num_blocks);
1043    }
1044    else
1045    {
1046        retval = NFC_STATUS_NO_BUFFERS;
1047    }
1048
1049    return(retval);
1050}
1051
1052/*****************************************************************************
1053**
1054** Function         rw_t3t_send_raw_frame
1055**
1056** Description      Send raw frame
1057**
1058** Returns          tNFC_STATUS
1059**
1060*****************************************************************************/
1061tNFC_STATUS rw_t3t_send_raw_frame (tRW_T3T_CB *p_cb, UINT16 len, UINT8 *p_data)
1062{
1063    BT_HDR *p_cmd_buf;
1064    UINT8 *p;
1065    tNFC_STATUS retval = NFC_STATUS_OK;
1066
1067    if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
1068    {
1069        /* Construct T3T message */
1070        p = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
1071
1072        /* Add data blocks to the message */
1073        ARRAY_TO_STREAM (p, p_data, len);
1074
1075        /* Calculate length of message */
1076        p_cmd_buf->len = len;
1077
1078        /* Send the T3T message */
1079        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_SEND_RAW_FRAME, p_cmd_buf, RW_T3T_RAW_FRAME_CMD_TIMEOUT_TICKS);
1080    }
1081    else
1082    {
1083        retval = NFC_STATUS_NO_BUFFERS;
1084    }
1085
1086    return (retval);
1087}
1088
1089
1090/*****************************************************************************
1091**  TAG RESPONSE HANDLERS
1092*****************************************************************************/
1093
1094
1095/*****************************************************************************
1096**
1097** Function         rw_t3t_act_handle_ndef_detect_rsp
1098**
1099** Description      Handle response to NDEF detection
1100**
1101** Returns          Nothing
1102**
1103*****************************************************************************/
1104void rw_t3t_act_handle_ndef_detect_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1105{
1106    UINT8 *p;
1107    UINT32 temp;
1108    UINT8 i;
1109    UINT16 checksum_calc, checksum_rx;
1110    tRW_DETECT_NDEF_DATA evt_data;
1111    UINT8 *p_t3t_rsp = (UINT8 *) (p_msg_rsp+1) + p_msg_rsp->offset;
1112
1113    evt_data.status = NFC_STATUS_FAILED;
1114    evt_data.flags  = RW_NDEF_FL_UNKNOWN;
1115
1116    /* Check if response code is CHECK resp (for reading NDEF attribute block) */
1117    if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP)
1118    {
1119        RW_TRACE_ERROR2 ("Response error: expecting rsp_code %02X, but got %02X", T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1120        evt_data.status = NFC_STATUS_FAILED;
1121    }
1122    /* Validate status code and NFCID2 response from tag */
1123    else if (  (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)                          /* verify response status code */
1124             ||(memcmp (p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM], NCI_NFCID2_LEN) != 0)  )   /* verify response IDm */
1125    {
1126        evt_data.status = NFC_STATUS_FAILED;
1127    }
1128    else
1129    {
1130        /* Get checksum from received ndef attribute msg */
1131        p = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA+T3T_MSG_NDEF_ATTR_INFO_SIZE];
1132        BE_STREAM_TO_UINT16 (checksum_rx, p);
1133
1134        /* Calculate checksum - move check for checsum to beginning */
1135        checksum_calc = 0;
1136        p = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA];
1137        for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++)
1138        {
1139            checksum_calc+=p[i];
1140        }
1141
1142        /* Validate checksum */
1143        if (checksum_calc != checksum_rx)
1144        {
1145            p_cb->ndef_attrib.status = NFC_STATUS_FAILED;       /* only ok or failed passed to the app. can be boolean*/
1146
1147            RW_TRACE_ERROR0 ("RW_T3tDetectNDEF checksum failed");
1148        }
1149        else
1150        {
1151            p_cb->ndef_attrib.status = NFC_STATUS_OK;
1152
1153            /* Validate version number */
1154            STREAM_TO_UINT8 (p_cb->ndef_attrib.version, p);
1155
1156            if (T3T_GET_MAJOR_VERSION (T3T_MSG_NDEF_VERSION) < T3T_GET_MAJOR_VERSION (p_cb->ndef_attrib.version))
1157            {
1158                /* Remote tag's MajorVer is newer than our's. Reject NDEF as per T3TOP RQ_T3T_NDA_024 */
1159                RW_TRACE_ERROR2 ("RW_T3tDetectNDEF: incompatible NDEF version. Local=0x%02x, Remote=0x%02x", T3T_MSG_NDEF_VERSION, p_cb->ndef_attrib.version);
1160                p_cb->ndef_attrib.status = NFC_STATUS_FAILED;
1161                evt_data.status = NFC_STATUS_BAD_RESP;
1162            }
1163            else
1164            {
1165                /* Remote tag's MajorVer is equal or older than our's. NDEF is compatible with our version. */
1166
1167                /* Update NDEF info */
1168                STREAM_TO_UINT8 (p_cb->ndef_attrib.nbr, p);              /* NBr: number of blocks that can be read using one Check command */
1169                STREAM_TO_UINT8 (p_cb->ndef_attrib.nbw, p);              /* Nbw: number of blocks that can be written using one Update command */
1170                BE_STREAM_TO_UINT16 (p_cb->ndef_attrib.nmaxb, p);        /* Nmaxb: maximum number of blocks available for NDEF data */
1171                BE_STREAM_TO_UINT32 (temp, p);
1172                STREAM_TO_UINT8 (p_cb->ndef_attrib.writef, p);           /* WriteFlag: 00h if writing data finished; 0Fh if writing data in progress */
1173                STREAM_TO_UINT8 (p_cb->ndef_attrib.rwflag, p);           /* RWFlag: 00h NDEF is read-only; 01h if read/write available */
1174
1175                /* Get length (3-byte, big-endian) */
1176                STREAM_TO_UINT8 (temp, p);                               /* Ln: high-byte */
1177                BE_STREAM_TO_UINT16 (p_cb->ndef_attrib.ln, p);           /* Ln: lo-word */
1178                p_cb->ndef_attrib.ln += (temp << 16);
1179
1180
1181                RW_TRACE_DEBUG1 ("Detected NDEF Ver: 0x%02x", p_cb->ndef_attrib.version);
1182                RW_TRACE_DEBUG6 ("Detected NDEF Attributes: Nbr=%i, Nbw=%i, Nmaxb=%i, WriteF=%i, RWFlag=%i, Ln=%i",
1183                    p_cb->ndef_attrib.nbr,
1184                    p_cb->ndef_attrib.nbw,
1185                    p_cb->ndef_attrib.nmaxb,
1186                    p_cb->ndef_attrib.writef,
1187                    p_cb->ndef_attrib.rwflag,
1188                    p_cb->ndef_attrib.ln);
1189
1190                /* Set data for RW_T3T_NDEF_DETECT_EVT */
1191                evt_data.status = p_cb->ndef_attrib.status;
1192                evt_data.cur_size = p_cb->ndef_attrib.ln;
1193                evt_data.max_size = (UINT32) p_cb->ndef_attrib.nmaxb * 16;
1194                evt_data.protocol = NFC_PROTOCOL_T3T;
1195                evt_data.flags    = (RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED);
1196                if (p_cb->ndef_attrib.rwflag == T3T_MSG_NDEF_RWFLAG_RO)
1197                    evt_data.flags    |= RW_NDEF_FL_READ_ONLY;
1198            }
1199        }
1200    }
1201
1202    RW_TRACE_DEBUG1 ("RW_T3tDetectNDEF response: %i", evt_data.status);
1203
1204    p_cb->rw_state = RW_T3T_STATE_IDLE;
1205
1206    /* Notify app of NDEF detection result */
1207    (*(rw_cb.p_cback)) (RW_T3T_NDEF_DETECT_EVT, (tRW_DATA *) &evt_data);
1208
1209    GKI_freebuf (p_msg_rsp);
1210}
1211
1212
1213/*****************************************************************************
1214**
1215** Function         rw_t3t_act_handle_check_rsp
1216**
1217** Description      Handle response to CHECK command
1218**
1219** Returns          Nothing
1220**
1221*****************************************************************************/
1222void rw_t3t_act_handle_check_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1223{
1224    UINT8 *p_t3t_rsp = (UINT8 *) (p_msg_rsp+1) + p_msg_rsp->offset;
1225    tRW_READ_DATA evt_data;
1226    tNFC_STATUS nfc_status = NFC_STATUS_OK;
1227
1228    /* Validate response from tag */
1229    if (  (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)                           /* verify response status code */
1230        ||(memcmp (p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM], NCI_NFCID2_LEN) != 0)  )   /* verify response IDm */
1231    {
1232        nfc_status = NFC_STATUS_FAILED;
1233        GKI_freebuf (p_msg_rsp);
1234    }
1235    else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP)
1236    {
1237        RW_TRACE_ERROR2 ("Response error: expecting rsp_code %02X, but got %02X", T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1238        nfc_status = NFC_STATUS_FAILED;
1239        GKI_freebuf (p_msg_rsp);
1240    }
1241    else
1242    {
1243        /* Copy incoming data into buffer */
1244        p_msg_rsp->offset += T3T_MSG_RSP_OFFSET_CHECK_DATA;     /* Skip over t3t header */
1245        p_msg_rsp->len -= T3T_MSG_RSP_OFFSET_CHECK_DATA;
1246        evt_data.status = NFC_STATUS_OK;
1247        evt_data.p_data = p_msg_rsp;
1248        (*(rw_cb.p_cback)) (RW_T3T_CHECK_EVT, (tRW_DATA *) &evt_data);
1249    }
1250
1251
1252    p_cb->rw_state = RW_T3T_STATE_IDLE;
1253
1254    (*(rw_cb.p_cback)) (RW_T3T_CHECK_CPLT_EVT, (tRW_DATA *) &nfc_status);
1255}
1256
1257/*****************************************************************************
1258**
1259** Function         rw_t3t_act_handle_update_rsp
1260**
1261** Description      Handle response to UPDATE command
1262**
1263** Returns          Nothing
1264**
1265*****************************************************************************/
1266void rw_t3t_act_handle_update_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1267{
1268    UINT8 *p_t3t_rsp = (UINT8 *) (p_msg_rsp+1) + p_msg_rsp->offset;
1269    tRW_READ_DATA evt_data;
1270
1271    /* Validate response from tag */
1272    if (   (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)                          /* verify response status code */
1273        ||(memcmp (p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM], NCI_NFCID2_LEN) != 0)  )   /* verify response IDm */
1274    {
1275        evt_data.status = NFC_STATUS_FAILED;
1276    }
1277    else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP)
1278    {
1279        RW_TRACE_ERROR2 ("Response error: expecting rsp_code %02X, but got %02X", T3T_MSG_OPC_UPDATE_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1280        evt_data.status = NFC_STATUS_FAILED;
1281    }
1282    else
1283    {
1284        /* Copy incoming data into buffer */
1285        evt_data.status = NFC_STATUS_OK;
1286    }
1287
1288    p_cb->rw_state = RW_T3T_STATE_IDLE;
1289
1290    (*(rw_cb.p_cback)) (RW_T3T_UPDATE_CPLT_EVT, (tRW_DATA *)&evt_data);
1291
1292    GKI_freebuf (p_msg_rsp);
1293}
1294
1295/*****************************************************************************
1296**
1297** Function         rw_t3t_act_handle_raw_senddata_rsp
1298**
1299** Description      Handle response to NDEF detection
1300**
1301** Returns          Nothing
1302**
1303*****************************************************************************/
1304void rw_t3t_act_handle_raw_senddata_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1305{
1306    tRW_READ_DATA evt_data;
1307
1308    /* Copy incoming data into buffer */
1309    evt_data.status = NFC_STATUS_OK;
1310    evt_data.p_data = p_msg_rsp;
1311
1312    p_cb->rw_state = RW_T3T_STATE_IDLE;
1313
1314    (*(rw_cb.p_cback)) (RW_T3T_RAW_FRAME_EVT, (tRW_DATA *) &evt_data);
1315}
1316
1317/*****************************************************************************
1318**
1319** Function         rw_t3t_act_handle_check_ndef_rsp
1320**
1321** Description      Handle response to NDEF read segment
1322**
1323** Returns          Nothing
1324**
1325*****************************************************************************/
1326void rw_t3t_act_handle_check_ndef_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1327{
1328    BOOLEAN check_complete = TRUE;
1329    tNFC_STATUS nfc_status = NFC_STATUS_OK;
1330    tRW_READ_DATA read_data;
1331    tRW_DATA evt_data;
1332    UINT8 *p_t3t_rsp = (UINT8 *) (p_msg_rsp+1) + p_msg_rsp->offset;
1333    UINT8 rsp_num_bytes_rx;
1334
1335    /* Validate response from tag */
1336    if (  (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)                      /* verify response status code */
1337        ||(memcmp (p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM], NCI_NFCID2_LEN) != 0) /* verify response IDm */
1338        ||(p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS] != ((p_cb->ndef_rx_readlen+15) >> 4))  )     /* verify length of response */
1339    {
1340        RW_TRACE_ERROR2 ("Response error: bad status, nfcid2, or invalid len: %i %i", p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS], ((p_cb->ndef_rx_readlen+15)>>4));
1341        nfc_status = NFC_STATUS_FAILED;
1342        GKI_freebuf (p_msg_rsp);
1343    }
1344    else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP)
1345    {
1346        RW_TRACE_ERROR2 ("Response error: expecting rsp_code %02X, but got %02X", T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1347        nfc_status = NFC_STATUS_FAILED;
1348        GKI_freebuf (p_msg_rsp);
1349    }
1350    else
1351    {
1352        /* Notify app of NDEF segment received */
1353        rsp_num_bytes_rx = p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS] * 16;    /* Number of bytes received, according to header */
1354        p_cb->ndef_rx_offset += p_cb->ndef_rx_readlen;
1355        read_data.status = NFC_STATUS_OK;
1356        p_msg_rsp->offset += T3T_MSG_RSP_OFFSET_CHECK_DATA;     /* Skip over t3t header (point to block data) */
1357        p_msg_rsp->len -= T3T_MSG_RSP_OFFSET_CHECK_DATA;
1358
1359        /* Verify that the bytes received is really the amount indicated in the check-response header */
1360        if (rsp_num_bytes_rx > p_msg_rsp->len)
1361        {
1362            RW_TRACE_ERROR2 ("Response error: CHECK rsp header indicates %i bytes, but only received %i bytes", rsp_num_bytes_rx, p_msg_rsp->len);
1363            nfc_status = NFC_STATUS_FAILED;
1364            GKI_freebuf (p_msg_rsp);
1365        }
1366        else
1367        {
1368            /* If this is the the final block, then set len to reflect only valid bytes (do not include padding to 16-byte boundary) */
1369            if ((p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT) && (p_cb->ndef_attrib.ln & 0x000F))
1370            {
1371                rsp_num_bytes_rx -= (16 - (p_cb->ndef_attrib.ln & 0x000F));
1372            }
1373
1374            p_msg_rsp->len = rsp_num_bytes_rx;
1375            read_data.p_data = p_msg_rsp;
1376            (*(rw_cb.p_cback)) (RW_T3T_CHECK_EVT, (tRW_DATA *) &read_data);
1377
1378            /* Send CHECK cmd for next NDEF segment, if needed */
1379            if (!(p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT))
1380            {
1381                if ((nfc_status = rw_t3t_send_next_ndef_check_cmd (p_cb)) == NFC_STATUS_OK)
1382                {
1383                    /* Still getting more segments. Don't send RW_T3T_CHECK_CPLT_EVT yet */
1384                    check_complete = FALSE;
1385                }
1386            }
1387        }
1388    }
1389
1390    /* Notify app of RW_T3T_CHECK_CPLT_EVT if entire NDEF has been read, or if failure */
1391    if (check_complete)
1392    {
1393        p_cb->rw_state = RW_T3T_STATE_IDLE;
1394        evt_data.status = nfc_status;
1395        (*(rw_cb.p_cback)) (RW_T3T_CHECK_CPLT_EVT, (tRW_DATA *) &evt_data);
1396    }
1397}
1398
1399
1400/*****************************************************************************
1401**
1402** Function         rw_t3t_act_handle_update_ndef_rsp
1403**
1404** Description      Handle response to NDEF write segment
1405**
1406** Returns          Nothing
1407**
1408*****************************************************************************/
1409void rw_t3t_act_handle_update_ndef_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1410{
1411    BOOLEAN update_complete = TRUE;
1412    tNFC_STATUS nfc_status = NFC_STATUS_OK;
1413    tRW_DATA evt_data;
1414    UINT8 *p_t3t_rsp = (UINT8 *) (p_msg_rsp+1) + p_msg_rsp->offset;
1415
1416    /* Check nfcid2 and status of response */
1417    if (  (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)                           /* verify response status code */
1418        ||(memcmp (p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM], NCI_NFCID2_LEN) != 0)  )   /* verify response IDm */
1419    {
1420        nfc_status = NFC_STATUS_FAILED;
1421    }
1422    /* Validate response opcode */
1423    else if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP)
1424    {
1425        RW_TRACE_ERROR2 ("Response error: expecting rsp_code %02X, but got %02X", T3T_MSG_OPC_UPDATE_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1426        nfc_status = NFC_STATUS_FAILED;
1427    }
1428    /* If this is response to final UPDATE, then update NDEF local size */
1429    else if (p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT)
1430    {
1431        /* If successful, update current NDEF size */
1432        p_cb->ndef_attrib.ln = p_cb->ndef_msg_len;
1433    }
1434    /*  If any more NDEF bytes to update, then send next UPDATE command */
1435    else if (p_cb->ndef_msg_bytes_sent < p_cb->ndef_msg_len)
1436    {
1437        /* Send UPDATE command for next segment of NDEF */
1438        if ((nfc_status = rw_t3t_send_next_ndef_update_cmd (p_cb)) == NFC_STATUS_OK)
1439        {
1440            /* Wait for update response */
1441            update_complete = FALSE;
1442        }
1443    }
1444    /*  Otherwise, no more NDEF bytes. Send final UPDATE for Attribute Information block */
1445    else
1446    {
1447        p_cb->flags |= RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
1448        if ((nfc_status = rw_t3t_send_update_ndef_attribute_cmd (p_cb, FALSE)) == NFC_STATUS_OK)
1449        {
1450            /* Wait for update response */
1451            update_complete = FALSE;
1452        }
1453    }
1454
1455    /* If update is completed, then notify app */
1456    if (update_complete)
1457    {
1458        p_cb->rw_state = RW_T3T_STATE_IDLE;
1459        evt_data.status = nfc_status;
1460        (*(rw_cb.p_cback)) (RW_T3T_UPDATE_CPLT_EVT, (tRW_DATA *) &evt_data);
1461    }
1462
1463
1464    GKI_freebuf (p_msg_rsp);
1465
1466    return;
1467}
1468
1469
1470/*****************************************************************************
1471**
1472** Function         rw_t3t_handle_get_sc_poll_rsp
1473**
1474** Description      Handle POLL response for getting system codes
1475**
1476** Returns          Nothing
1477**
1478*****************************************************************************/
1479static void rw_t3t_handle_get_sc_poll_rsp (tRW_T3T_CB *p_cb, UINT8 nci_status, UINT8 num_responses, UINT8 sensf_res_buf_size, UINT8 *p_sensf_res_buf)
1480{
1481    BT_HDR *p_cmd_buf;
1482    UINT8 *p, *p_cmd_start;
1483    UINT16 sc;
1484    tNFC_STATUS status = NFC_STATUS_FAILED;
1485
1486    /* If waiting for wildcard POLL */
1487    if (p_cb->rw_substate == RW_T3T_GET_SC_SST_POLL_WILDCARD)
1488    {
1489        /* Get the system code from the response */
1490        if (  (nci_status == NCI_STATUS_OK)
1491            &&(num_responses > 0)
1492            &&(sensf_res_buf_size >= (RW_T3T_SENSF_RES_RD_OFFSET + RW_T3T_SENSF_RES_RD_LEN))  )
1493        {
1494            p = &p_sensf_res_buf[RW_T3T_SENSF_RES_RD_OFFSET];
1495            BE_STREAM_TO_UINT16 (sc, p);
1496
1497            /* Handle felica lite */
1498            if (sc == T3T_SYSTEM_CODE_FELICA_LITE)
1499            {
1500                RW_TRACE_DEBUG1 ("FeliCa Lite tag detected (system code %04X)", sc);
1501                /* Store system code */
1502                p_cb->system_codes[p_cb->num_system_codes++] = sc;
1503
1504                /* Poll for NDEF system code */
1505                if ((status = (tNFC_STATUS) nci_snd_t3t_polling (T3T_SYSTEM_CODE_NDEF, T3T_POLL_RC_SC, 0)) == NCI_STATUS_OK)
1506                {
1507                    p_cb->rw_substate = RW_T3T_GET_SC_SST_POLL_NDEF;
1508                    p_cb->cur_poll_rc = 0;
1509                    p_cb->flags |= RW_T3T_FL_W4_GET_SC_POLL_RSP;
1510
1511                    /* start timer for waiting for responses */
1512                    rw_t3t_start_poll_timer (p_cb);
1513                }
1514            }
1515            else
1516            {
1517                /* All other types, send REQUEST_SYSTEM_CODE command */
1518                if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
1519                {
1520                    p_cb->rw_substate = RW_T3T_GET_SC_SST_REQUEST_SC;
1521
1522                    /* Construct T3T message */
1523                    p_cmd_start = p = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
1524                    UINT8_TO_STREAM (p, T3T_MSG_OPC_REQ_SYSTEMCODE_CMD);
1525                    ARRAY_TO_STREAM (p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1526
1527                    /* Fill in length field */
1528                    p_cmd_buf->len = (UINT16) (p - p_cmd_start);
1529
1530                    /* Send the T3T message */
1531                    status = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_GET_SYSTEM_CODES, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS);
1532                }
1533            }
1534        }
1535
1536        /* Error proceeding. Notify upper layer of system codes found so far */
1537        if (status != NFC_STATUS_OK)
1538        {
1539            rw_t3t_handle_get_system_codes_cplt ();
1540        }
1541    }
1542    /* If waiting for NDEF POLL */
1543    else if (p_cb->rw_substate == RW_T3T_GET_SC_SST_POLL_NDEF)
1544    {
1545        /* Validate response for NDEF poll */
1546        if ((nci_status == NCI_STATUS_OK) && (num_responses > 0))
1547        {
1548            /* Tag responded for NDEF poll */
1549            p_cb->system_codes[p_cb->num_system_codes++] = T3T_SYSTEM_CODE_NDEF;
1550        }
1551        rw_t3t_handle_get_system_codes_cplt ();
1552    }
1553}
1554
1555/*****************************************************************************
1556**
1557** Function         rw_t3t_handle_ndef_detect_poll_rsp
1558**
1559** Description      Handle POLL response for getting system codes
1560**
1561** Returns          Nothing
1562**
1563*****************************************************************************/
1564static void rw_t3t_handle_ndef_detect_poll_rsp (tRW_T3T_CB *p_cb, UINT8 nci_status, UINT8 num_responses, UINT8 sensf_res_buf_size, UINT8 *p_sensf_res_buf)
1565{
1566    BT_HDR *p_cmd_buf;
1567    UINT8 *p, *p_cmd_start;
1568    tRW_DATA evt_data;
1569
1570    /* Validate response for NDEF poll */
1571    if ((nci_status == NCI_STATUS_OK) && (num_responses > 0))
1572    {
1573        /* Tag responded for NDEF poll */
1574
1575        /* Read NDEF attribute block */
1576        if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
1577        {
1578            /* Construct T3T message */
1579            p = p_cmd_start = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
1580
1581            /* Add CHECK opcode to message  */
1582            UINT8_TO_STREAM (p, T3T_MSG_OPC_CHECK_CMD);
1583
1584            /* Add IDm to message */
1585            ARRAY_TO_STREAM (p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1586
1587            /* Add Service code list */
1588            UINT8_TO_STREAM (p, 1);                       /* Number of services (only 1 service: NDEF) */
1589            UINT16_TO_STREAM (p, T3T_MSG_NDEF_SC_RO);     /* Service code (little-endian format) */
1590
1591            /* Number of blocks */
1592            UINT8_TO_STREAM (p, 1);                       /* Number of blocks (only 1 block: NDEF Attribute Information ) */
1593
1594            /* Block List element: the NDEF attribute information block (block 0) */
1595            UINT8_TO_STREAM (p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
1596            UINT8_TO_STREAM (p, 0);
1597
1598            /* Calculate length of message */
1599            p_cmd_buf->len = (UINT16) (p - p_cmd_start);
1600
1601            /* Send the T3T message */
1602            if ((evt_data.status = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_DETECT_NDEF, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS)) == NFC_STATUS_OK)
1603            {
1604                /* CHECK command sent. Wait for response */
1605                return;
1606            }
1607        }
1608        nci_status = NFC_STATUS_FAILED;
1609    }
1610
1611    /* NDEF detection failed */
1612    p_cb->rw_state = RW_T3T_STATE_IDLE;
1613    evt_data.ndef.status = nci_status;
1614    evt_data.ndef.flags  = RW_NDEF_FL_UNKNOWN;
1615    (*(rw_cb.p_cback)) (RW_T3T_NDEF_DETECT_EVT, &evt_data);
1616}
1617
1618
1619/*****************************************************************************
1620**
1621** Function         rw_t3t_act_handle_get_sc_rsp
1622**
1623** Description      Handle response for getting system codes
1624**
1625** Returns          Nothing
1626**
1627*****************************************************************************/
1628void rw_t3t_act_handle_get_sc_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1629{
1630    UINT8 *p_t3t_rsp = (UINT8 *) (p_msg_rsp+1) + p_msg_rsp->offset;
1631    UINT8 *p;
1632    UINT16 sc;
1633    UINT8 num_sc, i;
1634
1635    /* Validate response opcode */
1636    if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_REQ_SYSTEMCODE_RSP)
1637    {
1638        RW_TRACE_ERROR2 ("Response error: expecting rsp_code %02X, but got %02X", T3T_MSG_OPC_REQ_SYSTEMCODE_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1639    }
1640    else
1641    {
1642        /* Point to number of systems parameter */
1643        p = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMSYS];
1644        STREAM_TO_UINT8 (num_sc, p);
1645
1646        /* Validate maximum */
1647        if (num_sc>T3T_MAX_SYSTEM_CODES)
1648        {
1649            RW_TRACE_DEBUG2 ("Tag's number of systems (%i) exceeds NFA max (%i)", num_sc, T3T_MAX_SYSTEM_CODES);
1650            num_sc = T3T_MAX_SYSTEM_CODES;
1651        }
1652
1653        for (i = 0; i < num_sc; i++)
1654        {
1655            BE_STREAM_TO_UINT16 (sc, p);
1656            p_cb->system_codes[p_cb->num_system_codes++] = sc;
1657        }
1658    }
1659    rw_t3t_handle_get_system_codes_cplt ();
1660
1661    GKI_freebuf (p_msg_rsp);
1662}
1663
1664/*****************************************************************************
1665**
1666** Function         rw_t3t_update_block
1667**
1668** Description      Send UPDATE command for single block (for formatting)
1669**
1670** Returns          tNFC_STATUS
1671**
1672*****************************************************************************/
1673tNFC_STATUS rw_t3t_update_block (tRW_T3T_CB *p_cb, UINT8 block_id, UINT8 *p_block_data)
1674{
1675    UINT8 *p_dst, *p_cmd_start;
1676    BT_HDR *p_cmd_buf;
1677    tNFC_STATUS status;
1678
1679    if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
1680    {
1681        p_dst = p_cmd_start = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
1682
1683        /* Add UPDATE opcode to message  */
1684        UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_UPDATE_CMD);
1685
1686        /* Add IDm to message */
1687        ARRAY_TO_STREAM (p_dst, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1688
1689        /* Add Service code list */
1690        UINT8_TO_STREAM (p_dst, 1);                      /* Number of services (only 1 service: NDEF) */
1691        UINT16_TO_STREAM (p_dst, T3T_MSG_NDEF_SC_RW);    /* Service code (little-endian format) */
1692
1693        /* Number of blocks */
1694        UINT8_TO_STREAM (p_dst, 1);
1695
1696        /* Add Block list element for MC */
1697        UINT8_TO_STREAM (p_dst, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
1698        UINT8_TO_STREAM (p_dst, block_id);
1699
1700        /* Copy MC data to UPDATE message */
1701        ARRAY_TO_STREAM (p_dst, p_block_data, T3T_MSG_BLOCKSIZE);
1702
1703        /* Calculate length of message */
1704        p_cmd_buf->len = (UINT16) (p_dst - p_cmd_start);
1705
1706        /* Send the T3T message */
1707        status = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_FORMAT, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS);
1708    }
1709    else
1710    {
1711        /* Unable to send UPDATE command */
1712        status = NFC_STATUS_NO_BUFFERS;
1713    }
1714
1715    return (status);
1716}
1717
1718/*****************************************************************************
1719**
1720** Function         rw_t3t_handle_fmt_poll_rsp
1721**
1722** Description      Handle POLL response for formatting felica-lite
1723**
1724** Returns          Nothing
1725**
1726*****************************************************************************/
1727static void rw_t3t_handle_fmt_poll_rsp (tRW_T3T_CB *p_cb, UINT8 nci_status, UINT8 num_responses, UINT8 sensf_res_buf_size, UINT8 *p_sensf_res_buf)
1728{
1729    BT_HDR *p_cmd_buf;
1730    UINT8 *p, *p_cmd_start;
1731    tRW_DATA evt_data;
1732
1733    evt_data.status = NFC_STATUS_OK;
1734
1735    /* Validate response for poll response */
1736    if ((nci_status == NCI_STATUS_OK) && (num_responses > 0))
1737    {
1738        /* Tag responded for Felica-Lite poll */
1739        /* Get MemoryControl block */
1740        RW_TRACE_DEBUG0 ("Felica-Lite tag detected...getting Memory Control block.");
1741
1742        /* Read NDEF attribute block */
1743        if ((p_cmd_buf = rw_t3t_get_cmd_buf ()) != NULL)
1744        {
1745            p_cb->rw_substate = RW_T3T_FMT_SST_CHECK_MC_BLK;
1746
1747            /* Construct T3T message */
1748            p = p_cmd_start = (UINT8 *) (p_cmd_buf+1) + p_cmd_buf->offset;
1749
1750            /* Add CHECK opcode to message  */
1751            UINT8_TO_STREAM (p, T3T_MSG_OPC_CHECK_CMD);
1752
1753            /* Add IDm to message */
1754            ARRAY_TO_STREAM (p, p_cb->peer_nfcid2, NCI_NFCID2_LEN);
1755
1756            /* Add Service code list */
1757            UINT8_TO_STREAM (p, 1);                       /* Number of services (only 1 service: NDEF) */
1758            UINT16_TO_STREAM (p, T3T_MSG_NDEF_SC_RO);     /* Service code (little-endian format) */
1759
1760            /* Number of blocks */
1761            UINT8_TO_STREAM (p, 1);                       /* Number of blocks (only 1 block: NDEF Attribute Information ) */
1762
1763            /* Block List element: the NDEF attribute information block (block 0) */
1764            UINT8_TO_STREAM (p, T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT);
1765            UINT8_TO_STREAM (p, T3T_MSG_FELICALITE_BLOCK_ID_MC);
1766
1767            /* Calculate length of message */
1768            p_cmd_buf->len = (UINT16) (p - p_cmd_start);
1769
1770            /* Send the T3T message */
1771            evt_data.status = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_FORMAT, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS);
1772        }
1773        else
1774        {
1775            RW_TRACE_ERROR0 ("Unable to allocate buffer to read MC block");
1776            evt_data.status = NFC_STATUS_NO_BUFFERS;
1777        }
1778    }
1779    else
1780    {
1781        RW_TRACE_ERROR0 ("Felica-Lite tag not detected");
1782        evt_data.status = NFC_STATUS_FAILED;
1783    }
1784
1785    /* If error, notify upper layer */
1786    if (evt_data.status != NFC_STATUS_OK)
1787    {
1788        rw_t3t_format_cplt (evt_data.status);
1789    }
1790}
1791
1792/*****************************************************************************
1793**
1794** Function         rw_t3t_act_handle_fmt_rsp
1795**
1796** Description      Handle response for formatting codes
1797**
1798** Returns          Nothing
1799**
1800*****************************************************************************/
1801void rw_t3t_act_handle_fmt_rsp (tRW_T3T_CB *p_cb, BT_HDR *p_msg_rsp)
1802{
1803    UINT8 *p_t3t_rsp = (UINT8 *) (p_msg_rsp+1) + p_msg_rsp->offset;
1804    UINT8 *p_mc;
1805    tRW_DATA evt_data;
1806
1807    evt_data.status = NFC_STATUS_OK;
1808
1809    /* Check tags's response for reading MemoryControl block */
1810    if (p_cb->rw_substate == RW_T3T_FMT_SST_CHECK_MC_BLK)
1811    {
1812        /* Validate response opcode */
1813        if (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_CHECK_RSP)
1814        {
1815            RW_TRACE_ERROR2 ("Response error: expecting rsp_code %02X, but got %02X", T3T_MSG_OPC_CHECK_RSP, p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE]);
1816            evt_data.status = NFC_STATUS_FAILED;
1817        }
1818        /* Validate status code and NFCID2 response from tag */
1819        else if (  (p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)                           /* verify response status code */
1820                 ||(memcmp (p_cb->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM], NCI_NFCID2_LEN) != 0)  )   /* verify response IDm */
1821        {
1822            evt_data.status = NFC_STATUS_FAILED;
1823        }
1824        else
1825        {
1826            /* Check if memory configuration (MC) block to see if SYS_OP=1 (NDEF enabled) */
1827            p_mc = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA];  /* Point to MC data of CHECK response */
1828
1829            if (p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] != 0x01)
1830            {
1831                /* Tag is not currently enabled for NDEF. Indicate that we need to update the MC block */
1832
1833                /* Set SYS_OP field to 0x01 (enable NDEF) */
1834                p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] = 0x01;
1835
1836                /* Construct and send UPDATE message to write MC block */
1837                p_cb->rw_substate = RW_T3T_FMT_SST_UPDATE_MC_BLK;
1838                evt_data.status = rw_t3t_update_block (p_cb, T3T_MSG_FELICALITE_BLOCK_ID_MC, p_mc);
1839            }
1840            else
1841            {
1842                /* SYS_OP=1: ndef already enabled. Just need to update attribute information block */
1843                p_cb->rw_substate = RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB;
1844                evt_data.status = rw_t3t_update_block (p_cb, 0, (UINT8 *) rw_t3t_default_attrib_info);
1845            }
1846        }
1847
1848        /* If error, notify upper layer */
1849        if (evt_data.status != NFC_STATUS_OK)
1850        {
1851            rw_t3t_format_cplt (evt_data.status);
1852        }
1853    }
1854    else if (p_cb->rw_substate == RW_T3T_FMT_SST_UPDATE_MC_BLK)
1855    {
1856        /* Validate response opcode */
1857        if (  (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP)
1858            ||(p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)  )
1859
1860        {
1861            RW_TRACE_ERROR2 ("Response error: rsp_code=%02X, status=%02X", p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE], p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1]);
1862            evt_data.status = NFC_STATUS_FAILED;
1863        }
1864        else
1865        {
1866            /* SYS_OP=1: ndef already enabled. Just need to update attribute information block */
1867            p_cb->rw_substate = RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB;
1868            evt_data.status = rw_t3t_update_block (p_cb, 0, (UINT8 *) rw_t3t_default_attrib_info);
1869        }
1870
1871        /* If error, notify upper layer */
1872        if (evt_data.status != NFC_STATUS_OK)
1873        {
1874            rw_t3t_format_cplt (evt_data.status);
1875        }
1876    }
1877    else if (p_cb->rw_substate == RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB)
1878    {
1879        /* Validate response opcode */
1880        if (  (p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] != T3T_MSG_OPC_UPDATE_RSP)
1881            ||(p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] != T3T_MSG_RSP_STATUS_OK)  )
1882
1883        {
1884            RW_TRACE_ERROR2 ("Response error: rsp_code=%02X, status=%02X", p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE], p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1]);
1885            evt_data.status = NFC_STATUS_FAILED;
1886        }
1887
1888
1889        rw_t3t_format_cplt (evt_data.status);
1890    }
1891
1892    GKI_freebuf (p_msg_rsp);
1893}
1894
1895/*******************************************************************************
1896**
1897** Function         rw_t3t_data_cback
1898**
1899** Description      This callback function receives the data from NFCC.
1900**
1901** Returns          none
1902**
1903*******************************************************************************/
1904void rw_t3t_data_cback (UINT8 conn_id, BT_HDR *p_msg)
1905{
1906    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
1907    BOOLEAN free_msg = FALSE;           /* if TRUE, free msg buffer before returning */
1908    UINT8 *p, sod;
1909
1910    /* Stop rsponse timer */
1911    nfc_stop_quick_timer (&p_cb->timer);
1912
1913#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
1914    /* Update rx stats */
1915    rw_main_update_rx_stats (p_msg->len);
1916#endif  /* RW_STATS_INCLUDED */
1917
1918    /* Check if we are expecting a response */
1919    if (p_cb->rw_state != RW_T3T_STATE_COMMAND_PENDING)
1920    {
1921        /*
1922        **  This must be raw frame response
1923        **  send raw frame to app with SoD
1924        */
1925        rw_t3t_act_handle_raw_senddata_rsp (p_cb, p_msg);
1926    }
1927    /* Sanity check: verify msg len is big enough to contain t3t header */
1928    else if (p_msg->len < T3T_MSG_RSP_COMMON_HDR_LEN)
1929    {
1930        RW_TRACE_ERROR1 ("T3T: invalid Type3 Tag Message (invalid len: %i)", p_msg->len);
1931        free_msg = TRUE;
1932
1933        rw_t3t_process_frame_error ();
1934    }
1935    else
1936    {
1937        /* Check for RF frame error */
1938        p = (UINT8 *) (p_msg+1) + p_msg->offset;
1939        sod = p[0];
1940        if (p[sod] != NCI_STATUS_OK)
1941        {
1942            RW_TRACE_ERROR1 ("T3T: rf frame error (crc status=%i)", p[sod]);
1943            GKI_freebuf (p_msg);
1944
1945            rw_t3t_process_frame_error ();
1946            return;
1947        }
1948
1949#if (BT_TRACE_PROTOCOL == TRUE)
1950        DispT3TagMessage (p_msg, TRUE);
1951#endif
1952
1953        /* Skip over SoD */
1954        p_msg->offset++;
1955        p_msg->len--;
1956
1957        /* Get response code */
1958        switch (p_cb->cur_cmd)
1959        {
1960            case RW_T3T_CMD_DETECT_NDEF:
1961                rw_t3t_act_handle_ndef_detect_rsp (p_cb, p_msg);
1962                break;
1963
1964            case RW_T3T_CMD_CHECK_NDEF:
1965                rw_t3t_act_handle_check_ndef_rsp (p_cb, p_msg);
1966                break;
1967
1968            case RW_T3T_CMD_UPDATE_NDEF:
1969                rw_t3t_act_handle_update_ndef_rsp (p_cb, p_msg);
1970                break;
1971
1972            case RW_T3T_CMD_CHECK:
1973                rw_t3t_act_handle_check_rsp (p_cb, p_msg);
1974                break;
1975
1976            case RW_T3T_CMD_UPDATE:
1977                rw_t3t_act_handle_update_rsp (p_cb, p_msg);
1978                break;
1979
1980            case RW_T3T_CMD_SEND_RAW_FRAME:
1981                rw_t3t_act_handle_raw_senddata_rsp (p_cb, p_msg);
1982                break;
1983
1984            case RW_T3T_CMD_GET_SYSTEM_CODES:
1985                rw_t3t_act_handle_get_sc_rsp (p_cb, p_msg);
1986                break;
1987
1988            case RW_T3T_CMD_FORMAT:
1989                rw_t3t_act_handle_fmt_rsp (p_cb, p_msg);
1990                break;
1991
1992            default:
1993                GKI_freebuf (p_msg);
1994                break;
1995        }
1996    }
1997
1998    if (free_msg)
1999    {
2000        GKI_freebuf (p_msg);
2001    }
2002}
2003
2004
2005/*******************************************************************************
2006**
2007** Function         rw_t3t_conn_cback
2008**
2009** Description      This callback function receives the events/data from NFCC.
2010**
2011** Returns          none
2012**
2013*******************************************************************************/
2014void rw_t3t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
2015{
2016    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2017    RW_TRACE_DEBUG2 ("rw_t3t_conn_cback: conn_id=%i, evt=0x%02x", conn_id, event);
2018
2019    /* Only handle NFC_RF_CONN_ID conn_id */
2020    if (conn_id != NFC_RF_CONN_ID)
2021    {
2022        return;
2023    }
2024
2025    switch (event)
2026    {
2027    case NFC_DEACTIVATE_CEVT:
2028        rw_t3t_unselect (NULL);
2029        break;
2030
2031    case NFC_DATA_CEVT:     /* check for status in tNFC_CONN */
2032        if (p_data->data.status == NFC_STATUS_OK)
2033        {
2034            rw_t3t_data_cback (conn_id, p_data->data.p_data);
2035            break;
2036        }
2037        /* Data event with error status...fall through to NFC_ERROR_CEVT case */
2038
2039
2040    case NFC_ERROR_CEVT:
2041        nfc_stop_quick_timer (&p_cb->timer);
2042
2043#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
2044        rw_main_update_trans_error_stats ();
2045#endif  /* RW_STATS_INCLUDED */
2046
2047        if (event == NFC_ERROR_CEVT)
2048            rw_t3t_process_error (NFC_STATUS_TIMEOUT);
2049        else
2050            rw_t3t_process_error (p_data->status);
2051        break;
2052
2053    default:
2054        break;
2055
2056    }
2057}
2058
2059
2060/*******************************************************************************
2061**
2062** Function         rw_t3t_select
2063**
2064** Description      Called by NFC manager when a Type3 tag has been activated
2065**
2066** Returns          NFC_STATUS_OK
2067**
2068*******************************************************************************/
2069tNFC_STATUS rw_t3t_select (UINT8 peer_nfcid2[NCI_RF_F_UID_LEN], UINT8 mrti_check, UINT8 mrti_update)
2070{
2071    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2072
2073    RW_TRACE_API0 ("rw_t3t_select");
2074
2075    memcpy (p_cb->peer_nfcid2, peer_nfcid2, NCI_NFCID2_LEN); /* Store tag's NFCID2 */
2076    p_cb->ndef_attrib.status = NFC_STATUS_NOT_INITIALIZED;  /* Indicate that NDEF detection has not been performed yet */
2077    p_cb->rw_state = RW_T3T_STATE_IDLE;
2078    p_cb->flags = 0;
2079
2080    /* Alloc cmd buf for retransmissions */
2081    if (p_cb->p_cur_cmd_buf ==  NULL)
2082    {
2083        if ((p_cb->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
2084        {
2085            RW_TRACE_ERROR0 ("rw_t3t_select: unable to allocate buffer for retransmission");
2086            p_cb->rw_state = RW_T3T_STATE_NOT_ACTIVATED;
2087            return (NFC_STATUS_FAILED);
2088        }
2089    }
2090
2091
2092    NFC_SetStaticRfCback (rw_t3t_conn_cback);
2093
2094    return NFC_STATUS_OK;
2095}
2096
2097
2098/*******************************************************************************
2099**
2100** Function         rw_t3t_unselect
2101**
2102** Description      Called by NFC manager when a Type3 tag has been de-activated
2103**
2104** Returns          NFC_STATUS_OK
2105**
2106*******************************************************************************/
2107static tNFC_STATUS rw_t3t_unselect (UINT8 peer_nfcid2[])
2108{
2109    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2110
2111#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
2112    /* Display stats */
2113    rw_main_log_stats ();
2114#endif  /* RW_STATS_INCLUDED */
2115
2116    /* Stop t3t timer (if started) */
2117    nfc_stop_quick_timer (&p_cb->timer);
2118
2119    /* Free cmd buf for retransmissions */
2120    if (p_cb->p_cur_cmd_buf)
2121    {
2122        GKI_freebuf (p_cb->p_cur_cmd_buf);
2123        p_cb->p_cur_cmd_buf = NULL;
2124    }
2125
2126    p_cb->rw_state = RW_T3T_STATE_NOT_ACTIVATED;
2127    NFC_SetStaticRfCback (NULL);
2128
2129    return NFC_STATUS_OK;
2130}
2131
2132
2133#if (BT_TRACE_VERBOSE == TRUE)
2134/*******************************************************************************
2135**
2136** Function         rw_t3t_cmd_str
2137**
2138** Description      Converts cmd_id to command string for logging
2139**
2140** Returns          command string
2141**
2142*******************************************************************************/
2143static char *rw_t3t_cmd_str (UINT8 cmd_id)
2144{
2145    switch (cmd_id)
2146    {
2147    case RW_T3T_CMD_DETECT_NDEF:
2148        return "RW_T3T_CMD_DETECT_NDEF";
2149
2150    case RW_T3T_CMD_CHECK_NDEF:
2151        return "RW_T3T_CMD_CHECK_NDEF";
2152
2153    case RW_T3T_CMD_UPDATE_NDEF:
2154        return "RW_T3T_CMD_UPDATE_NDEF";
2155
2156    case RW_T3T_CMD_CHECK:
2157        return "RW_T3T_CMD_CHECK";
2158
2159    case RW_T3T_CMD_UPDATE:
2160        return "RW_T3T_CMD_UPDATE";
2161
2162    case RW_T3T_CMD_SEND_RAW_FRAME:
2163        return "RW_T3T_CMD_SEND_RAW_FRAME";
2164
2165    case RW_T3T_CMD_GET_SYSTEM_CODES:
2166        return "RW_T3T_CMD_GET_SYSTEM_CODES";
2167
2168    default:
2169        return "Unknown";
2170    }
2171}
2172
2173
2174/*******************************************************************************
2175**
2176** Function         rw_t3t_state_str
2177**
2178** Description      Converts state_id to command string for logging
2179**
2180** Returns          command string
2181**
2182*******************************************************************************/
2183static char *rw_t3t_state_str (UINT8 state_id)
2184{
2185    switch (state_id)
2186    {
2187    case RW_T3T_STATE_NOT_ACTIVATED:
2188        return "RW_T3T_STATE_NOT_ACTIVATED";
2189
2190    case RW_T3T_STATE_IDLE:
2191        return "RW_T3T_STATE_IDLE";
2192
2193    case RW_T3T_STATE_COMMAND_PENDING:
2194        return "RW_T3T_STATE_COMMAND_PENDING";
2195
2196    default:
2197        return "Unknown";
2198    }
2199}
2200#endif
2201
2202/*****************************************************************************
2203**  Type3 Tag API Functions
2204*****************************************************************************/
2205
2206
2207/*****************************************************************************
2208**
2209** Function         RW_T3tDetectNDef
2210**
2211** Description
2212**      This function is used to perform NDEF detection on a Type 3 tag, and
2213**      retrieve the tag's NDEF attribute information (block 0).
2214**
2215**      Before using this API, the application must call RW_SelectTagType to
2216**      indicate that a Type 3 tag has been activated, and to provide the
2217**      tag's Manufacture ID (IDm) .
2218**
2219** Returns
2220**      NFC_STATUS_OK: ndef detection procedure started
2221**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2222**      NFC_STATUS_FAILED: other error
2223**
2224*****************************************************************************/
2225tNFC_STATUS RW_T3tDetectNDef (void)
2226{
2227    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2228    tNFC_STATUS retval = NFC_STATUS_OK;
2229
2230    RW_TRACE_API0 ("RW_T3tDetectNDef");
2231
2232    /* Check if we are in valid state to handle this API */
2233    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2234    {
2235        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2236        return (NFC_STATUS_FAILED);
2237    }
2238
2239    if ((retval = (tNFC_STATUS) nci_snd_t3t_polling (T3T_SYSTEM_CODE_NDEF, T3T_POLL_RC_SC, 0)) == NCI_STATUS_OK)
2240    {
2241        p_cb->cur_cmd = RW_T3T_CMD_DETECT_NDEF;
2242        p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
2243        p_cb->cur_poll_rc = 0;
2244        p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2245        p_cb->flags |= RW_T3T_FL_W4_NDEF_DETECT_POLL_RSP;
2246
2247        /* start timer for waiting for responses */
2248        rw_t3t_start_poll_timer (p_cb);
2249    }
2250
2251    return (retval);
2252}
2253
2254
2255/*****************************************************************************
2256**
2257** Function         RW_T3tCheckNDef
2258**
2259** Description
2260**      Retrieve NDEF contents from a Type3 tag.
2261**
2262**      The RW_T3T_CHECK_EVT event is used to notify the application for each
2263**      segment of NDEF data received. The RW_T3T_CHECK_CPLT_EVT event is used to
2264**      notify the application all segments have been received.
2265**
2266**      Before using this API, the RW_T3tDetectNDef function must be called to
2267**      verify that the tag contains NDEF data, and to retrieve the NDEF
2268**      attributes.
2269**
2270**      Internally, this command will be separated into multiple Tag 3 Check
2271**      commands (if necessary) - depending on the tag's Nbr (max number of
2272**      blocks per read) attribute.
2273**
2274** Returns
2275**      NFC_STATUS_OK: check command started
2276**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2277**      NFC_STATUS_FAILED: other error
2278**
2279*****************************************************************************/
2280tNFC_STATUS RW_T3tCheckNDef (void)
2281{
2282    tNFC_STATUS retval = NFC_STATUS_OK;
2283    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2284
2285    RW_TRACE_API0 ("RW_T3tCheckNDef");
2286
2287    /* Check if we are in valid state to handle this API */
2288    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2289    {
2290        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2291        return (NFC_STATUS_FAILED);
2292    }
2293    else if (p_cb->ndef_attrib.status != NFC_STATUS_OK)       /* NDEF detection not performed yet? */
2294    {
2295        RW_TRACE_ERROR0 ("Error: NDEF detection not performed yet");
2296        return (NFC_STATUS_NOT_INITIALIZED);
2297    }
2298    else if (p_cb->ndef_attrib.ln == 0)
2299    {
2300        RW_TRACE_ERROR0 ("Type 3 tag contains empty NDEF message");
2301        return (NFC_STATUS_FAILED);
2302    }
2303
2304    /* Check number of blocks needed for this update */
2305    p_cb->flags &= ~RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
2306    p_cb->ndef_rx_offset = 0;
2307    retval = rw_t3t_send_next_ndef_check_cmd (p_cb);
2308
2309    return (retval);
2310}
2311
2312/*****************************************************************************
2313**
2314** Function         RW_T3tUpdateNDef
2315**
2316** Description
2317**      Write NDEF contents to a Type3 tag.
2318**
2319**      The RW_T3T_UPDATE_CPLT_EVT callback event will be used to notify the
2320**      application of the response.
2321**
2322**      Before using this API, the RW_T3tDetectNDef function must be called to
2323**      verify that the tag contains NDEF data, and to retrieve the NDEF
2324**      attributes.
2325**
2326**      Internally, this command will be separated into multiple Tag 3 Update
2327**      commands (if necessary) - depending on the tag's Nbw (max number of
2328**      blocks per write) attribute.
2329**
2330** Returns
2331**      NFC_STATUS_OK: check command started
2332**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2333**      NFC_STATUS_REFUSED: tag is read-only
2334**      NFC_STATUS_BUFFER_FULL: len exceeds tag's maximum size
2335**      NFC_STATUS_FAILED: other error
2336**
2337*****************************************************************************/
2338tNFC_STATUS RW_T3tUpdateNDef (UINT32 len, UINT8 *p_data)
2339{
2340    tNFC_STATUS retval = NFC_STATUS_OK;
2341    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2342
2343    RW_TRACE_API1 ("RW_T3tUpdateNDef (len=%i)", len);
2344
2345    /* Check if we are in valid state to handle this API */
2346    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2347    {
2348        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2349        return (NFC_STATUS_FAILED);
2350    }
2351    else if (p_cb->ndef_attrib.status != NFC_STATUS_OK)       /* NDEF detection not performed yet? */
2352    {
2353        RW_TRACE_ERROR0 ("Error: NDEF detection not performed yet");
2354        return (NFC_STATUS_NOT_INITIALIZED);
2355    }
2356    else if (len > (((UINT32)p_cb->ndef_attrib.nmaxb) * 16))                /* Len exceed's tag's NDEF memory? */
2357    {
2358        return (NFC_STATUS_BUFFER_FULL);
2359    }
2360    else if (p_cb->ndef_attrib.rwflag == T3T_MSG_NDEF_RWFLAG_RO)/* Tag's NDEF memory is read-only? */
2361    {
2362        return (NFC_STATUS_REFUSED);
2363    }
2364
2365    /* Check number of blocks needed for this update */
2366    p_cb->flags &= ~RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
2367    p_cb->ndef_msg_bytes_sent = 0;
2368    p_cb->ndef_msg_len = len;
2369    p_cb->ndef_msg = p_data;
2370
2371    /* Send initial UPDATE command for NDEF Attribute Info */
2372    retval = rw_t3t_send_update_ndef_attribute_cmd (p_cb, TRUE);
2373
2374    return (retval);
2375}
2376
2377/*****************************************************************************
2378**
2379** Function         RW_T3tCheck
2380**
2381** Description
2382**      Read (non-NDEF) contents from a Type3 tag.
2383**
2384**      The RW_READ_EVT event is used to notify the application for each
2385**      segment of NDEF data received. The RW_READ_CPLT_EVT event is used to
2386**      notify the application all segments have been received.
2387**
2388**      Before using this API, the application must call RW_SelectTagType to
2389**      indicate that a Type 3 tag has been activated, and to provide the
2390**      tag's Manufacture ID (IDm) .
2391**
2392** Returns
2393**      NFC_STATUS_OK: check command started
2394**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2395**      NFC_STATUS_FAILED: other error
2396**
2397*****************************************************************************/
2398tNFC_STATUS RW_T3tCheck (UINT8 num_blocks, tT3T_BLOCK_DESC *t3t_blocks)
2399{
2400    tNFC_STATUS retval = NFC_STATUS_OK;
2401    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2402
2403    RW_TRACE_API1 ("RW_T3tCheck (num_blocks = %i)", num_blocks);
2404
2405    /* Check if we are in valid state to handle this API */
2406    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2407    {
2408        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2409        return (NFC_STATUS_FAILED);
2410    }
2411
2412    /* Send the CHECK command */
2413    retval = rw_t3t_send_check_cmd (p_cb, num_blocks, t3t_blocks);
2414
2415    return (retval);
2416}
2417
2418/*****************************************************************************
2419**
2420** Function         RW_T3tUpdate
2421**
2422** Description
2423**      Write (non-NDEF) contents to a Type3 tag.
2424**
2425**      The RW_WRITE_CPLT_EVT event is used to notify the application all
2426**      segments have been received.
2427**
2428**      Before using this API, the application must call RW_SelectTagType to
2429**      indicate that a Type 3 tag has been activated, and to provide the tag's
2430**      Manufacture ID (IDm) .
2431**
2432** Returns
2433**      NFC_STATUS_OK: check command started
2434**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2435**      NFC_STATUS_FAILED: other error
2436**
2437*****************************************************************************/
2438tNFC_STATUS RW_T3tUpdate (UINT8 num_blocks, tT3T_BLOCK_DESC *t3t_blocks, UINT8 *p_data)
2439{
2440    tNFC_STATUS retval = NFC_STATUS_OK;
2441    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2442
2443    RW_TRACE_API1 ("RW_T3tUpdate (num_blocks = %i)", num_blocks);
2444
2445    /* Check if we are in valid state to handle this API */
2446    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2447    {
2448        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2449        return (NFC_STATUS_FAILED);
2450    }
2451
2452    /* Send the UPDATE command */
2453    retval = rw_t3t_send_update_cmd (p_cb, num_blocks, t3t_blocks, p_data);
2454
2455    return (retval);
2456}
2457
2458/*****************************************************************************
2459**
2460** Function         RW_T3tPresenceCheck
2461**
2462** Description
2463**      Check if the tag is still in the field.
2464**
2465**      The RW_T3T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
2466**      or non-presence.
2467**
2468** Returns
2469**      NFC_STATUS_OK, if raw data frame sent
2470**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2471**      NFC_STATUS_FAILED: other error
2472**
2473*****************************************************************************/
2474tNFC_STATUS RW_T3tPresenceCheck (void)
2475{
2476    tNFC_STATUS retval = NFC_STATUS_OK;
2477    tRW_DATA evt_data;
2478    tRW_CB *p_rw_cb = &rw_cb;
2479
2480    RW_TRACE_API0 ("RW_T3tPresenceCheck");
2481
2482    /* If RW_SelectTagType was not called (no conn_callback) return failure */
2483    if (!(p_rw_cb->p_cback))
2484    {
2485        retval = NFC_STATUS_FAILED;
2486    }
2487    /* If we are not activated, then RW_T3T_PRESENCE_CHECK_EVT status=FAIL */
2488    else if (p_rw_cb->tcb.t3t.rw_state == RW_T3T_STATE_NOT_ACTIVATED)
2489    {
2490        evt_data.status = NFC_STATUS_FAILED;
2491        (*p_rw_cb->p_cback) (RW_T3T_PRESENCE_CHECK_EVT, &evt_data);
2492    }
2493    /* If command is pending */
2494    else if (p_rw_cb->tcb.t3t.rw_state == RW_T3T_STATE_COMMAND_PENDING)
2495    {
2496        /* If already performing presence check, return error */
2497        if (p_rw_cb->tcb.t3t.flags & RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP)
2498        {
2499            RW_TRACE_DEBUG0 ("RW_T3tPresenceCheck already in progress");
2500            retval = NFC_STATUS_FAILED;
2501        }
2502        /* If busy with any other command, assume that the tag is present */
2503        else
2504        {
2505            evt_data.status = NFC_STATUS_OK;
2506            (*p_rw_cb->p_cback) (RW_T3T_PRESENCE_CHECK_EVT, &evt_data);
2507        }
2508    }
2509    else
2510    {
2511        /* IDLE state: send POLL command */
2512        if ((retval = (tNFC_STATUS) nci_snd_t3t_polling (0xFFFF, T3T_POLL_RC_SC, 0)) == NCI_STATUS_OK)
2513        {
2514            p_rw_cb->tcb.t3t.flags |= RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP;
2515            p_rw_cb->tcb.t3t.rw_state = RW_T3T_STATE_COMMAND_PENDING;
2516            p_rw_cb->tcb.t3t.cur_poll_rc = 0;
2517
2518            /* start timer for waiting for responses */
2519            rw_t3t_start_poll_timer (&p_rw_cb->tcb.t3t);
2520        }
2521        else
2522        {
2523            RW_TRACE_DEBUG1 ("RW_T3tPresenceCheck error sending NCI_RF_T3T_POLLING cmd (status = 0x%0x)", retval);
2524        }
2525    }
2526
2527    return (retval);
2528}
2529
2530/*****************************************************************************
2531**
2532** Function         RW_T3tPoll
2533**
2534** Description
2535**      Send POLL command
2536**
2537** Returns
2538**      NFC_STATUS_OK, if raw data frame sent
2539**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2540**      NFC_STATUS_FAILED: other error
2541**
2542*****************************************************************************/
2543tNFC_STATUS RW_T3tPoll (UINT16 system_code, tT3T_POLL_RC rc, UINT8 tsn)
2544{
2545    tNFC_STATUS retval = NFC_STATUS_OK;
2546    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2547
2548    RW_TRACE_API0 ("RW_T3tPoll");
2549
2550    /* Check if we are in valid state to handle this API */
2551    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2552    {
2553        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2554        return (NFC_STATUS_FAILED);
2555    }
2556
2557    if ((retval = (tNFC_STATUS) nci_snd_t3t_polling (system_code, (UINT8) rc, tsn)) == NCI_STATUS_OK)
2558    {
2559        /* start timer for waiting for responses */
2560        p_cb->cur_poll_rc = rc;
2561        p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2562        rw_t3t_start_poll_timer (p_cb);
2563    }
2564
2565
2566    return (retval);
2567}
2568
2569/*****************************************************************************
2570**
2571** Function         RW_T3tSendRawFrame
2572**
2573** Description
2574**      This function is called to send a raw data frame to the peer device.
2575**      When type 3 tag receives response from peer, the callback function
2576**      will be called with a RW_T3T_RAW_FRAME_EVT [Table 6].
2577**
2578**      Before using this API, the application must call RW_SelectTagType to
2579**      indicate that a Type 3 tag has been activated.
2580**
2581**      The raw frame should be a properly formatted Type 3 tag message.
2582**
2583** Returns
2584**      NFC_STATUS_OK, if raw data frame sent
2585**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2586**      NFC_STATUS_FAILED: other error
2587**
2588*****************************************************************************/
2589tNFC_STATUS RW_T3tSendRawFrame (UINT16 len, UINT8 *p_data)
2590{
2591    tNFC_STATUS retval = NFC_STATUS_OK;
2592    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2593
2594    RW_TRACE_API1 ("RW_T3tSendRawFrame (len = %i)", len);
2595
2596    /* Check if we are in valid state to handle this API */
2597    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2598    {
2599        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2600        return (NFC_STATUS_FAILED);
2601    }
2602
2603    /* Send the UPDATE command */
2604    retval = rw_t3t_send_raw_frame (p_cb, len ,p_data);
2605
2606    return (retval);
2607}
2608
2609/*****************************************************************************
2610**
2611** Function         RW_T3tGetSystemCodes
2612**
2613** Description
2614**      Get systems codes supported by the activated tag:
2615**              Poll for wildcard (FFFF):
2616**                  - If felica-lite code then poll for ndef (12fc)
2617**                  - Otherwise send RequestSystmCode command to get
2618**                    system codes.
2619**
2620**      Before using this API, the application must call RW_SelectTagType to
2621**      indicate that a Type 3 tag has been activated.
2622**
2623** Returns
2624**      NFC_STATUS_OK, if raw data frame sent
2625**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2626**      NFC_STATUS_FAILED: other error
2627**
2628*****************************************************************************/
2629tNFC_STATUS RW_T3tGetSystemCodes (void)
2630{
2631    tNFC_STATUS retval = NFC_STATUS_OK;
2632    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2633
2634    RW_TRACE_API0 ("RW_T3tGetSystemCodes");
2635
2636    /* Check if we are in valid state to handle this API */
2637    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2638    {
2639        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2640        return (NFC_STATUS_FAILED);
2641    }
2642    else
2643    {
2644        if ((retval = (tNFC_STATUS) nci_snd_t3t_polling (0xFFFF, T3T_POLL_RC_SC, 0)) == NCI_STATUS_OK)
2645        {
2646            p_cb->cur_cmd = RW_T3T_CMD_GET_SYSTEM_CODES;
2647            p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
2648            p_cb->cur_poll_rc = T3T_POLL_RC_SC;
2649            p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2650            p_cb->rw_substate = RW_T3T_GET_SC_SST_POLL_WILDCARD;
2651            p_cb->flags |= RW_T3T_FL_W4_GET_SC_POLL_RSP;
2652            p_cb->num_system_codes = 0;
2653
2654            /* start timer for waiting for responses */
2655            rw_t3t_start_poll_timer (p_cb);
2656        }
2657    }
2658
2659
2660
2661    return (retval);
2662}
2663
2664/*****************************************************************************
2665**
2666** Function         RW_T3tFormatNDef
2667**
2668** Description
2669**      Format a type-3 tag for NDEF.
2670**
2671**      Only Felica-Lite tags are supported by this API. The
2672**      RW_T3T_FORMAT_CPLT_EVT is used to notify the status of the operation.
2673**
2674** Returns
2675**      NFC_STATUS_OK: ndef detection procedure started
2676**      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2677**      NFC_STATUS_FAILED: other error
2678**
2679*****************************************************************************/
2680tNFC_STATUS RW_T3tFormatNDef (void)
2681{
2682    tNFC_STATUS retval = NFC_STATUS_OK;
2683    tRW_T3T_CB *p_cb = &rw_cb.tcb.t3t;
2684
2685    RW_TRACE_API0 ("RW_T3tFormatNDef");
2686
2687    /* Check if we are in valid state to handle this API */
2688    if (p_cb->rw_state != RW_T3T_STATE_IDLE)
2689    {
2690        RW_TRACE_ERROR1 ("Error: invalid state to handle API (0x%x)", p_cb->rw_state);
2691        return (NFC_STATUS_FAILED);
2692    }
2693    else
2694    {
2695        /* Poll tag, to see if Felica-Lite system is supported */
2696        if ((retval = (tNFC_STATUS) nci_snd_t3t_polling (T3T_SYSTEM_CODE_FELICA_LITE, T3T_POLL_RC_SC, 0)) == NCI_STATUS_OK)
2697        {
2698            p_cb->cur_cmd = RW_T3T_CMD_FORMAT;
2699            p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
2700            p_cb->cur_poll_rc = T3T_POLL_RC_SC;
2701            p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
2702            p_cb->rw_substate = RW_T3T_FMT_SST_POLL_FELICA_LITE;
2703            p_cb->flags |= RW_T3T_FL_W4_FMT_FELICA_LITE_POLL_RSP;
2704
2705            /* start timer for waiting for responses */
2706            rw_t3t_start_poll_timer (p_cb);
2707        }
2708    }
2709
2710
2711
2712    return (retval);
2713}
2714