• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 NXP Semiconductors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /*!
17 * \file  phHal4Nfc_Reader.c
18 * \brief Hal4Nfc Reader source.
19 *
20 * Project: NFC-FRI 1.1
21 *
22 * $Date: Mon May 31 11:43:43 2010 $
23 * $Author: ing07385 $
24 * $Revision: 1.120 $
25 * $Aliases: NFC_FRI1.1_WK1023_R35_1 $
26 *
27 */
28 
29 /* ---------------------------Include files ------------------------------------*/
30 #include <phHal4Nfc.h>
31 #include <phHal4Nfc_Internal.h>
32 #include <phOsalNfc.h>
33 #include <phHciNfc.h>
34 #include <phOsalNfc_Timer.h>
35 #include <phNfcConfig.h>
36 
37 
38 /* ------------------------------- Macros ------------------------------------*/
39 #define PH_HAL4NFC_CMD_LENGTH      PHHAL_MAX_DATASIZE+12/**< Cmd length used
40                                                               for Transceive*/
41 #define PH_HAL4NFC_MAX_TRCV_LEN                     4096 /**<Only a max of 1KB
42                                                               can be sent at
43                                                               a time*/
44 #define PH_HAL4NFC_FLAG_0                              0
45 
46 #define PH_HAL4NFC_FLAG_1                              1
47 
48 #define PH_HAL4NFC_SEL_SECTOR1_BYTE0                0xC2
49 #define PH_HAL4NFC_SEL_SECTOR1_BYTE1                0xFF
50 
51 #define PH_HAL4NFC_SEL_SECTOR2_BYTE0                0x02
52 #define PH_HAL4NFC_SEL_SECTOR2_BYTE_RESERVED        0x00
53 
54 phHal4Nfc_Hal4Ctxt_t *gpHal4Ctxt;
55 
56 /* --------------------Structures and enumerations --------------------------*/
57 
58 static void phHal4Nfc_Iso_3A_Transceive(
59                         phHal_sTransceiveInfo_t   *psTransceiveInfo,
60                         phHal4Nfc_Hal4Ctxt_t      *Hal4Ctxt
61                         );
62 
63 static void phHal4Nfc_MifareTransceive(
64                         phHal_sTransceiveInfo_t   *psTransceiveInfo,
65                         phHal_sRemoteDevInformation_t  *psRemoteDevInfo,
66                         phHal4Nfc_Hal4Ctxt_t      *Hal4Ctxt
67                         );
68 
69 /*Allows to connect to a single, specific, already known Remote Device.*/
phHal4Nfc_Connect(phHal_sHwReference_t * psHwReference,phHal_sRemoteDevInformation_t * psRemoteDevInfo,pphHal4Nfc_ConnectCallback_t pNotifyConnectCb,void * pContext)70 NFCSTATUS phHal4Nfc_Connect(
71                             phHal_sHwReference_t          *psHwReference,
72                             phHal_sRemoteDevInformation_t *psRemoteDevInfo,
73                             pphHal4Nfc_ConnectCallback_t   pNotifyConnectCb,
74                             void                          *pContext
75                             )
76 {
77     NFCSTATUS RetStatus = NFCSTATUS_SUCCESS;
78     phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL;
79     uint8_t RemoteDevCount = 0;
80     int32_t MemCmpRet = 0;
81     /*NULL chks*/
82     if(NULL == psHwReference
83         || NULL == pNotifyConnectCb
84         || NULL == psRemoteDevInfo)
85     {
86         phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1);
87         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER);
88     }
89     /*Check initialised state*/
90     else if((NULL == psHwReference->hal_context)
91                         || (((phHal4Nfc_Hal4Ctxt_t *)
92                                 psHwReference->hal_context)->Hal4CurrentState
93                                                < eHal4StateOpenAndReady)
94                         || (((phHal4Nfc_Hal4Ctxt_t *)
95                                 psHwReference->hal_context)->Hal4NextState
96                                                == eHal4StateClosed))
97     {
98         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED);
99     }
100     else if ((psRemoteDevInfo ==
101              ((phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context)->
102                 sTgtConnectInfo.psConnectedDevice)
103              &&((phHal_eNfcIP1_Target == psRemoteDevInfo->RemDevType)
104                 ||(phHal_eJewel_PICC == psRemoteDevInfo->RemDevType)))
105     {
106         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_FEATURE_NOT_SUPPORTED);
107     }
108     else
109     {
110         /*Get Hal ctxt from hardware reference*/
111         Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context;
112         /*Register upper layer context*/
113         Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext;
114         /*Register upper layer callback*/
115         Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = pNotifyConnectCb;
116         /*Allow Connect only if no other remote device is connected*/
117         if((eHal4StateTargetDiscovered == Hal4Ctxt->Hal4CurrentState)
118             && (NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice))
119         {
120             RemoteDevCount = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices;
121             while(0 != RemoteDevCount)
122             {
123                 RemoteDevCount--;
124                 /*Check if handle provided by upper layer matches with any
125                   remote device in the list*/
126                 if(psRemoteDevInfo
127                     == (Hal4Ctxt->rem_dev_list[RemoteDevCount]))
128                 {
129 
130                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice
131                                   = Hal4Ctxt->rem_dev_list[RemoteDevCount];
132                     break;
133                 }
134             }/*End of while*/
135 
136             if(NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)
137             {
138                 /*No matching device handle in list*/
139                 RetStatus = PHNFCSTVAL(CID_NFC_HAL ,
140                                         NFCSTATUS_INVALID_REMOTE_DEVICE);
141             }
142             else
143             {
144                 MemCmpRet = phOsalNfc_MemCompare(
145                     (void *)&(psRemoteDevInfo->RemoteDevInfo),
146                     (void *)&(Hal4Ctxt->rem_dev_list[Hal4Ctxt
147                     ->psADDCtxtInfo->nbr_of_devices - 1]->RemoteDevInfo),
148                     sizeof(phHal_uRemoteDevInfo_t));
149 
150                 /*If device is already selected issue connect from here*/
151                 if(0 == MemCmpRet)
152                 {
153                     RetStatus = phHciNfc_Connect(Hal4Ctxt->psHciHandle,
154                         (void *)psHwReference,
155                         Hal4Ctxt->rem_dev_list[RemoteDevCount]);
156                     if(NFCSTATUS_PENDING == RetStatus)
157                     {
158                         Hal4Ctxt->Hal4NextState = eHal4StateTargetConnected;
159                     }
160 
161                 }
162                 else/*Select the matching device to connect to*/
163                 {
164                     RetStatus = phHciNfc_Reactivate (
165                         Hal4Ctxt->psHciHandle,
166                         (void *)psHwReference,
167                         Hal4Ctxt->rem_dev_list[RemoteDevCount]
168                         );
169                     Hal4Ctxt->Hal4NextState = eHal4StateTargetActivate;
170                 }
171                 if(NFCSTATUS_PENDING != RetStatus)
172                 {
173                     /*Rollback state*/
174                     Hal4Ctxt->Hal4CurrentState = eHal4StateOpenAndReady;
175                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice =  NULL;
176                     Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = NULL;
177                     Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL;
178                 }
179             }
180         }
181         /*Issue Reconnect*/
182         else if(psRemoteDevInfo ==
183                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)
184         {
185             RetStatus = phHciNfc_Reactivate (
186                 Hal4Ctxt->psHciHandle,
187                 (void *)psHwReference,
188                 psRemoteDevInfo
189                 );
190                 Hal4Ctxt->Hal4NextState = eHal4StateTargetActivate;
191         }
192 #ifdef RECONNECT_SUPPORT
193         else if (psRemoteDevInfo !=
194                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)
195         {
196             phHal_sRemoteDevInformation_t           *ps_store_connected_device =
197                                                 Hal4Ctxt->sTgtConnectInfo.psConnectedDevice;
198 
199             RemoteDevCount = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices;
200 
201             while (0 != RemoteDevCount)
202             {
203                 RemoteDevCount--;
204                 /*Check if handle provided by upper layer matches with any
205                   remote device in the list*/
206                 if(psRemoteDevInfo == (Hal4Ctxt->rem_dev_list[RemoteDevCount]))
207                 {
208                     break;
209                 }
210             }/*End of while*/
211 
212             if (ps_store_connected_device ==
213                 Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)
214             {
215                 RetStatus = phHciNfc_Reactivate (Hal4Ctxt->psHciHandle,
216                                                 (void *)psHwReference,
217                                                 psRemoteDevInfo);
218 
219                 if (NFCSTATUS_PENDING == RetStatus)
220                 {
221                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice =
222                                     Hal4Ctxt->rem_dev_list[RemoteDevCount];
223                     Hal4Ctxt->Hal4NextState = eHal4StateTargetActivate;
224                 }
225             }
226         }
227 #endif /* #ifdef RECONNECT_SUPPORT */
228         else if(NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)
229         {
230             /*Wrong state to issue connect*/
231             RetStatus = PHNFCSTVAL(CID_NFC_HAL,
232                                     NFCSTATUS_INVALID_REMOTE_DEVICE);
233         }
234         else/*No Target or already connected to device*/
235         {
236             RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_FAILED);
237         }
238 
239     }
240     return RetStatus;
241 }
242 
243 /*For Ordering Transceive Info for ISO_3A type tags*/
phHal4Nfc_Iso_3A_Transceive(phHal_sTransceiveInfo_t * psTransceiveInfo,phHal4Nfc_Hal4Ctxt_t * Hal4Ctxt)244 static void phHal4Nfc_Iso_3A_Transceive(
245                         phHal_sTransceiveInfo_t   *psTransceiveInfo,
246                         phHal4Nfc_Hal4Ctxt_t      *Hal4Ctxt
247                         )
248 {
249     uint16_t i;
250     uint16_t counter= 0;
251     /* Mifare UL, Keep MIFARE RAW command as it is */
252     Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type
253                     = (uint8_t)psTransceiveInfo->cmd.MfCmd;
254     /* Set flags for Select Sector */
255     if (psTransceiveInfo->sSendData.buffer[0] != phHal_eMifareWrite4)
256     {
257         if (Hal4Ctxt->SelectSectorFlag == PH_HAL4NFC_FLAG_0)
258         {
259             /* First Select Sector command */
260             if ((psTransceiveInfo->sSendData.buffer[1] == PH_HAL4NFC_SEL_SECTOR1_BYTE0) &&
261                 (psTransceiveInfo->sSendData.buffer[2] == PH_HAL4NFC_SEL_SECTOR1_BYTE1))
262             {
263                 Hal4Ctxt->SelectSectorFlag++;
264                 PHDBG_INFO("Inside 3ATrancv,first cmd, SelectSectorFlag is 1");
265                 for (i = 1; i < psTransceiveInfo->sSendData.length; i++)
266                 {
267                     psTransceiveInfo->sSendData.buffer[i - 1] =
268                         psTransceiveInfo->sSendData.buffer[i];
269                 }
270 
271                 psTransceiveInfo->sSendData.length--;
272             }
273             else
274             {
275                 PHDBG_INFO("Inside 3ATrancv,first cmd,setting SelectSectorFlag 0");
276                 Hal4Ctxt->SelectSectorFlag = 0;
277             }
278         }
279         else if (Hal4Ctxt->SelectSectorFlag == PH_HAL4NFC_FLAG_1)
280         {
281             if ((psTransceiveInfo->sSendData.buffer[1] < PH_HAL4NFC_SEL_SECTOR2_BYTE0) &&
282                 (psTransceiveInfo->sSendData.buffer[2] == PH_HAL4NFC_SEL_SECTOR2_BYTE_RESERVED) &&
283                 (psTransceiveInfo->sSendData.buffer[3] == PH_HAL4NFC_SEL_SECTOR2_BYTE_RESERVED) &&
284                 (psTransceiveInfo->sSendData.buffer[4] == PH_HAL4NFC_SEL_SECTOR2_BYTE_RESERVED))
285             {
286                 Hal4Ctxt->SelectSectorFlag++;
287                 PHDBG_INFO("Inside 3ATrancv,2nd cmd, SelectSectorFlag set to 2");
288                 for (i = 1; i < psTransceiveInfo->sSendData.length; i++)
289                 {
290                     psTransceiveInfo->sSendData.buffer[i - 1] =
291                         psTransceiveInfo->sSendData.buffer[i];
292                 }
293 
294                 psTransceiveInfo->sSendData.length--;
295             }
296             else
297             {
298                 PHDBG_INFO("Inside 3ATrancv,2nd cmd, SelectSectorFlag set to 0");
299                 Hal4Ctxt->SelectSectorFlag = 0;
300             }
301         }
302         else
303         {
304             Hal4Ctxt->SelectSectorFlag = 0;
305         }
306     }
307     else
308     {
309         PHDBG_INFO("Inside 3ATrancv,Mifarewrite4");
310         /* Convert MIFARE RAW to MIFARE CMD */
311         if (psTransceiveInfo->cmd.MfCmd == phHal_eMifareRaw)
312         {
313             psTransceiveInfo->cmd.MfCmd =
314                 (phHal_eMifareCmdList_t)psTransceiveInfo->sSendData.buffer[0];
315 
316             Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type =
317                 (uint8_t)psTransceiveInfo->cmd.MfCmd;
318 
319             Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.addr =
320                 psTransceiveInfo->addr =
321                 psTransceiveInfo->sSendData.buffer[1];
322 
323             for (counter = 2; counter < psTransceiveInfo->sSendData.length;
324                  counter++)
325             {
326                 psTransceiveInfo->sSendData.buffer[counter - 2] =
327                     psTransceiveInfo->sSendData.buffer[counter];
328             }
329             PHDBG_INFO("Hal4:Inside 3A_Trcv() ,minus length by 4");
330             psTransceiveInfo->sSendData.length =
331                 psTransceiveInfo->sSendData.length - 4;
332         }
333         else
334         {
335             Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type
336                         = (uint8_t)psTransceiveInfo->cmd.MfCmd;
337         }
338     }
339     return;
340 }
341 
342 /*For Ordering Transceive Info for Mifare tags*/
phHal4Nfc_MifareTransceive(phHal_sTransceiveInfo_t * psTransceiveInfo,phHal_sRemoteDevInformation_t * psRemoteDevInfo,phHal4Nfc_Hal4Ctxt_t * Hal4Ctxt)343 static void phHal4Nfc_MifareTransceive(
344                         phHal_sTransceiveInfo_t   *psTransceiveInfo,
345                         phHal_sRemoteDevInformation_t  *psRemoteDevInfo,
346                         phHal4Nfc_Hal4Ctxt_t      *Hal4Ctxt
347                         )
348 {
349     uint16_t counter;
350     if (
351 #ifndef DISABLE_MIFARE_UL_WRITE_WORKAROUND
352         phHal_eMifareWrite4 != psTransceiveInfo->sSendData.buffer[0]
353 #else
354         1
355 #endif/*#ifndef DISABLE_MIFARE_UL_WRITE_WORKAROUND*/
356         )
357 
358     {
359         /* Mifare UL, Keep MIFARE RAW command as it is */
360         Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type
361                         = (uint8_t)psTransceiveInfo->cmd.MfCmd;
362 
363     }
364     else
365     {
366         /* Convert MIFARE RAW to MIFARE CMD */
367         if (psTransceiveInfo->cmd.MfCmd == phHal_eMifareRaw)
368         {
369             psTransceiveInfo->cmd.MfCmd =
370                 (phHal_eMifareCmdList_t)psTransceiveInfo->sSendData.buffer[0];
371 
372             Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type =
373                 (uint8_t)psTransceiveInfo->cmd.MfCmd;
374 
375             Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.addr =
376                 psTransceiveInfo->addr =
377                 psTransceiveInfo->sSendData.buffer[1];
378 
379             for (counter = 2; counter < psTransceiveInfo->sSendData.length;
380                  counter++)
381             {
382                 psTransceiveInfo->sSendData.buffer[counter - 2] =
383                     psTransceiveInfo->sSendData.buffer[counter];
384             }
385             PHDBG_INFO("Hal4:Inside MifareTrcv() ,minus length by 4");
386             psTransceiveInfo->sSendData.length =
387                 psTransceiveInfo->sSendData.length - 4;
388 
389         }
390         else
391         {
392             Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type
393                         = (uint8_t)psTransceiveInfo->cmd.MfCmd;
394         }
395     }
396     return;
397 }
398 
399 /*  The phHal4Nfc_Transceive function allows the Initiator to send and receive
400  *  data to and from the Remote Device selected by the caller.*/
phHal4Nfc_Transceive(phHal_sHwReference_t * psHwReference,phHal_sTransceiveInfo_t * psTransceiveInfo,phHal_sRemoteDevInformation_t * psRemoteDevInfo,pphHal4Nfc_TransceiveCallback_t pTrcvCallback,void * pContext)401 NFCSTATUS phHal4Nfc_Transceive(
402                                phHal_sHwReference_t          *psHwReference,
403                                phHal_sTransceiveInfo_t       *psTransceiveInfo,
404                                phHal_sRemoteDevInformation_t  *psRemoteDevInfo,
405                                pphHal4Nfc_TransceiveCallback_t pTrcvCallback,
406                                void                           *pContext
407                                )
408 {
409     NFCSTATUS RetStatus = NFCSTATUS_PENDING;
410     phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)pContext;
411 
412     /*NULL checks*/
413     if((NULL == psHwReference)
414         ||( NULL == pTrcvCallback )
415         || (NULL == psRemoteDevInfo)
416         || (NULL == psTransceiveInfo)
417         || (NULL == psTransceiveInfo->sRecvData.buffer)
418         || (NULL == psTransceiveInfo->sSendData.buffer)
419         )
420     {
421         phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1);
422         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER);
423     }
424 #ifdef HAL_TRCV_LIMIT
425     else if(PH_HAL4NFC_MAX_TRCV_LEN < psTransceiveInfo->sSendData.length)
426     {
427         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_ALLOWED);
428     }
429 #endif/*#ifdef HAL_TRCV_LIMIT*/
430     /*Check initialised state*/
431     else if((NULL == psHwReference->hal_context)
432                         || (((phHal4Nfc_Hal4Ctxt_t *)
433                                 psHwReference->hal_context)->Hal4CurrentState
434                                                < eHal4StateOpenAndReady)
435                         || (((phHal4Nfc_Hal4Ctxt_t *)
436                                 psHwReference->hal_context)->Hal4NextState
437                                                == eHal4StateClosed))
438     {
439         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED);
440     }
441     else
442     {
443         Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context;
444         gpphHal4Nfc_Hwref = (phHal_sHwReference_t *)psHwReference;
445         if((eHal4StateTargetConnected != Hal4Ctxt->Hal4CurrentState)
446             ||(eHal4StateInvalid != Hal4Ctxt->Hal4NextState))
447         {
448             /*Hal4 state Busy*/
449             RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_BUSY);
450             PHDBG_INFO("HAL4:Trcv Failed.Returning Busy");
451         }
452         else if(psRemoteDevInfo != Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)
453         {
454             /*No such Target connected*/
455             RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_REMOTE_DEVICE);
456         }
457         else
458         {
459             /*allocate Trcv context*/
460             if(NULL == Hal4Ctxt->psTrcvCtxtInfo)
461             {
462                 Hal4Ctxt->psTrcvCtxtInfo= (pphHal4Nfc_TrcvCtxtInfo_t)
463                 phOsalNfc_GetMemory((uint32_t)(sizeof(phHal4Nfc_TrcvCtxtInfo_t)));
464                 if(NULL != Hal4Ctxt->psTrcvCtxtInfo)
465                 {
466                     (void)memset(Hal4Ctxt->psTrcvCtxtInfo,0,
467                                         sizeof(phHal4Nfc_TrcvCtxtInfo_t));
468                     Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus
469                         = NFCSTATUS_PENDING;
470                     Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
471                                                 = PH_OSALNFC_INVALID_TIMER_ID;
472                 }
473             }
474             if(NULL == Hal4Ctxt->psTrcvCtxtInfo)
475             {
476                 phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0);
477                 RetStatus= PHNFCSTVAL(CID_NFC_HAL ,
478                                             NFCSTATUS_INSUFFICIENT_RESOURCES);
479             }
480             else
481             {
482                 /*Process transceive based on Remote device type*/
483                 switch(Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType)
484                 {
485                 case phHal_eISO14443_3A_PICC:
486                     phHal4Nfc_Iso_3A_Transceive(
487                                         psTransceiveInfo,
488                                         Hal4Ctxt
489                                         );
490                     break;
491                 case phHal_eMifare_PICC:
492                     PHDBG_INFO("Mifare Cmd received");
493                     phHal4Nfc_MifareTransceive(
494                                         psTransceiveInfo,
495                                         psRemoteDevInfo,
496                                         Hal4Ctxt
497                                         );
498 
499 #if 0
500                     Hal4Ctxt->psTrcvCtxtInfo->
501                         XchangeInfo.params.tag_info.cmd_type
502                                         = (uint8_t)psTransceiveInfo->cmd.MfCmd;
503 #endif
504                     break;
505                 case phHal_eISO14443_A_PICC:
506                 case phHal_eISO14443_B_PICC:
507                     PHDBG_INFO("ISO14443 Cmd received");
508                     Hal4Ctxt->psTrcvCtxtInfo->
509                         XchangeInfo.params.tag_info.cmd_type
510                             = (uint8_t)psTransceiveInfo->cmd.Iso144434Cmd;
511                     break;
512                 case phHal_eISO15693_PICC:
513                     PHDBG_INFO("ISO15693 Cmd received");
514                     Hal4Ctxt->psTrcvCtxtInfo->
515                         XchangeInfo.params.tag_info.cmd_type
516                             = (uint8_t)psTransceiveInfo->cmd.Iso15693Cmd;
517                     break;
518                 case phHal_eNfcIP1_Target:
519                     {
520                         PHDBG_INFO("NfcIP1 Transceive");
521                         Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData
522                             = &(psTransceiveInfo->sSendData);
523                         Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData =
524                             &(psTransceiveInfo->sRecvData);
525                     }
526                     break;
527                 case phHal_eFelica_PICC:
528                     PHDBG_INFO("Felica Cmd received");
529                     Hal4Ctxt->psTrcvCtxtInfo->
530                         XchangeInfo.params.tag_info.cmd_type
531                         = (uint8_t)psTransceiveInfo->cmd.FelCmd;
532                     break;
533                 case phHal_eJewel_PICC:
534                     PHDBG_INFO("Jewel Cmd received");
535                     Hal4Ctxt->psTrcvCtxtInfo->
536                         XchangeInfo.params.tag_info.cmd_type
537                         = (uint8_t)psTransceiveInfo->cmd.JewelCmd;
538                     break;
539                 case phHal_eISO14443_BPrime_PICC:
540                     RetStatus = PHNFCSTVAL(CID_NFC_HAL ,
541                                               NFCSTATUS_FEATURE_NOT_SUPPORTED);
542                     break;
543                 default:
544                     PHDBG_WARNING("Invalid Device type received");
545                     RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_FAILED);
546                     break;
547 
548                 }
549             }
550         }
551         /*If status is anything other than NFCSTATUS_PENDING ,an error has
552           already occured, so dont process any further and return*/
553         if(RetStatus == NFCSTATUS_PENDING)
554         {
555             if(phHal_eNfcIP1_Target ==
556                   Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType)
557             {
558                 Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext;
559                 /*Register upper layer callback*/
560                 Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb  = pTrcvCallback;
561                 if(psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength
562                     >= psTransceiveInfo->sSendData.length)
563                 {
564                     Hal4Ctxt->psTrcvCtxtInfo->
565                         XchangeInfo.params.nfc_info.more_info = FALSE;
566                     Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length
567                                 = (uint8_t)psTransceiveInfo->sSendData.length;
568                     Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer
569                         = psTransceiveInfo->sSendData.buffer;
570                     /*Number of bytes remaining for next send*/
571                     Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length = 0;
572                 }
573                 else
574                 {
575                     Hal4Ctxt->psTrcvCtxtInfo->
576                         XchangeInfo.params.nfc_info.more_info = TRUE;
577                     Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer
578                         = Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer;
579                     Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length
580                                                 = psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength;
581 #if 0
582                     Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer
583                                                 += psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength;
584 #else
585                     Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent
586                         += psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength;
587 #endif
588                     /*Number of bytes remaining for next send*/
589                     Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length
590                                                -= psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength;
591                 }
592                 Hal4Ctxt->Hal4NextState = eHal4StateTransaction;
593 #ifdef TRANSACTION_TIMER
594                 /**Create a timer to keep track of transceive timeout*/
595                 if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
596                     == PH_OSALNFC_INVALID_TIMER_ID)
597                 {
598                     PHDBG_INFO("HAL4: Transaction Timer Create for transceive");
599                     Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
600                         = phOsalNfc_Timer_Create();
601                 }
602                 if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
603                     == PH_OSALNFC_INVALID_TIMER_ID)
604                 {
605                     RetStatus = PHNFCSTVAL(CID_NFC_HAL ,
606                         NFCSTATUS_INSUFFICIENT_RESOURCES);
607                 }
608                 else
609 #endif/*TRANSACTION_TIMER*/
610                 {
611                     PHDBG_INFO("Hal4:Calling phHciNfc_Send_Data from Hal4_Transceive()");
612                     RetStatus = phHciNfc_Send_Data (
613                                     Hal4Ctxt->psHciHandle,
614                                     psHwReference,
615                                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
616                                     &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo)
617                                     );
618                     if(NFCSTATUS_PENDING == RetStatus)
619                     {
620                         Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress = TRUE;
621                     }
622                 }
623             }
624             else if(psTransceiveInfo->sSendData.length > PH_HAL4NFC_CMD_LENGTH)
625             {
626                 RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_PARAMETER);
627             }
628             else if((psTransceiveInfo->sSendData.length == 0)
629                     && (Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length != 0))
630             {
631                 PHDBG_INFO("Hal4:Read remaining bytes");
632                 Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData
633                                             = &(psTransceiveInfo->sRecvData);
634                 /*Number of read bytes left is greater than bytes requested
635                     by upper layer*/
636                 if(Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length
637                     < Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length)
638                 {
639                     (void)memcpy(Hal4Ctxt->psTrcvCtxtInfo
640                                                 ->psUpperRecvData->buffer,
641                         (Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer
642                         + Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset)
643                         ,Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length);
644                     Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length -=
645                         Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length;
646                     Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset
647                         += Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length;
648                     RetStatus = PHNFCSTVAL(CID_NFC_HAL ,
649                                                 NFCSTATUS_MORE_INFORMATION);
650                 }
651                 else/*Number of read bytes left is smaller.Copy all bytes
652                       and free Hal's buffer*/
653                 {
654                     Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length
655                         = Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length;
656                     (void)memcpy(Hal4Ctxt->psTrcvCtxtInfo
657                                                         ->psUpperRecvData
658                                                                     ->buffer,
659                         (Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer
660                             + Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset)
661                         ,Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length);
662                     phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo
663                                                     ->sLowerRecvData.buffer);
664                     Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer = NULL;
665                     Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length = 0;
666                     Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset   = 0;
667                     RetStatus = NFCSTATUS_SUCCESS;
668                 }
669             }
670             else/*No more bytes remaining in Hal.Read from device*/
671             {
672                  /*Register upper layer context*/
673                 Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext;
674                 /*Register upper layer callback*/
675                 Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb  = pTrcvCallback;
676                 Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.addr
677                                                     = psTransceiveInfo->addr;
678                 Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length
679                                 = (uint16_t)psTransceiveInfo->sSendData.length;
680                 Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer
681                                         = psTransceiveInfo->sSendData.buffer;
682                 Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData
683                                             = &(psTransceiveInfo->sRecvData);
684 #ifdef TRANSACTION_TIMER
685                 /**Create a timer to keep track of transceive timeout*/
686                 if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
687                                     == PH_OSALNFC_INVALID_TIMER_ID)
688                 {
689                     PHDBG_INFO("HAL4: Transaction Timer Create for transceive");
690                     Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
691                                             = phOsalNfc_Timer_Create();
692                 }
693                 if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
694                     == PH_OSALNFC_INVALID_TIMER_ID)
695                 {
696                     RetStatus = PHNFCSTVAL(CID_NFC_HAL ,
697                                            NFCSTATUS_INSUFFICIENT_RESOURCES);
698                 }
699                 else
700 #endif /*TRANSACTION_TIMER*/
701                 {
702                     PHDBG_INFO("Calling phHciNfc_Exchange_Data");
703                     RetStatus = phHciNfc_Exchange_Data(
704                         Hal4Ctxt->psHciHandle,
705                         psHwReference,
706                         Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
707                         &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo)
708                         );
709 
710                     if(NFCSTATUS_PENDING == RetStatus)
711                     {
712                         Hal4Ctxt->Hal4NextState = eHal4StateTransaction;
713 #ifdef TRANSACTION_TIMER
714                         /**Start timer to keep track of transceive timeout*/
715                         phOsalNfc_Timer_Start(
716                             Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId,
717                             PH_HAL4NFC_TRANSCEIVE_TIMEOUT,
718                             phHal4Nfc_TrcvTimeoutHandler
719                             );
720 #endif/*#ifdef TRANSACTION_TIMER*/
721                     }
722                     else
723                     {
724                         Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
725                     }
726                 }
727             }
728         }
729     }
730     return RetStatus;
731 }
732 
733 #ifdef TRANSACTION_TIMER
734 /**Handle transceive timeout*/
phHal4Nfc_TrcvTimeoutHandler(uint32_t TrcvTimerId)735 void phHal4Nfc_TrcvTimeoutHandler(uint32_t TrcvTimerId)
736 {
737     phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = gpphHal4Nfc_Hwref->hal_context;
738     pphHal4Nfc_ReceiveCallback_t pUpperRecvCb = NULL;
739     pphHal4Nfc_TransceiveCallback_t pUpperTrcvCb = NULL;
740     phOsalNfc_Timer_Stop(TrcvTimerId);
741     phOsalNfc_Timer_Delete(TrcvTimerId);
742     Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId = PH_OSALNFC_INVALID_TIMER_ID;
743     Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
744     /*For a P2P target*/
745     if(Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb != NULL)
746     {
747         pUpperRecvCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb;
748         Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb = NULL;
749         (*pUpperRecvCb)(
750             Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
751             NULL,
752             NFCSTATUS_RF_TIMEOUT
753             );
754     }
755     else
756     {
757         /*For a P2P Initiator and tags*/
758         if(Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb != NULL)
759         {
760             pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb;
761             Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL;
762             (*pUpperTrcvCb)(
763                         Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
764                         Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
765                         NULL,
766                         NFCSTATUS_RF_TIMEOUT
767                         );
768         }
769     }
770 }
771 #endif /*TRANSACTION_TIMER*/
772 
773 
774 /**The function allows to disconnect from a specific Remote Device.*/
phHal4Nfc_Disconnect(phHal_sHwReference_t * psHwReference,phHal_sRemoteDevInformation_t * psRemoteDevInfo,phHal_eReleaseType_t ReleaseType,pphHal4Nfc_DiscntCallback_t pDscntCallback,void * pContext)775 NFCSTATUS phHal4Nfc_Disconnect(
776                         phHal_sHwReference_t          *psHwReference,
777                         phHal_sRemoteDevInformation_t *psRemoteDevInfo,
778                         phHal_eReleaseType_t           ReleaseType,
779                         pphHal4Nfc_DiscntCallback_t    pDscntCallback,
780                         void                             *pContext
781                         )
782 {
783     NFCSTATUS RetStatus = NFCSTATUS_PENDING;
784     phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL;
785     PHDBG_INFO("Hal4:Inside Hal4 disconnect");
786     /*NULL checks*/
787     if(NULL == psHwReference || NULL == pDscntCallback
788         || NULL == psRemoteDevInfo)
789     {
790         phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1);
791         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER);
792     }
793     /*Check Initialised state*/
794     else if((NULL == psHwReference->hal_context)
795                         || (((phHal4Nfc_Hal4Ctxt_t *)
796                                 psHwReference->hal_context)->Hal4CurrentState
797                                                < eHal4StateOpenAndReady)
798                         || (((phHal4Nfc_Hal4Ctxt_t *)
799                                 psHwReference->hal_context)->Hal4NextState
800                                                == eHal4StateClosed))
801     {
802         RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED);
803     }
804     else if(((phHal4Nfc_Hal4Ctxt_t *)
805                     psHwReference->hal_context)->Hal4CurrentState
806                     != eHal4StateTargetConnected)
807     {
808         PHDBG_INFO("Hal4:Current sate is not connect.Release returning failed");
809         RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_FAILED);
810     }
811     else
812     {
813         Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context;
814         if((Hal4Ctxt->sTgtConnectInfo.psConnectedDevice == NULL)
815             || (psRemoteDevInfo != Hal4Ctxt->sTgtConnectInfo.psConnectedDevice))
816         {
817             PHDBG_INFO("Hal4:disconnect returning INVALID_REMOTE_DEVICE");
818             RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_REMOTE_DEVICE);
819         }
820         else
821         {
822             /*Register upper layer context*/
823             Hal4Ctxt->sUpperLayerInfo.psUpperLayerDisconnectCtxt = pContext;
824             /*Register upper layer callback*/
825             Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb  = pDscntCallback;
826             /*Register Release Type*/
827             Hal4Ctxt->sTgtConnectInfo.ReleaseType = ReleaseType;
828             if((eHal4StateTransaction == Hal4Ctxt->Hal4NextState)
829                 &&((phHal_eNfcIP1_Target != psRemoteDevInfo->RemDevType)
830                 ||((NFC_DISCOVERY_CONTINUE != ReleaseType)
831                    &&(NFC_DISCOVERY_RESTART != ReleaseType))))
832             {
833                 Hal4Ctxt->sTgtConnectInfo.ReleaseType
834                                                   = NFC_INVALID_RELEASE_TYPE;
835                 PHDBG_INFO("Hal4:disconnect returning NFCSTATUS_NOT_ALLOWED");
836                 RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_NOT_ALLOWED);
837             }
838             else if((eHal4StateTransaction == Hal4Ctxt->Hal4NextState)
839                     &&(NULL != Hal4Ctxt->psTrcvCtxtInfo)
840                     &&(TRUE == Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress))
841             {
842                 /*store the hardware reference for executing disconnect later*/
843                 gpphHal4Nfc_Hwref = psHwReference;
844                 PHDBG_INFO("Hal4:disconnect deferred");
845             }
846             else/*execute disconnect*/
847             {
848                 RetStatus = phHal4Nfc_Disconnect_Execute(psHwReference);
849             }
850         }
851     }
852     return RetStatus;
853 }
854 
855 /**Execute Hal4 Disconnect*/
phHal4Nfc_Disconnect_Execute(phHal_sHwReference_t * psHwReference)856 NFCSTATUS phHal4Nfc_Disconnect_Execute(
857                             phHal_sHwReference_t  *psHwReference
858                             )
859 {
860     NFCSTATUS RetStatus = NFCSTATUS_PENDING;
861     phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt =
862         (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context;
863     phHal_eSmartMX_Mode_t SmxMode = eSmartMx_Default;
864     PHDBG_INFO("Hal4:Inside Hal4 disconnect execute");
865     switch(Hal4Ctxt->sTgtConnectInfo.ReleaseType)
866     {
867         /*Switch mode to Default*/
868         case NFC_SMARTMX_RELEASE:
869             SmxMode = eSmartMx_Default;
870             RetStatus = phHciNfc_Switch_SmxMode (
871                 Hal4Ctxt->psHciHandle,
872                 psHwReference,
873                 SmxMode,
874                 &(Hal4Ctxt->psADDCtxtInfo->sADDCfg)
875                 );
876             break;
877         /*Disconnect and continue polling wheel*/
878         case NFC_DISCOVERY_CONTINUE:
879         {
880             RetStatus = phHciNfc_Disconnect (
881                                     Hal4Ctxt->psHciHandle,
882                                     psHwReference,
883                                     FALSE
884                                     );
885             if(NFCSTATUS_PENDING != RetStatus)
886             {
887                 PHDBG_INFO("Hal4:Hci disconnect failed.Restarting discovery");
888                 RetStatus = phHciNfc_Restart_Discovery (
889                                     (void *)Hal4Ctxt->psHciHandle,
890                                     (void *)gpphHal4Nfc_Hwref,
891                                     FALSE
892                                     );
893                 if(NFCSTATUS_PENDING != RetStatus)
894                 {
895                     PHDBG_INFO("Hal4:Hci Restart discovery also failed");
896                 }
897             }
898             break;
899         }
900         /*Disconnect and restart polling wheel*/
901         case NFC_DISCOVERY_RESTART:
902             RetStatus = phHciNfc_Disconnect (
903                                 Hal4Ctxt->psHciHandle,
904                                 psHwReference,
905                                 TRUE
906                                 );
907             break;
908         default:
909             RetStatus = PHNFCSTVAL(CID_NFC_HAL,
910                 NFCSTATUS_FEATURE_NOT_SUPPORTED);
911             break;
912     }
913     Hal4Ctxt->sTgtConnectInfo.ReleaseType = NFC_INVALID_RELEASE_TYPE;
914     /*Update or rollback next state*/
915     Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == RetStatus?
916                     eHal4StateOpenAndReady:Hal4Ctxt->Hal4NextState);
917     return  RetStatus;
918 }
919 
920 /*The function allows to check for presence in vicinity of connected remote
921   device.*/
phHal4Nfc_PresenceCheck(phHal_sHwReference_t * psHwReference,pphHal4Nfc_GenCallback_t pPresenceChkCb,void * context)922 NFCSTATUS phHal4Nfc_PresenceCheck(
923                                 phHal_sHwReference_t     *psHwReference,
924                                 pphHal4Nfc_GenCallback_t  pPresenceChkCb,
925                                 void *context
926                                 )
927 {
928     NFCSTATUS RetStatus = NFCSTATUS_FAILED;
929     phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL;
930     /*NULL  checks*/
931     if((NULL == pPresenceChkCb) || (NULL == psHwReference))
932     {
933         RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_PARAMETER);
934     }
935     /*Check Initialised state*/
936     else if((NULL == psHwReference->hal_context)
937                         || (((phHal4Nfc_Hal4Ctxt_t *)
938                                 psHwReference->hal_context)->Hal4CurrentState
939                                                < eHal4StateOpenAndReady)
940                         || (((phHal4Nfc_Hal4Ctxt_t *)
941                                 psHwReference->hal_context)->Hal4NextState
942                                                == eHal4StateClosed))
943     {
944         PHDBG_INFO("HAL4:Context not Open");
945         RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_NOT_INITIALISED);
946     }
947     /*check connected state and session alive*/
948     else if((((phHal4Nfc_Hal4Ctxt_t *)
949              psHwReference->hal_context)->Hal4CurrentState
950                                 < eHal4StateTargetConnected)||
951             (NULL == ((phHal4Nfc_Hal4Ctxt_t *)
952               psHwReference->hal_context)->sTgtConnectInfo.psConnectedDevice)||
953             (FALSE == ((phHal4Nfc_Hal4Ctxt_t *)
954                         psHwReference->hal_context)->sTgtConnectInfo.
955                                     psConnectedDevice->SessionOpened))
956     {
957         PHDBG_INFO("HAL4:No target connected");
958         RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_RELEASED);
959     }
960     else
961     {
962         Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context;
963         /*allow only one Presence chk command at any point in time*/
964         if (eHal4StatePresenceCheck != Hal4Ctxt->Hal4NextState)
965         {
966             /* Check if remote device is felica */
967             if (Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType ==
968                 phHal_eFelica_PICC)
969             {
970                 /* If felica PICC then copy existing IDm to compare later,
971                    If IDm will be same then same PICC is present after presence check
972                    else PICC is changed */
973                 (void) memcpy(Hal4Ctxt->FelicaIDm,
974                               Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm,
975                               Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDmLength);
976             }
977             Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = context;
978             Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb = pPresenceChkCb;
979             RetStatus = phHciNfc_Presence_Check(Hal4Ctxt->psHciHandle,
980                                                 psHwReference
981                                                 );
982             Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == RetStatus?
983                 eHal4StatePresenceCheck:Hal4Ctxt->Hal4NextState);
984         }
985         else/*Ongoing presence chk*/
986         {
987             RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_BUSY);
988         }
989     }
990     return RetStatus;
991 }
992 
phHal4Nfc_PresenceChkComplete(phHal4Nfc_Hal4Ctxt_t * Hal4Ctxt,void * pInfo)993 void phHal4Nfc_PresenceChkComplete(
994                                    phHal4Nfc_Hal4Ctxt_t  *Hal4Ctxt,
995                                    void *pInfo
996                                    )
997 {
998     NFCSTATUS RetStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status;
999     Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
1000     /*Notify to upper layer*/
1001     if(NULL != Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb)
1002     {
1003         Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->SessionOpened
1004                      =(uint8_t)(NFCSTATUS_SUCCESS == RetStatus?TRUE:FALSE);
1005         /* Check if remote device is felica */
1006         if (Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType ==
1007             phHal_eFelica_PICC)
1008         {
1009             /* Check if IDm received is same as saved */
1010             if (0 != phOsalNfc_MemCompare(Hal4Ctxt->FelicaIDm,
1011                 Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm,
1012                 Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDmLength))
1013             {
1014                 RetStatus = NFCSTATUS_FAILED;
1015 
1016                 /* Presence check failed so reset remote device information */
1017                 (void) memset(Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm,
1018                               0, PHHAL_FEL_ID_LEN + 2);
1019                 (void) memset(Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.PMm,
1020                               0, PHHAL_FEL_PM_LEN);
1021             }
1022 
1023             /* Cleanup for stored IDm value for using it next time */
1024             (void) memset(Hal4Ctxt->FelicaIDm, 0, PHHAL_FEL_ID_LEN + 2);
1025         }
1026 
1027         (*Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb)(
1028                         Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
1029                         RetStatus
1030                         );
1031     }
1032     return;
1033 }
1034 
1035 /*Callback for reactivate target and to select appropriate target incase
1036  of multiple targets*/
phHal4Nfc_ReactivationComplete(phHal4Nfc_Hal4Ctxt_t * Hal4Ctxt,void * pInfo)1037 void phHal4Nfc_ReactivationComplete(
1038                                     phHal4Nfc_Hal4Ctxt_t  *Hal4Ctxt,
1039                                     void *pInfo
1040                                     )
1041 {
1042     NFCSTATUS Status = ((phNfc_sCompletionInfo_t *)pInfo)->status;
1043     /*A NFCSTATUS_SUCCESS status returned here means that the correct device
1044      to connect to has now been selected.So issue connect from here to complete
1045      activation*/
1046     if(NFCSTATUS_SUCCESS == Status)
1047     {
1048         Hal4Ctxt->Hal4NextState = eHal4StateTargetConnected;
1049         Status = phHciNfc_Connect(
1050             Hal4Ctxt->psHciHandle,
1051             gpphHal4Nfc_Hwref,
1052             Hal4Ctxt->sTgtConnectInfo.psConnectedDevice
1053             );
1054         Status = (NFCSTATUS_PENDING == Status)?
1055                     NFCSTATUS_PENDING:NFCSTATUS_FAILED;
1056     }
1057     else/*Device unavailable, return error in connect Callback*/
1058     {
1059         Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
1060         if(NULL != Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb)
1061         {
1062             (*Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb)(
1063                                 Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
1064                                 Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
1065                                 Status
1066                                 );
1067         }
1068     }
1069     return;
1070 }
1071 
phHal4Nfc_Felica_RePoll(void * context,NFCSTATUS status)1072 void phHal4Nfc_Felica_RePoll(void     *context,
1073                                         NFCSTATUS status)
1074 {
1075      phHal4Nfc_Hal4Ctxt_t  *Hal4Ctxt = gpHal4Ctxt;
1076      pphHal4Nfc_ConnectCallback_t pUpperConnectCb
1077                                 = Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb;
1078 
1079      Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL;
1080      PHDBG_INFO("Hal4:Calling Connect callback");
1081 
1082     if (pUpperConnectCb != NULL)
1083     {
1084          /*Notify to the upper layer*/
1085          (*pUpperConnectCb)(
1086                     Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
1087                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
1088                     status
1089                     );
1090     }
1091 
1092     return;
1093 }
phHal4Nfc_ConnectComplete(phHal4Nfc_Hal4Ctxt_t * Hal4Ctxt,void * pInfo)1094 void phHal4Nfc_ConnectComplete(
1095                                phHal4Nfc_Hal4Ctxt_t  *Hal4Ctxt,
1096                                void *pInfo
1097                                )
1098 {
1099     NFCSTATUS ConnectStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status;
1100     pphHal4Nfc_ConnectCallback_t pUpperConnectCb
1101                                 = Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb;
1102     /*Flag to decide whether or not upper layer callback has to be called*/
1103     uint8_t CallConnectCb = TRUE;
1104     uint8_t felicaRePoll = FALSE;
1105 
1106     /*Remote device Connect successful*/
1107     if((NFCSTATUS_SUCCESS == ConnectStatus)
1108 		||(eHal4StateTargetConnected == Hal4Ctxt->Hal4CurrentState))
1109     {
1110         phHal_sRemoteDevInformation_t *psRmtTgtConnected =
1111                             Hal4Ctxt->sTgtConnectInfo.psConnectedDevice;
1112         PHDBG_INFO("Hal4:Connect status Success");
1113         Hal4Ctxt->Hal4CurrentState = eHal4StateTargetConnected;
1114         Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
1115         /* Open the Session */
1116         psRmtTgtConnected->SessionOpened =
1117             (uint8_t)(NFCSTATUS_SUCCESS == ConnectStatus?TRUE:FALSE);
1118         Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL;
1119         if (psRmtTgtConnected->RemDevType == phHal_eFelica_PICC)
1120         {
1121             felicaRePoll = TRUE;
1122         }
1123     }
1124     else/*Remote device Connect failed*/
1125     {
1126         Hal4Ctxt->Hal4CurrentState = eHal4StateOpenAndReady;
1127         Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->SessionOpened = FALSE;
1128         /*For a NfcIp1 target and case where it is not a internal reconnect
1129           from Hal4 ,notify callback to upper layer*/
1130         if((phHal_eNfcIP1_Target
1131             == Hal4Ctxt->rem_dev_list[0]->RemDevType)
1132             || (NULL != Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb))
1133         {
1134             Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL;
1135         }
1136         else/*do not notify callback*/
1137         {
1138             CallConnectCb = FALSE;
1139         }
1140         /*Free the remote device list*/
1141         do
1142         {
1143             Hal4Ctxt->psADDCtxtInfo->nbr_of_devices--;
1144             if(NULL != Hal4Ctxt->rem_dev_list[
1145                         Hal4Ctxt->psADDCtxtInfo->nbr_of_devices])
1146             {
1147                 phOsalNfc_FreeMemory((void *)
1148                         (Hal4Ctxt->rem_dev_list[
1149                             Hal4Ctxt->psADDCtxtInfo->nbr_of_devices]));
1150                 Hal4Ctxt->rem_dev_list[
1151                     Hal4Ctxt->psADDCtxtInfo->nbr_of_devices] = NULL;
1152             }
1153         }while(0 < Hal4Ctxt->psADDCtxtInfo->nbr_of_devices);
1154 
1155         Hal4Ctxt->sTgtConnectInfo.psConnectedDevice = NULL;
1156     }
1157     if(TRUE == CallConnectCb)
1158     {
1159         if (felicaRePoll == TRUE)
1160         {
1161             /* Felica repoll through presence check */
1162 
1163             /* If felica PICC then copy existing IDm to compare later,
1164                If IDm will be same then same PICC is present after presence check
1165                else PICC is changed */
1166             (void) memcpy(Hal4Ctxt->FelicaIDm,
1167                           Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm,
1168                           Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDmLength);
1169 
1170             gpHal4Ctxt = Hal4Ctxt;
1171             Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb = phHal4Nfc_Felica_RePoll;
1172             ConnectStatus = phHciNfc_Presence_Check(Hal4Ctxt->psHciHandle,
1173                                                     gpphHal4Nfc_Hwref
1174                                                     );
1175             Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == ConnectStatus?
1176                     eHal4StatePresenceCheck:Hal4Ctxt->Hal4NextState);
1177             felicaRePoll = FALSE;
1178             Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = pUpperConnectCb;
1179         }
1180         else
1181         {
1182             PHDBG_INFO("Hal4:Calling Connect callback");
1183             /*Notify to the upper layer*/
1184             (*pUpperConnectCb)(
1185                     Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
1186                     Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
1187                     ConnectStatus
1188                     );
1189 	 }
1190     }
1191     else
1192     {
1193         PHDBG_INFO("Hal4:Connect failed ,Restarting discovery");
1194         /*Restart the Discovery wheel*/
1195         ConnectStatus = phHciNfc_Restart_Discovery (
1196                                     (void *)Hal4Ctxt->psHciHandle,
1197                                     (void *)gpphHal4Nfc_Hwref,
1198                                     FALSE
1199                                     );
1200         Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == ConnectStatus?
1201                                     eHal4StateConfiguring:eHal4StateInvalid);
1202     }
1203     return;
1204 }
1205 
1206 
1207 
1208 
phHal4Nfc_DisconnectComplete(phHal4Nfc_Hal4Ctxt_t * Hal4Ctxt,void * pInfo)1209 void phHal4Nfc_DisconnectComplete(
1210                                   phHal4Nfc_Hal4Ctxt_t  *Hal4Ctxt,
1211                                   void *pInfo
1212                                   )
1213 {
1214     NFCSTATUS ConnectStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status;
1215     phHal_sRemoteDevInformation_t *psConnectedDevice = NULL;
1216     pphHal4Nfc_DiscntCallback_t pUpperDisconnectCb = NULL;
1217     pphHal4Nfc_TransceiveCallback_t pUpperTrcvCb = NULL;
1218     PHDBG_INFO("Hal4:Inside Hal4 disconnect callback");
1219     if(NULL == Hal4Ctxt)
1220     {
1221         phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1);
1222     }
1223     else if(NFCSTATUS_SUCCESS != ConnectStatus)/*Restart the Discovery wheel*/
1224     {
1225         ConnectStatus = phHciNfc_Restart_Discovery (
1226                                     (void *)Hal4Ctxt->psHciHandle,
1227                                     (void *)gpphHal4Nfc_Hwref,
1228                                     FALSE
1229                                     );
1230         Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == ConnectStatus?
1231                                     eHal4StateConfiguring:eHal4StateInvalid);
1232     }
1233     else/*Remote device Disconnect successful*/
1234     {
1235         psConnectedDevice = Hal4Ctxt->sTgtConnectInfo.psConnectedDevice;
1236         pUpperDisconnectCb = Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb;
1237         /*Deallocate psTrcvCtxtInfo*/
1238         if(NULL != Hal4Ctxt->psTrcvCtxtInfo)
1239         {
1240             if(NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)
1241             {
1242                if(NULL != Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData)
1243                 {
1244                     phOsalNfc_FreeMemory(
1245                         Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData);
1246                 }
1247             }
1248             else
1249             {
1250                 if(phHal_eNfcIP1_Target
1251                     == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType)
1252                 {
1253                     pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb;
1254                     Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length = 0;
1255                     pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb;
1256                     Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL;
1257                 }
1258             }
1259             if(NULL != Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer)
1260             {
1261                 phOsalNfc_FreeMemory(
1262                     Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer);
1263             }
1264 
1265             phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo);
1266             Hal4Ctxt->psTrcvCtxtInfo = NULL;
1267         }
1268         /*Free the remote device list*/
1269         do
1270         {
1271             if(NULL != Hal4Ctxt->rem_dev_list[Hal4Ctxt->
1272                 psADDCtxtInfo->nbr_of_devices-1])
1273             {
1274                 phOsalNfc_FreeMemory((void *)
1275                     (Hal4Ctxt->rem_dev_list[Hal4Ctxt->
1276                     psADDCtxtInfo->nbr_of_devices-1]));
1277                 Hal4Ctxt->rem_dev_list[Hal4Ctxt->
1278                     psADDCtxtInfo->nbr_of_devices-1] = NULL;
1279             }
1280         }while(--(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices));
1281 
1282         Hal4Ctxt->sTgtConnectInfo.psConnectedDevice = NULL;
1283         /*Disconnect successful.Go to Ready state*/
1284         Hal4Ctxt->Hal4CurrentState = Hal4Ctxt->Hal4NextState;
1285         Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb = NULL;
1286         Hal4Ctxt->Hal4NextState = (
1287             eHal4StateOpenAndReady == Hal4Ctxt->Hal4NextState?
1288             eHal4StateInvalid:Hal4Ctxt->Hal4NextState);
1289         /*Issue any pending Trcv callback*/
1290         if(NULL != pUpperTrcvCb)
1291         {
1292             (*pUpperTrcvCb)(
1293                 Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
1294                 psConnectedDevice,
1295                 NULL,
1296                 NFCSTATUS_FAILED
1297                 );
1298         }
1299         /*Notify upper layer*/
1300         if(NULL != pUpperDisconnectCb)
1301         {
1302             PHDBG_INFO("Hal4:Calling Upper layer disconnect callback");
1303             (*pUpperDisconnectCb)(
1304                         Hal4Ctxt->sUpperLayerInfo.psUpperLayerDisconnectCtxt,
1305                         psConnectedDevice,
1306                         ConnectStatus
1307                         );
1308         }
1309     }
1310     return;
1311 }
1312 
1313 
1314 /*Transceive complete handler function*/
phHal4Nfc_TransceiveComplete(phHal4Nfc_Hal4Ctxt_t * Hal4Ctxt,void * pInfo)1315 void phHal4Nfc_TransceiveComplete(
1316                                   phHal4Nfc_Hal4Ctxt_t  *Hal4Ctxt,
1317                                   void *pInfo
1318                                   )
1319 {
1320     /*Copy status code*/
1321     NFCSTATUS TrcvStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status;
1322     /*Update next state*/
1323     Hal4Ctxt->Hal4NextState = (eHal4StateTransaction
1324              == Hal4Ctxt->Hal4NextState?eHal4StateInvalid:Hal4Ctxt->Hal4NextState);
1325     /*Reset SelectSectorFlag for Mifare*/
1326     if (Hal4Ctxt->SelectSectorFlag == 2)
1327     {
1328         TrcvStatus = NFCSTATUS_SUCCESS;
1329         PHDBG_INFO("Inside Hal4TrcvComplete SelectSectorFlag is 2");
1330         Hal4Ctxt->SelectSectorFlag = 0;
1331     }
1332 
1333     if(NULL == Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData)
1334     {
1335         /*if recv buffer is Null*/
1336         phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1);
1337         TrcvStatus = NFCSTATUS_FAILED;
1338     }
1339     else if(TrcvStatus == NFCSTATUS_SUCCESS)
1340     {
1341         /*Check if recvdata buffer given by upper layer is big enough to
1342         receive all response bytes.If it is not big enough ,copy number
1343         of bytes requested by upper layer to the buffer.Remaining
1344         bytes are retained in Hal4 and upper layer has to issue another
1345         transceive call to read the same.*/
1346         if(((phNfc_sTransactionInfo_t *)pInfo)
1347             ->length  > Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length )
1348         {
1349             TrcvStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_MORE_INFORMATION);
1350             Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length
1351                 = ((phNfc_sTransactionInfo_t *)pInfo)->length
1352                 - Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length;
1353 
1354             Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer
1355                 = (uint8_t *)phOsalNfc_GetMemory(
1356                 Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length
1357                 );
1358             if(NULL != Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer)
1359             {
1360                 (void)memcpy(
1361                     Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer,
1362                     (((phNfc_sTransactionInfo_t *)pInfo)->buffer
1363                     + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData
1364                     ->length)
1365                     ,Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length
1366                     );
1367             }
1368             else
1369             {
1370                 TrcvStatus = PHNFCSTVAL(CID_NFC_HAL,
1371                     NFCSTATUS_INSUFFICIENT_RESOURCES);
1372                 phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0);
1373             }
1374 
1375         }
1376         else/*Buffer provided by upper layer is big enough to hold all read
1377               bytes*/
1378         {
1379             Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length
1380                 = ((phNfc_sTransactionInfo_t *)pInfo)->length;
1381             Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length = 0;
1382         }
1383         (void)memcpy(Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->buffer,
1384             ((phNfc_sTransactionInfo_t *)pInfo)->buffer,
1385             Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length
1386             );
1387 
1388     }
1389     else/*Error scenario.Set received bytes length to zero*/
1390     {
1391         Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length = 0;
1392     }
1393     (void)memset((void *)&(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params),
1394                   0,
1395                   sizeof(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params)
1396                 );
1397     Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset = 0;
1398     /*Issue transceive callback*/
1399     (*Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb)(
1400         Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
1401         Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
1402         Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData,
1403         TrcvStatus
1404         );
1405     return;
1406 }
1407