merge with master
[adaptation/devices/nfc-plugin-nxp.git] / src / phHciNfc_LinkMgmt.c
1 /*\r
2  * Copyright (C) 2010 NXP Semiconductors\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 \r
18 /*!\r
19 * =========================================================================== *\r
20 *                                                                             *\r
21 *                                                                             *\r
22 * \file  phHciNfc_LinkMgmt.c                                                  *\r
23 * \brief HCI Link Management Gate Routines.                                   *\r
24 *                                                                             *\r
25 *                                                                             *\r
26 * Project: NFC-FRI-1.1                                                        *\r
27 *                                                                             *\r
28 * $Date: Thu Feb 11 18:52:19 2010 $                                           *\r
29 * $Author: ing04880 $                                                         *\r
30 * $Revision: 1.11 $                                                            *\r
31 * $Aliases: NFC_FRI1.1_WK1007_R33_1,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 $                                                                *\r
32 *                                                                             *\r
33 * =========================================================================== *\r
34 */\r
35 \r
36 /*\r
37 ***************************** Header File Inclusion ****************************\r
38 */\r
39 #include <phNfcCompId.h>\r
40 #include <phHciNfc_Pipe.h>\r
41 #include <phHciNfc_LinkMgmt.h>\r
42 #include <phOsalNfc.h>\r
43 \r
44 /*\r
45 ****************************** Macro Definitions *******************************\r
46 */\r
47 \r
48 #define REC_ERROR_INDEX         0x01U\r
49 \r
50 #define REC_RETRY_LEN           0x02U\r
51 \r
52 /*\r
53 *************************** Structure and Enumeration ***************************\r
54 */\r
55 \r
56 \r
57 /** \defgroup grp_hci_nfc HCI Link Management Component\r
58  *\r
59  *\r
60  */\r
61 \r
62 typedef enum phHciNfc_LinkMgmt_Seq{\r
63     LINK_MGMT_PIPE_OPEN     = 0x00U,\r
64     LINK_MGMT_GET_REC_ERROR,\r
65     LINK_MGMT_SET_REC_ERROR,\r
66     LINK_MGMT_PIPE_CLOSE\r
67 } phHciNfc_LinkMgmt_Seq_t;\r
68 \r
69 typedef struct phHciNfc_LinkMgmt_Info{\r
70     phHciNfc_LinkMgmt_Seq_t link_cur_seq;\r
71     phHciNfc_LinkMgmt_Seq_t link_next_seq;\r
72     phHciNfc_Pipe_Info_t    *p_pipe_info;\r
73     /* Rec Error Count Number from the Host Controller */\r
74     uint16_t                hc_rec_error;\r
75     /* Rec Error Count Number of the Terminal Host */\r
76     uint16_t                rec_error;\r
77 } phHciNfc_LinkMgmt_Info_t;\r
78 \r
79 \r
80 /*\r
81 *************************** Static Function Declaration **************************\r
82 */\r
83 \r
84 static\r
85 NFCSTATUS\r
86 phHciNfc_LinkMgmt_InfoUpdate(\r
87                                 phHciNfc_sContext_t     *psHciContext,\r
88                                 phHal_sHwReference_t    *pHwRef,\r
89                                 uint8_t                 index,\r
90                                 uint8_t                 *reg_value,\r
91                                 uint8_t                 reg_length\r
92                          );\r
93 static\r
94 NFCSTATUS\r
95 phHciNfc_Recv_LinkMgmt_Response(\r
96                         void                *psHciContext,\r
97                         void                *pHwRef,\r
98                         uint8_t             *pResponse,\r
99 #ifdef ONE_BYTE_LEN\r
100                         uint8_t             length\r
101 #else\r
102                         uint16_t            length\r
103 #endif\r
104                        );\r
105 \r
106 \r
107 /*\r
108 *************************** Function Definitions ***************************\r
109 */\r
110 \r
111 \r
112 \r
113 \r
114 /*!\r
115  * \brief Initialisation of Link Managment Gate.\r
116  *\r
117  * This function initialses the Link Management gate and \r
118  * populates the Link Management Information Structure\r
119  * \r
120  */\r
121 \r
122 NFCSTATUS\r
123 phHciNfc_LinkMgmt_Initialise(\r
124                                 phHciNfc_sContext_t     *psHciContext,\r
125                                 void                    *pHwRef\r
126                          )\r
127 {\r
128     NFCSTATUS                           status = NFCSTATUS_SUCCESS;\r
129     phHciNfc_Pipe_Info_t                *p_pipe_info = NULL;\r
130     phHciNfc_LinkMgmt_Info_t            *p_link_mgmt_info=NULL;\r
131     uint8_t                             link_pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID;\r
132 \r
133     if( ( NULL == psHciContext )\r
134         || (NULL == pHwRef )\r
135         )\r
136     {\r
137         status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);\r
138     }\r
139     else\r
140     {\r
141         if( ( NULL == psHciContext->p_link_mgmt_info )\r
142             && (phHciNfc_Allocate_Resource((void **)(&p_link_mgmt_info),\r
143                     sizeof(phHciNfc_LinkMgmt_Info_t))== NFCSTATUS_SUCCESS)\r
144           )\r
145         {\r
146             psHciContext->p_link_mgmt_info = p_link_mgmt_info;\r
147             p_link_mgmt_info->link_cur_seq = LINK_MGMT_PIPE_OPEN;\r
148             p_link_mgmt_info->link_next_seq = LINK_MGMT_PIPE_OPEN;\r
149             p_link_mgmt_info->p_pipe_info = NULL;\r
150         }\r
151         else\r
152         {\r
153             p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *)\r
154                                 psHciContext->p_link_mgmt_info ;\r
155         }\r
156 \r
157         if( NULL == p_link_mgmt_info )\r
158         {\r
159             status = PHNFCSTVAL(CID_NFC_HCI,\r
160                         NFCSTATUS_INVALID_HCI_INFORMATION);\r
161         }\r
162 #ifdef ESTABLISH_SESSION\r
163         else if( hciMode_Session == psHciContext->hci_mode )\r
164         {\r
165             status = NFCSTATUS_SUCCESS;\r
166         }\r
167 #endif\r
168         else\r
169         {\r
170             switch(p_link_mgmt_info->link_cur_seq )\r
171             {\r
172                 /* Link Mgmt pipe open sequence */\r
173                 case LINK_MGMT_PIPE_OPEN:\r
174                 {\r
175                     if(phHciNfc_Allocate_Resource((void **)(&p_pipe_info),\r
176                         sizeof(phHciNfc_Pipe_Info_t))!= NFCSTATUS_SUCCESS)\r
177                     {\r
178                         status = PHNFCSTVAL(CID_NFC_HCI,\r
179                                 NFCSTATUS_INSUFFICIENT_RESOURCES);\r
180                     }\r
181                     else\r
182                     {\r
183                         /* Populate the pipe information in the pipe handle */\r
184                         ((phHciNfc_Pipe_Info_t *)p_pipe_info)->pipe.pipe_id = \r
185                                         PIPETYPE_STATIC_LINK;\r
186                         ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_resp = \r
187                                         &phHciNfc_Recv_LinkMgmt_Response;\r
188                         psHciContext->p_pipe_list[PIPETYPE_STATIC_LINK] =\r
189                                                                     p_pipe_info ;\r
190                         status = phHciNfc_Open_Pipe( psHciContext,\r
191                                                             pHwRef,p_pipe_info );\r
192                         if(status == NFCSTATUS_SUCCESS)\r
193                         {\r
194                             p_link_mgmt_info->p_pipe_info = p_pipe_info ;\r
195                             p_link_mgmt_info->link_next_seq = \r
196                                                     LINK_MGMT_GET_REC_ERROR;\r
197                             status = NFCSTATUS_PENDING;\r
198                         }\r
199                     }\r
200                     break;\r
201                 }\r
202                 case LINK_MGMT_GET_REC_ERROR:\r
203                 {\r
204                     p_pipe_info = p_link_mgmt_info->p_pipe_info;\r
205                     if(NULL == p_pipe_info )\r
206                     {\r
207                         status = PHNFCSTVAL(CID_NFC_HCI, \r
208                                         NFCSTATUS_INVALID_HCI_SEQUENCE);\r
209                     }\r
210                     else\r
211                     {\r
212                         p_pipe_info->reg_index = REC_ERROR_INDEX;\r
213                         link_pipe_id = PIPETYPE_STATIC_LINK ;\r
214                         status = \r
215                             phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, \r
216                                 link_pipe_id,   (uint8_t)ANY_GET_PARAMETER );\r
217                         if(NFCSTATUS_PENDING == status )\r
218                         {\r
219                             p_link_mgmt_info->link_next_seq =\r
220                                                         LINK_MGMT_PIPE_CLOSE;\r
221                             status = NFCSTATUS_SUCCESS;\r
222                         }\r
223                     }\r
224                     break;\r
225                 }\r
226                 case LINK_MGMT_SET_REC_ERROR:\r
227                 {\r
228                     p_pipe_info = p_link_mgmt_info->p_pipe_info;\r
229                     if(NULL == p_pipe_info )\r
230                     {\r
231                         status = PHNFCSTVAL(CID_NFC_HCI, \r
232                                         NFCSTATUS_INVALID_HCI_SEQUENCE);\r
233                     }\r
234                     else\r
235                     {\r
236                         p_pipe_info->reg_index = REC_ERROR_INDEX;\r
237                         link_pipe_id = PIPETYPE_STATIC_LINK ;\r
238                         status = \r
239                             phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, \r
240                                 link_pipe_id,   (uint8_t)ANY_GET_PARAMETER );\r
241                         if(NFCSTATUS_PENDING == status )\r
242                         {\r
243                             p_link_mgmt_info->link_next_seq =\r
244                                                         LINK_MGMT_PIPE_CLOSE;\r
245                             status = NFCSTATUS_SUCCESS;\r
246                         }\r
247                     }\r
248                     break;\r
249                 }\r
250                 default:\r
251                 {\r
252                     status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE);\r
253                     break;\r
254                 }\r
255 \r
256             }/* End of the Sequence Switch */\r
257 \r
258         }/* End of the Link Info Memory Check */\r
259     } /* End of Null Context Check */\r
260 \r
261     return status;\r
262 }\r
263 \r
264 /*!\r
265  * \brief Opens the Link Management Pipe of the Link Management Gate.\r
266  *\r
267  * This function Opens the Link Management Pipe of the Link Management\r
268  * Gate and Confirms that the HCI Link is behaving as expected.\r
269  */\r
270 \r
271 NFCSTATUS\r
272 phHciNfc_LinkMgmt_Open(\r
273                                 phHciNfc_sContext_t     *psHciContext,\r
274                                 void                    *pHwRef\r
275                              )\r
276 {\r
277     NFCSTATUS                           status = NFCSTATUS_SUCCESS;\r
278 \r
279     if( (NULL == psHciContext) || (NULL == pHwRef) )\r
280     {\r
281       status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);\r
282     }\r
283     else\r
284     {\r
285         phHciNfc_LinkMgmt_Info_t  *p_link_mgmt_info=\r
286             (phHciNfc_LinkMgmt_Info_t *)psHciContext->p_link_mgmt_info ;\r
287         if(( NULL != p_link_mgmt_info ) && \r
288                 ( NULL != p_link_mgmt_info->p_pipe_info  ))\r
289         {\r
290             status = phHciNfc_Open_Pipe( psHciContext,\r
291                             pHwRef, p_link_mgmt_info->p_pipe_info );\r
292             if(status == NFCSTATUS_SUCCESS)\r
293             {\r
294                 status = NFCSTATUS_PENDING;\r
295             }\r
296         }\r
297         else\r
298         {\r
299             status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED);\r
300 \r
301         }/* End of the Identity Info Memory Check */\r
302 \r
303     } /* End of Null Context Check */\r
304 \r
305     return status;\r
306 }\r
307 \r
308 \r
309 NFCSTATUS\r
310 phHciNfc_LinkMgmt_Release(\r
311                                 phHciNfc_sContext_t     *psHciContext,\r
312                                 void                    *pHwRef\r
313                              )\r
314 {\r
315     NFCSTATUS                           status = NFCSTATUS_SUCCESS;\r
316     phHciNfc_LinkMgmt_Info_t            *p_link_mgmt_info=NULL;\r
317 \r
318     if( (NULL == psHciContext) || (NULL == pHwRef) )\r
319     {\r
320       status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);\r
321     }\r
322     else\r
323     {\r
324         if( NULL != psHciContext->p_link_mgmt_info )\r
325         {\r
326             p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *)\r
327                                 psHciContext->p_link_mgmt_info ;\r
328             status = phHciNfc_Close_Pipe( psHciContext,\r
329                             pHwRef, p_link_mgmt_info->p_pipe_info );\r
330         }\r
331         else\r
332         {\r
333             status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED);\r
334 \r
335         }/* End of the Identity Info Memory Check */\r
336 \r
337 \r
338     } /* End of Null Context Check */\r
339 \r
340     return status;\r
341 }\r
342 \r
343 \r
344 /*!\r
345  * \brief Receives the HCI Response from the corresponding peripheral device.\r
346  *\r
347  * This function receives the HCI Command Response from the connected NFC\r
348  * Pheripheral device.\r
349  */\r
350 static\r
351 NFCSTATUS\r
352 phHciNfc_Recv_LinkMgmt_Response(\r
353                         void                *psContext,\r
354                         void                *pHwRef,\r
355                         uint8_t             *pResponse,\r
356 #ifdef ONE_BYTE_LEN\r
357                         uint8_t             length\r
358 #else\r
359                         uint16_t            length\r
360 #endif\r
361                     )\r
362 {\r
363     phHciNfc_sContext_t         *psHciContext = \r
364                                     (phHciNfc_sContext_t *)psContext ;\r
365     phHciNfc_LinkMgmt_Info_t    *p_link_mgmt_info=NULL;\r
366     NFCSTATUS                   status = NFCSTATUS_SUCCESS;\r
367     uint8_t                     prev_cmd = ANY_GET_PARAMETER;\r
368 \r
369     if( (NULL == psHciContext) || (NULL == pHwRef) )\r
370     {\r
371       status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);\r
372     }\r
373     else if(  NULL == psHciContext->p_link_mgmt_info )\r
374     {\r
375         status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED);\r
376     }\r
377     else\r
378     {\r
379         p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *)\r
380                             psHciContext->p_link_mgmt_info ;\r
381         prev_cmd = p_link_mgmt_info->p_pipe_info->prev_msg ;\r
382         switch(prev_cmd)\r
383         {\r
384             case ANY_GET_PARAMETER:\r
385             {\r
386                 status = phHciNfc_LinkMgmt_InfoUpdate(psHciContext,\r
387                             (phHal_sHwReference_t *)pHwRef,\r
388                             p_link_mgmt_info->p_pipe_info->reg_index, \r
389                             &pResponse[HCP_HEADER_LEN],\r
390                                 (uint8_t)(length - HCP_HEADER_LEN));\r
391                 break;\r
392             }\r
393             case ANY_SET_PARAMETER:\r
394             {\r
395                 status = PHNFCSTVAL(CID_NFC_HCI,\r
396                                     NFCSTATUS_FEATURE_NOT_SUPPORTED);\r
397                 break;\r
398             }\r
399             case ANY_OPEN_PIPE:\r
400             {\r
401                 break;\r
402             }\r
403             case ANY_CLOSE_PIPE:\r
404             {\r
405                 phOsalNfc_FreeMemory(p_link_mgmt_info->p_pipe_info);\r
406                 p_link_mgmt_info->p_pipe_info = NULL;\r
407                 psHciContext->p_pipe_list[PIPETYPE_STATIC_LINK] = NULL;\r
408                 break;\r
409             }\r
410             default:\r
411             {\r
412                 status = PHNFCSTVAL(CID_NFC_HCI,\r
413                                         NFCSTATUS_INVALID_HCI_RESPONSE);\r
414                 break;\r
415             }\r
416         }\r
417         if( NFCSTATUS_SUCCESS == status )\r
418         {\r
419             if( NULL != p_link_mgmt_info->p_pipe_info)\r
420             {\r
421                 p_link_mgmt_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS;\r
422             }\r
423             p_link_mgmt_info->link_cur_seq = p_link_mgmt_info->link_next_seq;\r
424         }\r
425 \r
426     }\r
427     return status;\r
428 }\r
429 \r
430 \r
431 static\r
432 NFCSTATUS\r
433 phHciNfc_LinkMgmt_InfoUpdate(\r
434                                 phHciNfc_sContext_t     *psHciContext,\r
435                                 phHal_sHwReference_t    *pHwRef,\r
436                                 uint8_t                 index,\r
437                                 uint8_t                 *reg_value,\r
438                                 uint8_t                 reg_length\r
439                           )\r
440 {\r
441     phHciNfc_LinkMgmt_Info_t    *p_link_mgmt_info=NULL;\r
442     NFCSTATUS                   status = NFCSTATUS_SUCCESS;\r
443     uint8_t                     i=0;\r
444     if( (NULL == psHciContext)\r
445         || (NULL == pHwRef)\r
446         || (NULL == reg_value)\r
447         || (reg_length == 0)\r
448       )\r
449     {\r
450         status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);\r
451     }\r
452     else if ( NULL == psHciContext->p_link_mgmt_info )\r
453     {\r
454         status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION);\r
455     }\r
456     else\r
457     {\r
458         p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *)\r
459                                 psHciContext->p_link_mgmt_info ;\r
460         if (REC_ERROR_INDEX == index)\r
461         {\r
462             HCI_PRINT_BUFFER("\tHost Controller REC Error Count :",reg_value,reg_length);\r
463             /* p_link_mgmt_info->hc_rec_error = reg_value[i] ; */\r
464             for(i=0 ;(reg_length == REC_RETRY_LEN)&&(i < reg_length); i++)\r
465             {\r
466                 p_link_mgmt_info->hc_rec_error |= \r
467                             (uint16_t)(reg_value[i] << (BYTE_SIZE * i));\r
468             }\r
469         }\r
470         else\r
471         {\r
472             status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION);\r
473         } /* End of the Index Check */\r
474 \r
475     } /* End of Context and the Link information validity check */\r
476 \r
477     return status;\r
478 }\r