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