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