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