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/*!
18* =========================================================================== *
19*                                                                             *
20*                                                                             *
21* \file  hHciNfc_AdminMgmt.c                                                  *
22* \brief HCI Admin Gate Management Routines.                                  *
23*                                                                             *
24*                                                                             *
25* Project: NFC-FRI-1.1                                                        *
26*                                                                             *
27* $Date: Mon Apr  5 19:23:34 2010 $                                           *
28* $Author: ing04880 $                                                         *
29* $Revision: 1.47 $                                                           *
30* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $
31*                                                                             *
32* =========================================================================== *
33*/
34
35/*
36***************************** Header File Inclusion ****************************
37*/
38#include <phNfcCompId.h>
39#include <phHciNfc_Pipe.h>
40#include <phHciNfc_AdminMgmt.h>
41#include <phHciNfc_DevMgmt.h>
42#include <phOsalNfc.h>
43/*
44****************************** Macro Definitions *******************************
45*/
46
47#define SESSION_INDEX       0x01U
48#define MAX_PIPE_INDEX      0x02U
49#define WHITELIST_INDEX     0x03U
50#define HOST_LIST_INDEX     0x04U
51
52/* Max Whitelist Supported by the Device*/
53#define SESSIONID_LEN       0x08U
54#define WHITELIST_MAX_LEN   0x03U
55#define HOST_LIST_MAX_LEN   0x05U
56
57/* Address Definitions for HW Configuration */
58#define NFC_ADDRESS_UICC_SESSION        0x9EA2U
59
60
61
62/*
63*************************** Structure and Enumeration ***************************
64*/
65
66typedef enum phHciNfc_Admin_Seq{
67    ADMIN_PIPE_OPEN     = 0x00U,
68    ADMIN_GET_HOST_LIST,
69    ADMIN_GET_WHITE_LIST,
70    ADMIN_GET_SESSION,
71    ADMIN_VERIFY_SESSION,
72    ADMIN_CLEAR_UICC_PIPES,
73    ADMIN_CLEAR_PIPES,
74    ADMIN_PIPE_REOPEN,
75    ADMIN_CREATE_PIPES,
76    ADMIN_SET_SESSION,
77    ADMIN_SET_WHITE_LIST,
78    ADMIN_UPDATE_PIPES,
79    ADMIN_PIPE_CLOSE,
80    ADMIN_DELETE_PIPES,
81    ADMIN_END_SEQUENCE
82} phHciNfc_Admin_Seq_t;
83
84
85/* Information structure for the Admin Gate */
86typedef struct phHciNfc_AdminGate_Info{
87    /* Current running Sequence of the Admin Management */
88    phHciNfc_Admin_Seq_t            current_seq;
89    /* Next running Sequence of the Admin Management */
90    phHciNfc_Admin_Seq_t            next_seq;
91    /* Pointer to the Admin Pipe Information */
92    phHciNfc_Pipe_Info_t            *admin_pipe_info;
93    /* Sequence for the Pipe Initialisation */
94    phHciNfc_PipeMgmt_Seq_t         pipe_seq;
95    /* Session ID of the Device */
96    uint8_t                         session_id[SESSIONID_LEN];
97    /* Max number of pipes that can be created on the Device */
98    uint8_t                         max_pipe;
99    /* List of Hosts that can be access the device Admin Gate. */
100    uint8_t                         whitelist[WHITELIST_MAX_LEN];
101    /* Host List from the Host Controller */
102    uint8_t                         host_list[HOST_LIST_MAX_LEN];
103} phHciNfc_AdminGate_Info_t;
104
105/*
106*************************** Static Function Declaration **************************
107*/
108
109/**
110 * \ingroup grp_hci_nfc
111 *
112 *  The phHciNfc_Recv_Admin_Response function interprets the received AdminGate
113 *  response from the Host Controller Gate.
114 *
115 *  \param[in]  psHciContext            psHciContext is the pointer to HCI Layer
116 *                                      context Structure.
117 *  \param[in]  pHwRef                  pHwRef is the Information of
118 *                                      the Device Interface Link .
119 *  \param[in,out]  pResponse           Response received from the Host Cotroller
120 *                                      Admin gate.
121 *  \param[in]  length                  length contains the length of the
122 *                                      response received from the Host Controller.
123 *
124 *  \retval NFCSTATUS_PENDING           AdminGate Response to be received is pending.
125 *  \retval NFCSTATUS_SUCCESS           AdminGate Response received Successfully.
126 *  \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
127 *                                      could not be interpreted properly.
128 *  \retval Other errors                Errors related to the other layers
129 *
130 */
131
132static
133NFCSTATUS
134phHciNfc_Recv_Admin_Response(
135                        void                *psHciContext,
136                        void                *pHwRef,
137                        uint8_t             *pResponse,
138#ifdef ONE_BYTE_LEN
139                        uint8_t             length
140#else
141                        uint16_t            length
142#endif
143                       );
144
145
146static
147NFCSTATUS
148phHciNfc_Admin_InfoUpdate(
149                                phHciNfc_sContext_t     *psHciContext,
150                                phHal_sHwReference_t    *pHwRef,
151                                uint8_t                 index,
152                                uint8_t                 *reg_value,
153                                uint8_t                 reg_length
154                         );
155
156static
157 NFCSTATUS
158 phHciNfc_Recv_Admin_Cmd (
159                        void                *psContext,
160                        void                *pHwRef,
161                        uint8_t             *pCmd,
162#ifdef ONE_BYTE_LEN
163                        uint8_t             length
164#else
165                        uint16_t            length
166#endif
167                     );
168
169
170static
171 NFCSTATUS
172 phHciNfc_Recv_Admin_Event (
173                        void                *psContext,
174                        void                *pHwRef,
175                        uint8_t             *pEvent,
176#ifdef ONE_BYTE_LEN
177                        uint8_t             length
178#else
179                        uint16_t            length
180#endif
181                     );
182
183
184/*
185*************************** Function Definitions ***************************
186*/
187
188
189
190/*!
191 * \brief Initialisation of Admin Gate and Establish the Session .
192 *
193 * This function initialses the Admin Gates and Establishes the Session by creating
194 * all the required pipes and sets the Session ID
195 *
196 */
197
198NFCSTATUS
199phHciNfc_Admin_Initialise(
200                                phHciNfc_sContext_t     *psHciContext,
201                                void                    *pHwRef
202                         )
203{
204    NFCSTATUS                           status = NFCSTATUS_SUCCESS;
205    phHciNfc_Pipe_Info_t                *p_pipe_info = NULL;
206    phHciNfc_AdminGate_Info_t           *p_admin_info=NULL;
207    uint8_t                             length = 0;
208
209    if( (NULL == psHciContext)
210        || (NULL == pHwRef )
211        )
212    {
213        status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
214    }
215    else
216    {
217        if( ( NULL == psHciContext->p_admin_info )
218            && (phHciNfc_Allocate_Resource((void **)(&p_admin_info),
219                    sizeof(phHciNfc_AdminGate_Info_t))== NFCSTATUS_SUCCESS)
220          )
221        {
222            psHciContext->p_admin_info = (void *) p_admin_info;
223            p_admin_info->current_seq = ADMIN_PIPE_OPEN;
224            p_admin_info->next_seq = ADMIN_END_SEQUENCE;
225            p_admin_info->admin_pipe_info = NULL;
226        }
227        else
228        {
229            p_admin_info = (phHciNfc_AdminGate_Info_t * )
230                                psHciContext->p_admin_info ;
231        }
232
233        if( NULL == p_admin_info)
234        {
235            status = PHNFCSTVAL(CID_NFC_HCI,
236                        NFCSTATUS_INSUFFICIENT_RESOURCES);
237        }
238        else
239        {
240            switch(p_admin_info->current_seq)
241            {
242                /* Admin pipe open sequence , Initially open the Admin Pipe */
243                case ADMIN_PIPE_OPEN:
244                {
245                    if(phHciNfc_Allocate_Resource((void **)(&p_pipe_info),
246                        sizeof(phHciNfc_Pipe_Info_t))!= NFCSTATUS_SUCCESS)
247                    {
248                        status = PHNFCSTVAL(CID_NFC_HCI,
249                                NFCSTATUS_INSUFFICIENT_RESOURCES);
250                    }
251                    else
252                    {
253                        /* Populate the pipe information in the pipe handle */
254                        ((phHciNfc_Pipe_Info_t *)p_pipe_info)->pipe.pipe_id =
255                                        PIPETYPE_STATIC_ADMIN;
256                        ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_resp =
257                                        &phHciNfc_Recv_Admin_Response;
258                        ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_cmd =
259                                        &phHciNfc_Recv_Admin_Cmd;
260                        ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_event =
261                                        &phHciNfc_Recv_Admin_Event;
262                        psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN] =
263                                                                    p_pipe_info ;
264                        status = phHciNfc_Open_Pipe( psHciContext,
265                                                            pHwRef,p_pipe_info );
266                        if(status == NFCSTATUS_SUCCESS)
267                        {
268                            p_admin_info->admin_pipe_info = p_pipe_info ;
269                            p_admin_info->next_seq = ADMIN_GET_SESSION;
270                            status = NFCSTATUS_PENDING;
271                        }
272                    }
273                    break;
274                }
275                case ADMIN_GET_SESSION:
276                {
277                    p_pipe_info = p_admin_info->admin_pipe_info;
278                    p_pipe_info->reg_index = SESSION_INDEX;
279                    p_pipe_info->prev_status =
280                        phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef,
281                            (uint8_t)HCI_ADMIN_PIPE_ID,
282                                (uint8_t)ANY_GET_PARAMETER);
283                    if(NFCSTATUS_PENDING == p_pipe_info->prev_status )
284                    {
285#ifdef UICC_SESSION_RESET
286                        p_admin_info->next_seq = ADMIN_CLEAR_UICC_PIPES;
287#elif defined (ESTABLISH_SESSION)
288                        p_admin_info->next_seq = ADMIN_VERIFY_SESSION;
289#else
290                        p_admin_info->next_seq = ADMIN_CLEAR_PIPES;
291#endif
292                        status = NFCSTATUS_PENDING;
293                    }
294                    break;
295                }
296#ifdef UICC_SESSION_RESET
297                case ADMIN_CLEAR_UICC_PIPES:
298                {
299                    uint8_t config = 0x00;
300                    p_pipe_info = p_admin_info->admin_pipe_info;
301                     /* TODO: Implement the Clear UICC PIPES Using
302                      * Memory configuration.
303                      */
304                    status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef,
305                            NFC_ADDRESS_UICC_SESSION , config );
306                    if(NFCSTATUS_PENDING == status )
307                    {
308                        p_admin_info->next_seq = ADMIN_CLEAR_PIPES;
309                        status = NFCSTATUS_PENDING;
310                    }
311                    break;
312                }
313#endif
314                case ADMIN_VERIFY_SESSION:
315                {
316                    phHal_sHwConfig_t *p_hw_config =
317                             (phHal_sHwConfig_t *) psHciContext->p_config_params;
318                    phHal_sHwReference_t *p_hw_ref =
319                             (phHal_sHwReference_t *) pHwRef;
320                    int             cmp_val = 0;
321                    p_pipe_info = p_admin_info->admin_pipe_info;
322                    cmp_val = phOsalNfc_MemCompare(p_hw_config->session_id ,
323                                 p_hw_ref->session_id ,
324                                         sizeof(p_hw_ref->session_id));
325                    if((cmp_val == 0)
326                        && ( HCI_SESSION == psHciContext->init_mode)
327                        )
328                    {
329                        psHciContext->hci_mode = hciMode_Session;
330                        status = phHciNfc_Update_Pipe( psHciContext, pHwRef,
331                                                &p_admin_info->pipe_seq );
332                        if((status == NFCSTATUS_SUCCESS)
333                            && (NULL != p_pipe_info))
334                        {
335
336                            p_pipe_info->reg_index = MAX_PIPE_INDEX;
337                            status = phHciNfc_Send_Generic_Cmd( psHciContext,
338                                    pHwRef, (uint8_t)HCI_ADMIN_PIPE_ID,
339                                                    (uint8_t)ANY_GET_PARAMETER );
340                            p_pipe_info->prev_status = status;
341                            if(NFCSTATUS_PENDING == status )
342                            {
343                                p_admin_info->next_seq = ADMIN_PIPE_CLOSE;
344                                status = NFCSTATUS_SUCCESS;
345                            }
346                        }
347                        else
348                        {
349                            status = PHNFCSTVAL(CID_NFC_HCI,
350                                            NFCSTATUS_INVALID_HCI_SEQUENCE);
351                        }
352                        break;
353                    }
354                    else
355                    {
356                        /* To clear the pipe information*/
357                        psHciContext->hci_mode = hciMode_Override;
358                        p_admin_info->current_seq = ADMIN_CLEAR_PIPES;
359                    }
360                }
361                /* fall through */
362                case ADMIN_CLEAR_PIPES:
363                {
364                    p_pipe_info = p_admin_info->admin_pipe_info;
365                    p_pipe_info->prev_status =
366                                    phHciNfc_Send_Admin_Cmd( psHciContext,
367                                        pHwRef, ADM_CLEAR_ALL_PIPE,
368                                            length, p_pipe_info);
369                    status = ((p_pipe_info->prev_status == NFCSTATUS_PENDING)?
370                                            NFCSTATUS_SUCCESS :
371                                                p_pipe_info->prev_status);
372                    if(status == NFCSTATUS_SUCCESS)
373                    {
374                        p_admin_info->next_seq = ADMIN_PIPE_REOPEN;
375                        status = NFCSTATUS_PENDING;
376                    }
377                    break;
378                }
379                /* Admin pipe Re-Open sequence , Re-Open the Admin Pipe */
380                case ADMIN_PIPE_REOPEN:
381                {
382                    p_pipe_info = p_admin_info->admin_pipe_info;
383                    status = phHciNfc_Open_Pipe( psHciContext,
384                                                        pHwRef,p_pipe_info );
385                    if(status == NFCSTATUS_SUCCESS)
386                    {
387                        p_admin_info->next_seq = ADMIN_CREATE_PIPES;
388                        status = NFCSTATUS_PENDING;
389                    }
390                    break;
391                }
392                case ADMIN_CREATE_PIPES:
393                {
394                    status = phHciNfc_Create_All_Pipes( psHciContext, pHwRef,
395                                                        &p_admin_info->pipe_seq );
396                    if(status == NFCSTATUS_SUCCESS)
397                    {
398                        p_admin_info->next_seq = ADMIN_GET_WHITE_LIST;
399                        status = NFCSTATUS_PENDING;
400                    }
401                    break;
402                }
403                case ADMIN_GET_WHITE_LIST:
404                {
405                    p_pipe_info = p_admin_info->admin_pipe_info;
406                    if(NULL == p_pipe_info )
407                    {
408                        status = PHNFCSTVAL(CID_NFC_HCI,
409                                        NFCSTATUS_INVALID_HCI_SEQUENCE);
410                    }
411                    else
412                    {
413                        p_pipe_info->reg_index = WHITELIST_INDEX;
414                        status = phHciNfc_Send_Generic_Cmd( psHciContext,
415                                pHwRef, (uint8_t)HCI_ADMIN_PIPE_ID,
416                                                (uint8_t)ANY_GET_PARAMETER );
417                        p_pipe_info->prev_status = status;
418                        if(HCI_SELF_TEST == psHciContext->init_mode)
419                        {
420                            status = ((NFCSTATUS_PENDING == status )?
421                                            NFCSTATUS_SUCCESS : status);
422                        }
423                        else
424                        {
425                            if(NFCSTATUS_PENDING == status )
426                            {
427                                p_admin_info->next_seq = ADMIN_GET_HOST_LIST;
428                                /* status = NFCSTATUS_SUCCESS; */
429                            }
430                        }
431                    }
432                    break;
433                }
434                case ADMIN_GET_HOST_LIST:
435                {
436                    p_pipe_info = p_admin_info->admin_pipe_info;
437                    if(NULL == p_pipe_info )
438                    {
439                        status = PHNFCSTVAL(CID_NFC_HCI,
440                                        NFCSTATUS_INVALID_HCI_SEQUENCE);
441                    }
442                    else
443                    {
444                        p_pipe_info->reg_index = HOST_LIST_INDEX;
445                        status = phHciNfc_Send_Generic_Cmd( psHciContext,
446                                pHwRef, (uint8_t)HCI_ADMIN_PIPE_ID,
447                                                (uint8_t)ANY_GET_PARAMETER );
448                        p_pipe_info->prev_status = status;
449                        if(NFCSTATUS_PENDING == status )
450                        {
451
452#if defined(HOST_WHITELIST)
453                            p_admin_info->next_seq = ADMIN_SET_WHITE_LIST;
454#else
455                            p_admin_info->next_seq = ADMIN_SET_SESSION;
456                            status = NFCSTATUS_SUCCESS;
457#endif
458                        }
459                    }
460                    break;
461                }
462                case ADMIN_SET_WHITE_LIST:
463                {
464                    p_pipe_info = p_admin_info->admin_pipe_info;
465                    if(NULL == p_pipe_info )
466                    {
467                        status = PHNFCSTVAL(CID_NFC_HCI,
468                                        NFCSTATUS_INVALID_HCI_SEQUENCE);
469                    }
470                    else
471                    {
472                        uint8_t             i = 0;
473
474                        for (i = 0; i < WHITELIST_MAX_LEN - 2; i++ )
475                        {
476                            p_admin_info->whitelist[i] = i + 2;
477                        }
478                        status = phHciNfc_Set_Param(psHciContext, pHwRef,
479                                      p_pipe_info, WHITELIST_INDEX,
480                                        (uint8_t *)p_admin_info->whitelist, i );
481                        if(NFCSTATUS_PENDING == status )
482                        {
483                            p_admin_info->next_seq = ADMIN_SET_SESSION;
484                            status = NFCSTATUS_SUCCESS;
485                        }
486                    }
487                    break;
488                }
489                case ADMIN_SET_SESSION:
490                {
491                    phHal_sHwConfig_t *p_hw_config =
492                             (phHal_sHwConfig_t *) psHciContext->p_config_params;
493                    p_pipe_info = p_admin_info->admin_pipe_info;
494                    status = phHciNfc_Set_Param(psHciContext, pHwRef, p_pipe_info,
495                        SESSION_INDEX, (uint8_t *)(p_hw_config->session_id),
496                            sizeof(p_hw_config->session_id));
497                    if(NFCSTATUS_PENDING == p_pipe_info->prev_status )
498                    {
499                        p_admin_info->next_seq = ADMIN_PIPE_CLOSE;
500                        status = NFCSTATUS_SUCCESS;
501                    }
502                    break;
503                }
504                default:
505                {
506                    status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE);
507                    break;
508                }
509
510            }/* End of the Sequence Switch */
511
512        }/* End of the Admin Info Memory Check */
513
514    }/* End of Null context Check */
515
516    return status;
517}
518
519#ifdef HOST_EMULATION
520
521/*!
522 * \brief Creates the Card Emulation Gate Pipes .
523 *
524 * This function Creates the Card Emulation Gate.
525 */
526
527NFCSTATUS
528phHciNfc_Admin_CE_Init(
529                                phHciNfc_sContext_t     *psHciContext,
530                                void                    *pHwRef,
531                                phHciNfc_GateID_t       ce_gate
532
533                             )
534{
535    NFCSTATUS                           status = NFCSTATUS_SUCCESS;
536    /* phHciNfc_Pipe_Info_t             *pipe_info = NULL; */
537    phHciNfc_AdminGate_Info_t           *p_admin_info=NULL;
538
539    if( (NULL == psHciContext) || (NULL == pHwRef) )
540    {
541      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
542    }
543    else
544    {
545        if( NULL != psHciContext->p_admin_info )
546        {
547            p_admin_info = psHciContext->p_admin_info;
548
549            switch(ce_gate)
550            {
551                /* Card Emulation A Gate Pipe Creation */
552                case phHciNfc_CETypeAGate:
553                {
554                    p_admin_info->pipe_seq = PIPE_CARD_A_CREATE;
555                    break;
556                }
557                /* Card Emulation B Gate Pipe Creation */
558                case phHciNfc_CETypeBGate:
559                {
560                    p_admin_info->pipe_seq = PIPE_CARD_B_CREATE;
561                    break;
562                }
563                default:
564                {
565                    status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_HCI_GATE_NOT_SUPPORTED);
566                    break;
567                }
568            } /* End of CE Gate Switch */
569
570            if (NFCSTATUS_SUCCESS == status)
571            {
572                status = phHciNfc_CE_Pipes_OP( psHciContext,
573                                        pHwRef, &p_admin_info->pipe_seq );
574                if(status == NFCSTATUS_SUCCESS)
575                {
576                    p_admin_info->next_seq = ADMIN_END_SEQUENCE;
577                    /* status = NFCSTATUS_PENDING; */
578                }
579            }
580
581        }/* End of NULL Check for the Admin_Info */
582    } /* End of Null Check for the Context */
583    return status;
584}
585
586#endif
587
588/*!
589 * \brief Releases the resources allocated the Admin Management.
590 *
591 * This function Releases the resources allocated the Admin Management
592 * and resets the hardware to the reset state.
593 */
594
595NFCSTATUS
596phHciNfc_Admin_Release(
597                                phHciNfc_sContext_t     *psHciContext,
598                                void                    *pHwRef,
599                                phHciNfc_HostID_t        host_type
600                             )
601{
602    NFCSTATUS                           status = NFCSTATUS_SUCCESS;
603    phHciNfc_Pipe_Info_t                *p_pipe_info = NULL;
604
605    if( (NULL == psHciContext) || (NULL == pHwRef) )
606    {
607      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
608    }
609    else
610    {
611        if( NULL != psHciContext->p_admin_info )
612        {
613            if(phHciNfc_UICCHostID != host_type)
614            {
615                p_pipe_info = psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN];
616
617                status = phHciNfc_Close_Pipe( psHciContext,
618                                                    pHwRef, p_pipe_info );
619            }
620
621        }/* End of NULL Check for the Admin_Info */
622    } /* End of Null Check for the Context */
623    return status;
624}
625
626
627/*!
628 * \brief Sends the HCI Admin Event to the corresponding peripheral device.
629 *
630 * This function sends the HCI Admin Events to the connected NFC Pheripheral
631 * device
632 */
633
634 NFCSTATUS
635 phHciNfc_Send_Admin_Event (
636                      phHciNfc_sContext_t   *psHciContext,
637                      void                  *pHwRef,
638                      uint8_t               event,
639                      uint8_t               length,
640                      void                  *params
641                     )
642{
643    phHciNfc_HCP_Packet_t       *hcp_packet = NULL;
644    phHciNfc_AdminGate_Info_t   *p_admin_info=NULL;
645    NFCSTATUS                   status = NFCSTATUS_SUCCESS;
646
647    if( (NULL == psHciContext)
648        || (NULL == pHwRef)
649      )
650    {
651      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
652    }
653    else
654    {
655        psHciContext->tx_total = 0 ;
656        length +=  HCP_HEADER_LEN ;
657        p_admin_info = psHciContext->p_admin_info;
658
659        if( EVT_HOT_PLUG ==   event )
660        {
661
662            /* Use the HCP Packet Structure to Construct the send HCP
663                * Packet data.
664                */
665            hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
666            phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
667                                    (uint8_t) HCI_ADMIN_PIPE_ID,
668                                    HCP_MSG_TYPE_EVENT, event);
669        }
670        else
671        {
672            status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INSTRUCTION);
673        }
674
675        if( NFCSTATUS_SUCCESS == status )
676        {
677            p_admin_info->admin_pipe_info->sent_msg_type = HCP_MSG_TYPE_EVENT;
678            p_admin_info->admin_pipe_info->prev_msg = event ;
679            p_admin_info->admin_pipe_info->param_info = params ;
680            psHciContext->tx_total = length;
681            psHciContext->response_pending = FALSE ;
682            status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef );
683            p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_PENDING;
684        }
685    }
686
687    return status;
688}
689
690
691/*!
692 * \brief Sends the HCI Admin Commands to the corresponding peripheral device.
693 *
694 * This function sends the HCI Admin Commands to the connected NFC Pheripheral
695 * device
696 */
697
698 NFCSTATUS
699 phHciNfc_Send_Admin_Cmd (
700                      phHciNfc_sContext_t   *psHciContext,
701                      void                  *pHwRef,
702                      uint8_t               cmd,
703                      uint8_t               length,
704                      void                  *params
705                     )
706{
707    phHciNfc_HCP_Packet_t       *hcp_packet = NULL;
708    phHciNfc_HCP_Message_t      *hcp_message = NULL;
709    phHciNfc_AdminGate_Info_t   *p_admin_info=NULL;
710    phHciNfc_Pipe_Info_t        *p_pipe_info = NULL;
711    uint8_t                     i=0;
712    NFCSTATUS                   status = NFCSTATUS_SUCCESS;
713
714    if( (NULL == psHciContext)
715        || (NULL == pHwRef)
716        || (NULL == params)
717      )
718    {
719      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
720    }
721    else
722    {
723        p_pipe_info = (phHciNfc_Pipe_Info_t *)  params;
724        psHciContext->tx_total = 0 ;
725        length +=  HCP_HEADER_LEN ;
726        p_admin_info = psHciContext->p_admin_info;
727        switch(  cmd )
728        {
729            case ADM_CREATE_PIPE:
730            {
731                hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
732                /* Use the HCP Packet Structure to Construct the send HCP
733                * Packet data.
734                */
735                phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
736                                        (uint8_t) HCI_ADMIN_PIPE_ID,
737                                        HCP_MSG_TYPE_COMMAND, cmd);
738                hcp_message = &(hcp_packet->msg.message);
739
740                /* Source HOST ID Parameter is not passed as a
741                 * parameter in the HCI SPEC */
742
743                /* hcp_message->payload[i++] = p_pipe_info->pipe.source.host_id; */
744                hcp_message->payload[i++] = p_pipe_info->pipe.source.gate_id;
745                hcp_message->payload[i++] = p_pipe_info->pipe.dest.host_id;
746                hcp_message->payload[i++] = p_pipe_info->pipe.dest.gate_id;
747                break;
748            }
749            case ADM_DELETE_PIPE:
750            {
751                uint8_t     pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID;
752
753                pipe_id = p_pipe_info->pipe.pipe_id;
754                if( pipe_id < PIPETYPE_DYNAMIC )
755                {
756                    /* The Static Pipes cannot be Deleted */
757                    status = PHNFCSTVAL(CID_NFC_HCI,
758                                    NFCSTATUS_INVALID_PARAMETER );
759                    HCI_DEBUG("phHciNfc_Send_Admin_Cmd: Static Pipe %u "
760                                                "Cannot be Deleted \n",pipe_id);
761                }
762                else
763                {
764
765                    /* Use the HCP Packet Structure to Construct the send HCP
766                     * Packet data.
767                     */
768                    hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
769                    phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
770                                            (uint8_t) HCI_ADMIN_PIPE_ID,
771                                            HCP_MSG_TYPE_COMMAND, cmd);
772                    hcp_message = &(hcp_packet->msg.message);
773                    hcp_message->payload[i++] = pipe_id ;
774                }
775                break;
776            }
777            case ADM_CLEAR_ALL_PIPE:
778            {
779
780                /* Use the HCP Packet Structure to Construct the send HCP
781                 * Packet data.
782                 */
783                hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
784                phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
785                                        (uint8_t) HCI_ADMIN_PIPE_ID,
786                                        HCP_MSG_TYPE_COMMAND, cmd);
787                hcp_message = &(hcp_packet->msg.message);
788                break;
789            }
790            /* These are notifications and can not be sent by the Host */
791            /* case ADM_NOTIFY_PIPE_CREATED: */
792            /* case ADM_NOTIFY_PIPE_DELETED: */
793            /* case ADM_NOTIFY_ALL_PIPE_CLEARED: */
794            default:
795                status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_COMMAND);
796                break;
797        }
798        if( NFCSTATUS_SUCCESS == status )
799        {
800            p_admin_info->admin_pipe_info->sent_msg_type = HCP_MSG_TYPE_COMMAND;
801            p_admin_info->admin_pipe_info->prev_msg = cmd;
802            p_admin_info->admin_pipe_info->param_info = p_pipe_info;
803            psHciContext->tx_total = length;
804            psHciContext->response_pending = TRUE;
805            status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef );
806            p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_PENDING;
807        }
808    }
809
810    return status;
811}
812
813
814/*!
815 * \brief Receives the HCI Response from the corresponding peripheral device.
816 *
817 * This function receives the HCI Command Response from the connected NFC
818 * Pheripheral device.
819 */
820
821static
822NFCSTATUS
823phHciNfc_Recv_Admin_Response(
824                        void                *psContext,
825                        void                *pHwRef,
826                        uint8_t             *pResponse,
827#ifdef ONE_BYTE_LEN
828                        uint8_t             length
829#else
830                        uint16_t            length
831#endif
832                    )
833{
834    phHciNfc_sContext_t         *psHciContext =
835                                    (phHciNfc_sContext_t *)psContext ;
836    phHciNfc_HCP_Packet_t       *hcp_packet = NULL;
837    phHciNfc_HCP_Message_t      *hcp_message = NULL;
838    phHciNfc_Pipe_Info_t        *p_pipe_info = NULL;
839    phHciNfc_AdminGate_Info_t   *p_admin_info = NULL;
840    NFCSTATUS                   status = NFCSTATUS_SUCCESS;
841    uint8_t                     pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID;
842    uint8_t                     prev_cmd = 0;
843    NFCSTATUS                   prev_status = NFCSTATUS_SUCCESS;
844
845    if( (NULL == psHciContext) || (NULL == pHwRef) )
846    {
847      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
848    }
849    else if ( NULL == psHciContext->p_admin_info )
850    {
851        status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION);
852    }
853    else
854    {
855        hcp_packet = (phHciNfc_HCP_Packet_t *)pResponse;
856        hcp_message = &hcp_packet->msg.message;
857        p_admin_info = psHciContext->p_admin_info;
858        prev_cmd = p_admin_info->admin_pipe_info->prev_msg ;
859        prev_status = p_admin_info->admin_pipe_info->prev_status ;
860        if(prev_status == NFCSTATUS_PENDING)
861        {
862            switch(prev_cmd)
863            {
864                case ANY_SET_PARAMETER:
865                {
866                    break;
867                }
868                case ANY_GET_PARAMETER:
869                {
870                    status = phHciNfc_Admin_InfoUpdate(psHciContext,
871                                (phHal_sHwReference_t *)pHwRef,
872                                p_admin_info->admin_pipe_info->reg_index,
873                                    &pResponse[HCP_HEADER_LEN],
874                                        (uint8_t)(length - HCP_HEADER_LEN));
875                    break;
876                }
877                case ANY_OPEN_PIPE:
878                {
879                    break;
880                }
881                case ANY_CLOSE_PIPE:
882                {
883                    phOsalNfc_FreeMemory(p_admin_info->admin_pipe_info);
884                    p_admin_info->admin_pipe_info = NULL;
885                    psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN] = NULL;
886                    break;
887                }
888                case ADM_CREATE_PIPE:
889                {
890                    p_pipe_info = (phHciNfc_Pipe_Info_t *)
891                                        p_admin_info->admin_pipe_info->param_info;
892                    pipe_id = hcp_message->payload[RESPONSE_PIPEID_OFFSET];
893                    status = phHciNfc_Update_PipeInfo(psHciContext,
894                        &(p_admin_info->pipe_seq), pipe_id, p_pipe_info);
895                    if(NFCSTATUS_SUCCESS == status )
896                    {
897                        psHciContext->p_pipe_list[pipe_id] = p_pipe_info;
898                        p_pipe_info->pipe.pipe_id = pipe_id;
899                    }
900                    break;
901                }
902                case ADM_DELETE_PIPE:
903                {
904                    p_pipe_info = (phHciNfc_Pipe_Info_t *)
905                                    p_admin_info->admin_pipe_info->param_info;
906                    if ( NULL != p_pipe_info )
907                    {
908                        pipe_id = p_pipe_info->pipe.pipe_id;
909                        status = phHciNfc_Update_PipeInfo(
910                            psHciContext, &(p_admin_info->pipe_seq),
911                             (uint8_t) HCI_UNKNOWN_PIPE_ID, p_pipe_info);
912                        if(NFCSTATUS_SUCCESS == status )
913                        {
914                            phOsalNfc_FreeMemory(p_pipe_info);
915                            psHciContext->p_pipe_list[pipe_id] = NULL;
916                        }
917                    }
918                    break;
919                }
920                case ADM_CLEAR_ALL_PIPE:
921                {
922                    break;
923                }
924                default:
925                {
926                    status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE);
927                    HCI_DEBUG("%s: Default Statement Should Not Occur \n",
928                                                    "phHciNfc_Recv_Admin_Response");
929                    break;
930                }
931            }
932        }
933        if( NFCSTATUS_SUCCESS == status )
934        {
935            if( NULL != p_admin_info->admin_pipe_info)
936            {
937                p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_SUCCESS;
938            }
939            p_admin_info->current_seq = p_admin_info->next_seq;
940        }
941    }
942    return status;
943}
944
945/*!
946 * \brief Receives the HCI Admin Commands from the corresponding peripheral device.
947 *
948 * This function receives  the HCI Admin Commands from the connected NFC Pheripheral
949 * device
950 */
951static
952 NFCSTATUS
953 phHciNfc_Recv_Admin_Cmd (
954                        void                *psContext,
955                        void                *pHwRef,
956                        uint8_t             *pCmd,
957#ifdef ONE_BYTE_LEN
958                        uint8_t             length
959#else
960                        uint16_t            length
961#endif
962                     )
963{
964    phHciNfc_sContext_t         *psHciContext =
965                                    (phHciNfc_sContext_t *)psContext ;
966    phHciNfc_HCP_Packet_t       *hcp_packet = NULL;
967    phHciNfc_HCP_Message_t      *hcp_message = NULL;
968    phHciNfc_AdminGate_Info_t   *p_admin_info=NULL;
969    phHciNfc_Pipe_Info_t        *p_pipe_info = NULL;
970    uint8_t                     index=0;
971    uint8_t                     pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID;
972    uint8_t                     cmd = (uint8_t) HCP_MSG_INSTRUCTION_INVALID;
973    uint8_t                     response = (uint8_t) ANY_OK;
974    NFCSTATUS                   status = NFCSTATUS_SUCCESS;
975
976    if( (NULL == psHciContext)
977        || (NULL == pHwRef)
978        || (HCP_HEADER_LEN > length )
979      )
980    {
981      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
982    }
983    else
984    {
985        hcp_packet = (phHciNfc_HCP_Packet_t *)pCmd;
986        hcp_message = &hcp_packet->msg.message;
987        p_admin_info = psHciContext->p_admin_info;
988        /* Get the Command instruction bits from the Message Header */
989        cmd = (uint8_t) GET_BITS8( hcp_message->msg_header,
990            HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN);
991
992        switch( cmd )
993        {
994            /* These are notifications sent by the Host Controller */
995            case ADM_NOTIFY_PIPE_CREATED:
996            {
997                pipe_id = hcp_message->payload[RESPONSE_PIPEID_OFFSET];
998                p_pipe_info = (phHciNfc_Pipe_Info_t *)
999                        phOsalNfc_GetMemory(sizeof(phHciNfc_Pipe_Info_t));
1000                memset(p_pipe_info, 0, sizeof(phHciNfc_Pipe_Info_t));
1001                if(NULL != p_pipe_info)
1002                {
1003                    /* The Source Host is the UICC Host */
1004                    p_pipe_info->pipe.source.host_id =
1005                                    hcp_message->payload[index++];
1006                    /* The Source Gate is same as the Destination Gate */
1007                    p_pipe_info->pipe.source.gate_id    =
1008                                    hcp_message->payload[index++];
1009                    /* The Source Host is the Terminal Host */
1010                    p_pipe_info->pipe.dest.host_id =
1011                                    hcp_message->payload[index++];
1012                    p_pipe_info->pipe.dest.gate_id  =
1013                                    hcp_message->payload[index++];
1014                    p_pipe_info->pipe.pipe_id   =
1015                                    hcp_message->payload[index++];
1016                }
1017                status = phHciNfc_Update_PipeInfo(psHciContext,
1018                    &(p_admin_info->pipe_seq), pipe_id, p_pipe_info);
1019
1020                if( NFCSTATUS_SUCCESS == status )
1021                {
1022                    psHciContext->p_pipe_list[pipe_id] = p_pipe_info;
1023                    if (NULL != p_pipe_info)
1024                    {
1025                        p_pipe_info->pipe.pipe_id = pipe_id;
1026                    }
1027                }
1028                break;
1029            }
1030            case ADM_NOTIFY_PIPE_DELETED:
1031            {
1032                pipe_id = hcp_message->payload[index++];
1033                p_pipe_info = psHciContext->p_pipe_list[pipe_id];
1034                if ( NULL != p_pipe_info )
1035                {
1036                        status = phHciNfc_Update_PipeInfo(
1037                            psHciContext, &(p_admin_info->pipe_seq),
1038                             (uint8_t) HCI_UNKNOWN_PIPE_ID, p_pipe_info);
1039                    if(NFCSTATUS_SUCCESS == status )
1040                    {
1041                        phOsalNfc_FreeMemory(p_pipe_info);
1042                        psHciContext->p_pipe_list[pipe_id] = NULL;
1043                    }
1044                }
1045                break;
1046            }
1047            /* TODO: Since we receive the Host ID, we need to clear
1048             * all the pipes created with the host
1049             */
1050            case ADM_NOTIFY_ALL_PIPE_CLEARED:
1051            {
1052                break;
1053            }
1054            /* case ADM_CREATE_PIPE: */
1055            /* case ADM_DELETE_PIPE: */
1056            /* case ADM_CLEAR_ALL_PIPE: */
1057            default:
1058            {
1059                response = ANY_E_CMD_NOT_SUPPORTED;
1060                status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_COMMAND_NOT_SUPPORTED);
1061                break;
1062            }
1063        }
1064        hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
1065        phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
1066                                (uint8_t) HCI_ADMIN_PIPE_ID,
1067                                HCP_MSG_TYPE_RESPONSE, response );
1068        psHciContext->tx_total = HCP_HEADER_LEN;
1069        status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef );
1070
1071        p_admin_info->admin_pipe_info->recv_msg_type = HCP_MSG_TYPE_COMMAND;
1072        p_admin_info->admin_pipe_info->sent_msg_type = HCP_MSG_TYPE_RESPONSE;
1073        p_admin_info->admin_pipe_info->prev_msg = response;
1074        p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_PENDING;
1075    }
1076    return status;
1077}
1078
1079/*!
1080 * \brief Receives the HCI Admin Event from the corresponding peripheral device.
1081 *
1082 * This function receives  the HCI Admin Events from the connected NFC Pheripheral
1083 * device
1084 */
1085static
1086 NFCSTATUS
1087 phHciNfc_Recv_Admin_Event (
1088                        void                *psContext,
1089                        void                *pHwRef,
1090                        uint8_t             *pEvent,
1091#ifdef ONE_BYTE_LEN
1092                        uint8_t             length
1093#else
1094                        uint16_t            length
1095#endif
1096                     )
1097{
1098    phHciNfc_sContext_t         *psHciContext =
1099                                    (phHciNfc_sContext_t *)psContext ;
1100    phHciNfc_HCP_Packet_t       *hcp_packet = NULL;
1101    phHciNfc_HCP_Message_t      *hcp_message = NULL;
1102    uint8_t                     event = (uint8_t) HCP_MSG_INSTRUCTION_INVALID;
1103    NFCSTATUS                   status = NFCSTATUS_SUCCESS;
1104
1105    if( (NULL == psHciContext)
1106        || (NULL == pHwRef)
1107        || (HCP_HEADER_LEN > length )
1108      )
1109    {
1110      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
1111    }
1112    else
1113    {
1114        hcp_packet = (phHciNfc_HCP_Packet_t *)pEvent;
1115        hcp_message = &hcp_packet->msg.message;
1116        /* Get the Command instruction bits from the Message Header */
1117        event = (uint8_t) GET_BITS8( hcp_message->msg_header,
1118            HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN);
1119
1120        if( EVT_HOT_PLUG ==   event )
1121        {
1122            status = phHciNfc_Send_Admin_Event ( psHciContext, pHwRef,
1123                                EVT_HOT_PLUG, 0 ,NULL);
1124
1125        }
1126        else
1127        {
1128            status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INSTRUCTION);
1129        }
1130
1131
1132    }
1133    return status;
1134}
1135
1136
1137static
1138NFCSTATUS
1139phHciNfc_Admin_InfoUpdate(
1140                                phHciNfc_sContext_t     *psHciContext,
1141                                phHal_sHwReference_t    *pHwRef,
1142                                uint8_t                 index,
1143                                uint8_t                 *reg_value,
1144                                uint8_t             reg_length
1145                          )
1146{
1147    phHciNfc_AdminGate_Info_t   *p_admin_info=NULL;
1148    uint8_t                     i=0;
1149    NFCSTATUS                   status = NFCSTATUS_SUCCESS;
1150    if(NULL == reg_value)
1151    {
1152        status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
1153    }
1154    else
1155    {
1156        p_admin_info = psHciContext->p_admin_info ;
1157        HCI_PRINT_BUFFER("Admin Mgmt Info Buffer",reg_value,reg_length);
1158        switch(index)
1159        {
1160            case SESSION_INDEX :
1161            {
1162                for(i=0 ;(reg_length == SESSIONID_LEN)&&(i < reg_length); i++)
1163                {
1164                    p_admin_info->session_id[i] = reg_value[i];
1165                    pHwRef->session_id[i] = reg_value[i];
1166                }
1167                break;
1168            }
1169            case MAX_PIPE_INDEX :
1170            {
1171                p_admin_info->max_pipe = reg_value[i];
1172                break;
1173            }
1174            case WHITELIST_INDEX :
1175            {
1176                for(i=0 ;(reg_length <= WHITELIST_MAX_LEN)&&(i < reg_length); i++)
1177                {
1178                    p_admin_info->whitelist[i] = reg_value[i];
1179                }
1180                break;
1181            }
1182            case HOST_LIST_INDEX :
1183            {
1184                for(i=0 ;(reg_length <= HOST_LIST_MAX_LEN)&&(i < reg_length); i++)
1185                {
1186                    p_admin_info->host_list[i] = reg_value[i];
1187                }
1188                break;
1189            }
1190            default:
1191            {
1192                status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE);
1193                break;
1194            } /*End of the default Switch Case */
1195
1196        } /*End of the Index Switch */
1197
1198    } /* End of Context and the Identity information validity check */
1199
1200    return status;
1201}
1202
1203