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