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