nfc_hal_prm.c revision 85b7e84f6cc61506c94e98844cac9ce50bbbe9dc
1/******************************************************************************
2 *
3 *  Copyright (C) 2012-2013 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18#include <string.h>
19#include "nfc_hal_int.h"
20#include "userial.h"
21
22/*****************************************************************************
23* Definitions
24*****************************************************************************/
25
26/* Internal flags */
27#define NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF  0x01    /* Application provided patchram in a single buffer */
28#define NFC_HAL_PRM_FLAGS_RFU               0x02    /* Reserved for future use */
29#define NFC_HAL_PRM_FLAGS_SIGNATURE_SENT    0x04    /* Signature sent to NFCC */
30#define NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED  0x08    /* PreI2C patch required */
31#define NFC_HAL_PRM_FLAGS_NO_NVM            0x10    /* Not NVM available (patch downloaded to SRAM) */
32#define NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF 0x20    /* Support RESET_NTF from NFCC after sending signature */
33#define NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED 0x40    /* FPM patch in NVM failed CRC check */
34#define NFC_HAL_PRM_FLAGS_NVM_LPM_CORRUPTED 0x80    /* LPM patch in NVM failed CRC check */
35
36/* Secure patch download definitions */
37#define NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN  7       /* PRJID + MAJORVER + MINORVER + COUNT */
38#define NFC_HAL_PRM_NCD_PATCH_VERSION_LEN  16
39
40#define NFC_HAL_PRM_SPD_PRE_DOWNLOAD_DELAY (500)   /* Delay before starting to patch download (in ms) */
41
42/* Enumeration of power modes IDs */
43#define NFC_HAL_PRM_SPD_POWER_MODE_LPM     0
44#define NFC_HAL_PRM_SPD_POWER_MODE_FPM     1
45
46/* Version string for BCM20791B3 */
47const UINT8 NFC_HAL_PRM_BCM20791B3_STR[]   = "20791B3";
48#define NFC_HAL_PRM_BCM20791B3_STR_LEN     (sizeof (NFC_HAL_PRM_BCM20791B3_STR)-1)
49
50#define NFC_HAL_PRM_SPD_TOUT                   (6000)  /* timeout for SPD events (in ms)   */
51#define NFC_HAL_PRM_END_DELAY                  (250)   /* delay before sending any new command (ms)*/
52
53/* command to get currently downloaded patch version */
54static UINT8 nfc_hal_prm_get_patch_version_cmd [NCI_MSG_HDR_SIZE] =
55{
56    NCI_MTS_CMD|NCI_GID_PROP,
57    NCI_MSG_GET_PATCH_VERSION,
58    0x00
59};
60
61#if (NFC_HAL_PRM_DEBUG == TRUE)
62#define NFC_HAL_PRM_STATE(str)  NCI_TRACE_DEBUG2 ("%s st: %d", str, nfc_hal_cb.prm.state)
63#else
64#define NFC_HAL_PRM_STATE(str)
65#endif
66
67void nfc_hal_prm_post_baud_update (tHAL_NFC_STATUS status);
68
69/*****************************************************************************
70** Extern variable from nfc_hal_dm_cfg.c
71*****************************************************************************/
72extern BOOLEAN nfc_hal_prm_nvm_required;
73
74/*******************************************************************************
75**
76** Function         nfc_hal_prm_spd_handle_download_complete
77**
78** Description      Patch download complete (for secure patch download)
79**
80** Returns          void
81**
82*******************************************************************************/
83void nfc_hal_prm_spd_handle_download_complete (UINT8 event)
84{
85    nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_IDLE;
86
87    /* Notify application now */
88    if (nfc_hal_cb.prm.p_cback)
89        (nfc_hal_cb.prm.p_cback) (event);
90}
91
92/*******************************************************************************
93**
94** Function         nfc_hal_prm_spd_send_next_segment
95**
96** Description      Send next patch segment (for secure patch download)
97**
98** Returns          void
99**
100*******************************************************************************/
101void nfc_hal_prm_spd_send_next_segment (void)
102{
103    UINT8   *p_src;
104    UINT16  len, offset = nfc_hal_cb.prm.cur_patch_offset;
105    UINT8   hcit, oid, hdr0, type;
106    UINT8   chipverlen;
107    UINT8   chipverstr[NCI_SPD_HEADER_CHIPVER_LEN];
108    UINT8   patch_hdr_size = NCI_MSG_HDR_SIZE + 1; /* 1 is for HCIT */
109
110    /* Validate that segment is at least big enought to have NCI_MSG_HDR_SIZE + 1 (hcit) */
111    if (nfc_hal_cb.prm.cur_patch_len_remaining < patch_hdr_size)
112    {
113        NCI_TRACE_ERROR0 ("Unexpected end of patch.");
114        nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
115        return;
116    }
117
118    /* Parse NCI command header */
119    p_src = (UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset);
120    STREAM_TO_UINT8 (hcit, p_src);
121    STREAM_TO_UINT8 (hdr0, p_src);
122    STREAM_TO_UINT8 (oid,  p_src);
123    STREAM_TO_UINT8 (len,  p_src);
124    STREAM_TO_UINT8 (type, p_src);
125
126
127    /* Update number of bytes comsumed */
128    nfc_hal_cb.prm.cur_patch_offset += (len + patch_hdr_size);
129    nfc_hal_cb.prm.cur_patch_len_remaining -=  (len + patch_hdr_size);
130
131    /* Check if sending signature byte */
132    if (  (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD )
133        &&(type == NCI_SPD_TYPE_SIGNATURE)  )
134    {
135        nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
136    }
137    /* Check for header */
138    else if (  (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD )
139             &&(type == NCI_SPD_TYPE_HEADER)  )
140    {
141        /* Check if patch is for BCM20791B3 */
142        p_src += NCI_SPD_HEADER_OFFSET_CHIPVERLEN;
143        STREAM_TO_UINT8 (chipverlen, p_src);
144        STREAM_TO_ARRAY (chipverstr, p_src, NCI_SPD_HEADER_CHIPVER_LEN);
145
146        if (memcmp (NFC_HAL_PRM_BCM20791B3_STR, chipverstr, NFC_HAL_PRM_BCM20791B3_STR_LEN) == 0)
147        {
148            /* Patch is for BCM2079B3 - do not wait for RESET_NTF after patch download */
149            nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF;
150        }
151        else
152        {
153            /* Patch is for BCM2079B4 or newer - wait for RESET_NTF after patch download */
154            nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF;
155        }
156    }
157
158    /* Send the command (not including HCIT here) */
159    nfc_hal_dm_send_nci_cmd ((UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset + 1), (UINT8) (len + NCI_MSG_HDR_SIZE),
160                             nfc_hal_prm_nci_command_complete_cback);
161}
162
163/*******************************************************************************
164**
165** Function         nfc_hal_prm_spd_handle_next_patch_start
166**
167** Description      Handle start of next patch (for secure patch download)
168**
169** Returns          void
170**
171*******************************************************************************/
172void nfc_hal_prm_spd_handle_next_patch_start (void)
173{
174    UINT32  cur_patch_mask;
175    UINT32  cur_patch_len;
176    BOOLEAN found_patch_to_download = FALSE;
177
178    while (!found_patch_to_download)
179    {
180        /* Get length of current patch */
181        cur_patch_len = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len;
182
183        /* Check if this is a patch we need to download */
184        cur_patch_mask = ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
185        if (nfc_hal_cb.prm.spd_patch_needed_mask & cur_patch_mask)
186        {
187            found_patch_to_download = TRUE;
188        }
189        else
190        {
191            /* Do not need to download this patch. Skip to next patch */
192            NCI_TRACE_DEBUG1 ("Skipping patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
193
194            nfc_hal_cb.prm.spd_cur_patch_idx++;
195            if (nfc_hal_cb.prm.spd_cur_patch_idx >= nfc_hal_cb.prm.spd_patch_count)
196            {
197                /* No more to download */
198                nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT);
199                return;
200            }
201            else if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF))
202            {
203                /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch header */
204                (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
205                return;
206            }
207            else
208            {
209                /* Patch in buffer. Skip over current patch. Check next patch */
210                nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) cur_patch_len;
211                nfc_hal_cb.prm.cur_patch_offset += (UINT16) cur_patch_len;
212            }
213        }
214    }
215
216
217    /* Begin downloading patch */
218    NCI_TRACE_DEBUG1 ("Downloading patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
219    nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_DOWNLOADING;
220    nfc_hal_prm_spd_send_next_segment ();
221}
222
223#if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
224/*******************************************************************************
225**
226** Function         nfc_hal_prm_spd_download_i2c_fix
227**
228** Description      Start downloading patch for i2c fix
229**
230** Returns          void
231**
232*******************************************************************************/
233void nfc_hal_prm_spd_download_i2c_fix (void)
234{
235    UINT8 *p, *p_start;
236    UINT16 patchfile_project_id;
237    UINT16 patchfile_ver_major;
238    UINT16 patchfile_ver_minor;
239    UINT16 patchfile_patchsize;
240    UINT8 u8;
241
242    NCI_TRACE_DEBUG0 ("Downloading I2C fix...");
243
244    /* Save pointer and offset of patchfile, so we can resume after downloading the i2c fix */
245    nfc_hal_cb.prm.spd_patch_offset = nfc_hal_cb.prm.cur_patch_offset;
246    nfc_hal_cb.prm.spd_patch_len_remaining = nfc_hal_cb.prm.cur_patch_len_remaining;
247
248    /* Initialize pointers for downloading i2c fix */
249    nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm_i2c.p_patch;
250    nfc_hal_cb.prm.cur_patch_offset = 0;
251    nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm_i2c.len;
252
253    /* Parse the i2c patchfile */
254    if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN)
255    {
256        /* Parse patchfile header */
257        p = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data;
258        p_start = p;
259        STREAM_TO_UINT16 (patchfile_project_id, p);
260        STREAM_TO_UINT16 (patchfile_ver_major, p);
261        STREAM_TO_UINT16 (patchfile_ver_minor, p);
262
263        /* RFU */
264        p++;
265
266        /* Check how many patches are in the patch file */
267        STREAM_TO_UINT8 (u8, p);
268
269        /* Should only be one patch */
270        if (u8 > 1)
271        {
272            NCI_TRACE_ERROR1 ("Invalid i2c fix: invalid number of patches (%i)", u8);
273            nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
274            return;
275        }
276
277
278        /* Get info about the i2c patch*/
279        STREAM_TO_UINT8 (u8, p);                     /* power mode (not needed for i2c patch)    */
280        STREAM_TO_UINT16 (patchfile_patchsize, p);   /* size of patch                            */
281
282        /* 5 byte RFU */
283        p += 5;
284
285        /* Adjust length to exclude patchfiloe header */
286        nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start);       /* Adjust size of patchfile                        */
287        nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start);              /* Bytes of patchfile transmitted/processed so far */
288
289        /* Begin sending patch to the NFCC */
290        nfc_hal_prm_spd_send_next_segment ();
291    }
292    else
293    {
294        /* ERROR: Bad length for patchfile */
295        NCI_TRACE_ERROR0 ("Invalid i2c fix: unexpected end of patch");
296        nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
297    }
298}
299#endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
300
301/*******************************************************************************
302**
303** Function         nfc_hal_prm_spd_check_version
304**
305** Description      Check patchfile version with current downloaded version
306**
307** Returns          void
308**
309*******************************************************************************/
310void nfc_hal_prm_spd_check_version (void)
311{
312    UINT8 *p, *p_start, i;
313    UINT32 patchfile_patch_present_mask;
314    UINT16 patchfile_project_id;
315    UINT16 patchfile_ver_major = 0;
316    UINT16 patchfile_ver_minor;
317    UINT16 patchfile_patchsize;
318
319    UINT8  return_code = NFC_HAL_PRM_COMPLETE_EVT;
320
321    /* Initialize patchfile offset pointers */
322    p = p_start = NULL;
323    patchfile_patchsize = 0;
324
325    /* Get patchfile version */
326    if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN)
327    {
328        /* Parse patchfile header */
329        p       = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data;
330        p_start = p;
331        STREAM_TO_UINT16 (patchfile_project_id, p);
332        STREAM_TO_UINT16 (patchfile_ver_major, p);
333        STREAM_TO_UINT16 (patchfile_ver_minor, p);
334
335        /* RFU */
336        p++;
337
338        /* Check how many patches are in the patch file */
339        STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_count, p);
340
341        if (nfc_hal_cb.prm.spd_patch_count > NFC_HAL_PRM_MAX_PATCH_COUNT)
342        {
343            NCI_TRACE_ERROR2 ("Unsupported patchfile (number of patches (%i) exceeds maximum (%i)",
344                               nfc_hal_cb.prm.spd_patch_count, NFC_HAL_PRM_MAX_PATCH_COUNT);
345        }
346
347        /* Mask of patches that are present in the patchfile */
348        patchfile_patch_present_mask = 0;
349
350        /* Get lengths for each patch */
351        for (i = 0; i < nfc_hal_cb.prm.spd_patch_count; i++)
352        {
353            /* Get power mode for this patch */
354            STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_desc[i].power_mode, p);
355
356            /* Update mask of power-modes present in the patchfile */
357            patchfile_patch_present_mask |= ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[i].power_mode);
358
359            /* Get length of patch */
360            STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_patch_desc[i].len, p);
361
362            /* Add total size of patches */
363            patchfile_patchsize += nfc_hal_cb.prm.spd_patch_desc[i].len;
364
365            /* 5 byte RFU */
366            p += 5;
367        }
368
369        /* Adjust offset to after the patch file header */
370        nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start);              /* Bytes of patchfile transmitted/processed so far */
371        nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start);       /* Adjust size of patchfile                        */
372
373
374        NCI_TRACE_DEBUG6 ("Patchfile info: ProjID=0x%04x,  Ver=%i.%i, Num patches=%i, PatchMask=0x%08x, PatchSize=%i",
375                           patchfile_project_id, patchfile_ver_major, patchfile_ver_minor,
376                           nfc_hal_cb.prm.spd_patch_count, patchfile_patch_present_mask, patchfile_patchsize);
377
378        /*********************************************************************
379        * Version check of patchfile against NVM
380        *********************************************************************/
381
382#if (!defined (NFC_HAL_PRM_SKIP_VERSION_CHECK) || (NFC_HAL_PRM_SKIP_VERSION_CHECK == FALSE))
383        /* Download the patchfile if no patches in NVM */
384        if ((nfc_hal_cb.prm.spd_project_id == 0) || (nfc_hal_cb.prm.spd_nvm_patch_mask == 0))
385        {
386            /* No patch in NVM, need to download all */
387            nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
388
389            NCI_TRACE_DEBUG2 ("No previous patch detected. Downloading patch %i.%i",
390                              patchfile_ver_major, patchfile_ver_minor);
391        }
392        /* Skip download if project ID of patchfile does not match NVM */
393        else if (nfc_hal_cb.prm.spd_project_id != patchfile_project_id)
394        {
395            /* Project IDs mismatch */
396            NCI_TRACE_DEBUG2 ("Patch download skipped: Mismatched Project ID (NVM ProjId: 0x%04x, Patchfile ProjId: 0x%04x)",
397                              nfc_hal_cb.prm.spd_project_id, patchfile_project_id);
398
399            return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT;
400        }
401        /* Skip download if version of patchfile older or equal to version in NVM */
402        /* unless NVM is corrupted (then don't skip download if patchfile has the same major ver)*/
403        else if (  (nfc_hal_cb.prm.spd_ver_major > patchfile_ver_major)
404                 ||(  (nfc_hal_cb.prm.spd_ver_major == patchfile_ver_major) && (nfc_hal_cb.prm.spd_ver_minor == patchfile_ver_minor)
405                    && !((patchfile_patch_present_mask & ( 1 << NFC_HAL_PRM_SPD_POWER_MODE_LPM)) && (nfc_hal_cb.prm.spd_lpm_patch_size == 0))  /* Do not skip download: patchfile has LPM, but NVM does not */
406                    && !((patchfile_patch_present_mask & ( 1 << NFC_HAL_PRM_SPD_POWER_MODE_FPM)) && (nfc_hal_cb.prm.spd_fpm_patch_size == 0))  /* Do not skip download: patchfile has FPM, but NVM does not */
407                    && !(nfc_hal_cb.prm.flags & (NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED |NFC_HAL_PRM_FLAGS_NVM_LPM_CORRUPTED))  )  )
408        {
409            /* NVM version is newer than patchfile */
410            NCI_TRACE_DEBUG2 ("Patch download skipped. NVM patch (version %i.%i) is newer than the patchfile ",
411                              nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
412
413            return_code = NFC_HAL_PRM_COMPLETE_EVT;
414        }
415        /* Remaining cases: patchfile major version is newer than NVM; or major version is the same with different minor version */
416        /* Download all patches in the patchfile */
417        else
418        {
419            nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
420
421            NCI_TRACE_DEBUG4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...",
422                              patchfile_ver_major, patchfile_ver_minor,
423                              nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
424        }
425#else   /* NFC_HAL_PRM_SKIP_VERSION_CHECK */
426        nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
427#endif
428    }
429    else
430    {
431        /* Invalid patch file header */
432        NCI_TRACE_ERROR0 ("Invalid patch file header.");
433
434        return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT;
435    }
436
437    /* If we need to download anything, get the first patch to download */
438    if (nfc_hal_cb.prm.spd_patch_needed_mask)
439    {
440        NCI_TRACE_ERROR4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...",
441                            patchfile_ver_major, patchfile_ver_minor,
442                            nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
443#if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
444        /* Check if I2C patch is needed: if                                     */
445        /*      - I2C patch file was provided using HAL_NfcPrmSetI2cPatch, and        */
446        /*      -   current patch in NVM has ProjectID=0, or                    */
447        /*          FPM is not present or corrupted, or                         */
448        /*          or patchfile is major-ver 76+                               */
449        if (  (nfc_hal_cb.prm_i2c.p_patch)
450            &&(  (nfc_hal_cb.prm.spd_project_id == 0)
451               ||(nfc_hal_cb.prm.spd_fpm_patch_size == 0)
452               ||(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED)
453               ||(patchfile_ver_major >= 76)))
454        {
455            NCI_TRACE_DEBUG0 ("I2C patch fix required.");
456            nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED;
457
458            /* Download i2c fix first */
459            nfc_hal_prm_spd_download_i2c_fix ();
460            return;
461        }
462#endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
463
464        /* Download first segment */
465        nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
466        if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF))
467        {
468            /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch segment */
469            (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
470        }
471        else
472        {
473            nfc_hal_prm_spd_handle_next_patch_start ();
474        }
475    }
476    else
477    {
478        static BOOLEAN firstTime = TRUE;
479        if (firstTime) {
480            NCI_TRACE_ERROR2 ("BCM2079x: NVM patch version is %d.%d",
481                    nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
482            firstTime = FALSE;
483        }
484        /* Download complete */
485        nfc_hal_prm_spd_handle_download_complete (return_code);
486    }
487}
488
489#if (NFC_HAL_TRACE_VERBOSE == TRUE)
490/*******************************************************************************
491**
492** Function         nfc_hal_prm_spd_status_str
493**
494** Description      Return status string for a given spd status code
495**
496** Returns          Status string
497**
498*******************************************************************************/
499UINT8 *nfc_hal_prm_spd_status_str (UINT8 spd_status_code)
500{
501    char *p_str;
502
503    switch (spd_status_code)
504    {
505    case NCI_STATUS_SPD_ERROR_DEST:
506        p_str = "SPD_ERROR_DEST";
507        break;
508
509    case NCI_STATUS_SPD_ERROR_PROJECTID:
510        p_str = "SPD_ERROR_PROJECTID";
511        break;
512
513    case NCI_STATUS_SPD_ERROR_CHIPVER:
514        p_str = "SPD_ERROR_CHIPVER";
515        break;
516
517    case NCI_STATUS_SPD_ERROR_MAJORVER:
518        p_str = "SPD_ERROR_MAJORVER";
519        break;
520
521    case NCI_STATUS_SPD_ERROR_INVALID_PARAM:
522        p_str = "SPD_ERROR_INVALID_PARAM";
523        break;
524
525    case NCI_STATUS_SPD_ERROR_INVALID_SIG:
526        p_str = "SPD_ERROR_INVALID_SIG";
527        break;
528
529    case NCI_STATUS_SPD_ERROR_NVM_CORRUPTED:
530        p_str = "SPD_ERROR_NVM_CORRUPTED";
531        break;
532
533    case NCI_STATUS_SPD_ERROR_PWR_MODE:
534        p_str = "SPD_ERROR_PWR_MODE";
535        break;
536
537    case NCI_STATUS_SPD_ERROR_MSG_LEN:
538        p_str = "SPD_ERROR_MSG_LEN";
539        break;
540
541    case NCI_STATUS_SPD_ERROR_PATCHSIZE:
542        p_str = "SPD_ERROR_PATCHSIZE";
543        break;
544
545    default:
546        p_str = "Unspecified Error";
547        break;
548
549    }
550
551    return ((UINT8*) p_str);
552}
553#endif  /* (NFC_HAL_TRACE_VERBOSE == TRUE) */
554
555/*******************************************************************************
556**
557** Function         nfc_hal_prm_nci_command_complete_cback
558**
559** Description      Callback for NCI vendor specific command complete
560**                  (for secure patch download)
561**
562** Returns          void
563**
564*******************************************************************************/
565void nfc_hal_prm_nci_command_complete_cback (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data)
566{
567    UINT8 status, u8;
568    UINT8 *p;
569    UINT32 post_signature_delay;
570
571    NFC_HAL_PRM_STATE ("nfc_hal_prm_nci_command_complete_cback");
572
573    /* Stop the command-timeout timer */
574    nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer);
575
576    /* Skip over NCI header */
577    p = p_data + NCI_MSG_HDR_SIZE;
578
579    /* Handle GET_PATCH_VERSION Rsp */
580    if (event == NFC_VS_GET_PATCH_VERSION_EVT)
581    {
582        /* Get project id */
583        STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_project_id, p);
584
585        /* RFU */
586        p++;
587
588        /* Get chip version string */
589        STREAM_TO_UINT8 (u8, p);
590        p += NFC_HAL_PRM_NCD_PATCH_VERSION_LEN;
591
592        /* Get major/minor version */
593        STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_ver_major, p);
594        STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_ver_minor, p);
595        STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_nvm_max_size, p);
596        STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_patch_max_size, p);
597        STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_lpm_patch_size, p);
598        STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_fpm_patch_size, p);
599
600        /* LPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is present in nvm) */
601        STREAM_TO_UINT8 (u8, p);
602        if (!u8)
603        {
604            nfc_hal_cb.prm.spd_nvm_patch_mask |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_LPM);
605        }
606        else
607        {
608            /* LPM patch in NVM fails CRC check */
609            nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_NVM_LPM_CORRUPTED;
610        }
611
612
613        /* FPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is present in nvm) */
614        STREAM_TO_UINT8 (u8, p);
615        if (!u8)
616        {
617            nfc_hal_cb.prm.spd_nvm_patch_mask |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_FPM);
618        }
619        else
620        {
621            /* FPM patch in NVM fails CRC check */
622            nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED;
623        }
624
625        /* Check if downloading patch to RAM only (no NVM) */
626        STREAM_TO_UINT8 (u8, p);
627        if (!u8)
628        {
629            if (nfc_hal_prm_nvm_required)
630            {
631                NCI_TRACE_ERROR0 ("This platform requires NVM and the NVM is not available - Abort");
632                nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_NO_NVM_EVT);
633                return;
634            }
635            nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_NO_NVM;
636        }
637
638        /* Get patchfile version number */
639        nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_COMPARE_VERSION;
640
641        if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
642        {
643            /* If patch is in a buffer, get patch version from buffer */
644            nfc_hal_prm_spd_check_version ();
645        }
646        else
647        {
648            /* Notify adaptation layer to send patch version (via HAL_NfcPrmDownloadContinue) */
649            (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_PATCHFILE_HDR_EVT);
650        }
651
652    }
653    /* Handle SECURE_PATCH_DOWNLOAD Rsp */
654    else if (event == NFC_VS_SEC_PATCH_DOWNLOAD_EVT)
655    {
656        /* Status and error code */
657        STREAM_TO_UINT8 (status, p);
658        STREAM_TO_UINT8 (u8, p);
659
660        if (status != NCI_STATUS_OK)
661        {
662#if (NFC_HAL_TRACE_VERBOSE == TRUE)
663            NCI_TRACE_ERROR2 ("Patch download failed, reason code=0x%X (%s)", status, nfc_hal_prm_spd_status_str (status));
664#else
665            NCI_TRACE_ERROR1 ("Patch download failed, reason code=0x%X", status);
666#endif
667
668            /* Notify application */
669            nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
670            return;
671        }
672
673        /* If last segment (SIGNATURE) sent */
674        if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SIGNATURE_SENT)
675        {
676            /* Wait for authentication complate (SECURE_PATCH_DOWNLOAD NTF) */
677            nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTHENTICATING;
678            nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
679                                            (NFC_HAL_PRM_SPD_TOUT * QUICK_TIMER_TICKS_PER_SEC) / 1000);
680            return;
681        }
682        /* Download next segment */
683        else if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
684        {
685            /* If patch is in a buffer, get next patch from buffer */
686            nfc_hal_prm_spd_send_next_segment ();
687        }
688        else
689        {
690            /* Notify adaptation layer to get next patch segment (via HAL_NfcPrmDownloadContinue) */
691            (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_CONTINUE_EVT);
692        }
693    }
694    /* Handle SECURE_PATCH_DOWNLOAD NTF */
695    else if (event == NFC_VS_SEC_PATCH_AUTH_EVT)
696    {
697        NCI_TRACE_DEBUG1 ("prm flags:0x%x.", nfc_hal_cb.prm.flags);
698        /* Status and error code */
699        STREAM_TO_UINT8 (status, p);
700        STREAM_TO_UINT8 (u8, p);
701
702        /* Sanity check - should only get this NTF while in AUTHENTICATING stage */
703        if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTHENTICATING)
704        {
705            if (status != NCI_STATUS_OK)
706            {
707                NCI_TRACE_ERROR0 ("Patch authentication failed");
708                nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_BAD_SIGNATURE_EVT);
709                return;
710            }
711
712#if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
713            if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED)
714            {
715                NCI_TRACE_DEBUG1 ("PreI2C patch downloaded...waiting %i ms for NFCC to reboot.", nfc_hal_cb.prm_i2c.prei2c_delay);
716
717                /* Restore pointers to patchfile */
718                nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED;
719                nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm.p_spd_patch;
720                nfc_hal_cb.prm.cur_patch_offset = nfc_hal_cb.prm.spd_patch_offset;
721                nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm.spd_patch_len_remaining;
722
723                /* Resume normal patch download */
724                nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
725                nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
726
727                /* Post PreI2C delay */
728                nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00, (nfc_hal_cb.prm_i2c.prei2c_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000);
729
730                return;
731            }
732#endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
733
734
735            /* Wait for NFCC to save the patch to NVM */
736            if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF)
737            {
738                /* 20791B4 or newer - wait for RESET_NTF */
739                post_signature_delay = NFC_HAL_PRM_RESET_NTF_DELAY;
740                NCI_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for RESET NTF...", post_signature_delay);
741
742            }
743            else if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_NO_NVM)
744            {
745                /* No NVM. Wait for NFCC to restart */
746                post_signature_delay = NFC_HAL_PRM_END_DELAY;
747                NCI_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NFCC to restart...", post_signature_delay);
748            }
749            else
750            {
751                /* Wait for NFCC to save the patch to NVM (need about 1 ms per byte) */
752                post_signature_delay = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len;
753                if (post_signature_delay < nfc_hal_cb.prm.patchram_delay)
754                    post_signature_delay = nfc_hal_cb.prm.patchram_delay;
755                NCI_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NVM update to complete...", post_signature_delay);
756            }
757
758            nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTH_DONE;
759
760            nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
761                                            (post_signature_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000);
762        }
763        else
764        {
765            NCI_TRACE_ERROR0 ("Got unexpected SECURE_PATCH_DOWNLOAD NTF");
766            nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
767        }
768    }
769    else
770    {
771        /* Invalid response from NFCC during patch download */
772        NCI_TRACE_ERROR1 ("Invalid response from NFCC during patch download (opcode=0x%02X)", event);
773        nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
774    }
775
776    NFC_HAL_PRM_STATE ("prm_nci_command_complete_cback");
777}
778
779/*******************************************************************************
780**
781** Function         nfc_hal_prm_nfcc_ready_to_continue
782**
783** Description      Continue to download patch or notify application completition
784**
785** Returns          void
786**
787*******************************************************************************/
788void nfc_hal_prm_nfcc_ready_to_continue (void)
789{
790    /* Clear the bit for the patch we just downloaded */
791    nfc_hal_cb.prm.spd_patch_needed_mask &= ~ ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
792
793    /* Check if another patch to download */
794    nfc_hal_cb.prm.spd_cur_patch_idx++;
795    if ((nfc_hal_cb.prm.spd_patch_needed_mask) && (nfc_hal_cb.prm.spd_cur_patch_idx < nfc_hal_cb.prm.spd_patch_count))
796    {
797        nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
798        nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
799
800        if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
801        {
802            /* If patch is in a buffer, get next patch from buffer */
803            nfc_hal_prm_spd_handle_next_patch_start ();
804        }
805        else
806        {
807            /* Notify adaptation layer to get next patch header (via HAL_NfcPrmDownloadContinue) */
808            (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
809        }
810
811    }
812    else
813    {
814        /* Done downloading */
815        NCI_TRACE_DEBUG0 ("Patch downloaded and authenticated.");
816        nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT);
817    }
818}
819
820/*******************************************************************************
821**
822** Function         nfc_hal_prm_spd_reset_ntf
823**
824** Description      Received RESET NTF from NFCC, indicating it has completed
825**                  reset after patch download.
826**
827** Returns          void
828**
829*******************************************************************************/
830void nfc_hal_prm_spd_reset_ntf (UINT8 reset_reason, UINT8 reset_type)
831{
832    /* Check if we were expecting a RESET NTF */
833    if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
834    {
835        NCI_TRACE_DEBUG2 ("Received RESET NTF after patch download (reset_reason=%i, reset_type=%i)", reset_reason, reset_type);
836
837        /* Stop waiting for RESET NTF */
838        nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer);
839
840        {
841        /* Continue with patch download */
842        nfc_hal_prm_nfcc_ready_to_continue ();
843    }
844    }
845    else
846    {
847        NCI_TRACE_ERROR2 ("Received unexpected RESET NTF (reset_reason=%i, reset_type=%i)", reset_reason, reset_type);
848    }
849}
850
851/*******************************************************************************
852**
853** Function:    nfc_post_final_baud_update
854**
855** Description: Called after baud rate udate
856**
857** Returns:     Nothing
858**
859*******************************************************************************/
860void nfc_hal_prm_post_baud_update (tHAL_NFC_STATUS status)
861{
862    NFC_HAL_PRM_STATE ("nfc_hal_prm_post_baud_update");
863
864    if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
865    {
866        /* Proceed with next step of patch download sequence */
867        nfc_hal_prm_nfcc_ready_to_continue ();
868    }
869}
870
871/*******************************************************************************
872**
873** Function         nfc_hal_prm_process_timeout
874**
875** Description      Process timer expireation for patch download
876**
877** Returns          void
878**
879*******************************************************************************/
880void nfc_hal_prm_process_timeout (void *p_tle)
881{
882    NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout");
883
884    if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_IDLE)
885    {
886        nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_VERSION;
887
888        /* Get currently downloaded patch version */
889        nfc_hal_dm_send_nci_cmd (nfc_hal_prm_get_patch_version_cmd, NCI_MSG_HDR_SIZE, nfc_hal_prm_nci_command_complete_cback);
890    }
891    else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
892    {
893        if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF)
894        {
895            /* Timeout waiting for RESET NTF after signature sent */
896            NCI_TRACE_ERROR0 ("Timeout waiting for RESET NTF after patch download");
897            nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
898        }
899        else
900        {
901            nfc_hal_prm_nfcc_ready_to_continue ();
902        }
903    }
904    else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
905    {
906        NCI_TRACE_DEBUG0 ("Delay after PreI2C patch download...proceeding to download firmware patch");
907        nfc_hal_prm_spd_handle_next_patch_start ();
908    }
909    else
910    {
911        NCI_TRACE_ERROR1 ("Patch download: command timeout (state=%i)", nfc_hal_cb.prm.state);
912
913        nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
914    }
915
916    NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout");
917}
918
919
920/*******************************************************************************
921**
922** Function         HAL_NfcPrmDownloadStart
923**
924** Description      Initiate patch download
925**
926** Input Params
927**                  format_type     patch format type
928**                                  (NFC_HAL_PRM_FORMAT_BIN, NFC_HAL_PRM_FORMAT_HCD, or
929**                                   NFC_HAL_PRM_FORMAT_NCD)
930**
931**                  dest_address    destination adderess (needed for BIN format only)
932**
933**                  p_patchram_buf  pointer to patchram buffer. If NULL,
934**                                  then app must call HAL_NfcPrmDownloadContinue when
935**                                  NFC_HAL_PRM_CONTINUE_EVT is received, to send the next
936**                                  segment of patchram
937**
938**                  patchram_len    size of p_patchram_buf (if non-NULL)
939**
940**                  patchram_delay  The delay after each patch.
941**                                  If the given value is less than the size of the patchram,
942**                                  the size of patchram is used instead.
943**
944**                  p_cback         callback for download status
945**
946**
947** Returns          TRUE if successful, otherwise FALSE
948**
949**
950*******************************************************************************/
951BOOLEAN HAL_NfcPrmDownloadStart (tNFC_HAL_PRM_FORMAT format_type,
952                                 UINT32              dest_address,
953                                 UINT8               *p_patchram_buf,
954                                 UINT32              patchram_len,
955                                 UINT32              patchram_delay,
956                                 tNFC_HAL_PRM_CBACK  *p_cback)
957{
958    NCI_TRACE_API0 ("HAL_NfcPrmDownloadStart ()");
959
960    memset (&nfc_hal_cb.prm, 0, sizeof (tNFC_HAL_PRM_CB));
961
962    if (p_patchram_buf)
963    {
964        nfc_hal_cb.prm.p_cur_patch_data = p_patchram_buf;
965        nfc_hal_cb.prm.cur_patch_offset = 0;
966        nfc_hal_cb.prm.cur_patch_len_remaining = (UINT16) patchram_len;
967        nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF;
968
969        if (patchram_len == 0)
970            return FALSE;
971    }
972
973    nfc_hal_cb.prm.p_cback          = p_cback;
974    nfc_hal_cb.prm.dest_ram         = dest_address;
975    nfc_hal_cb.prm.format           = format_type;
976    nfc_hal_cb.prm.patchram_delay   = patchram_delay;
977
978    nfc_hal_cb.prm.timer.p_cback = nfc_hal_prm_process_timeout;
979
980    if (format_type == NFC_HAL_PRM_FORMAT_NCD)
981    {
982        /* Store patch buffer pointer and length */
983        nfc_hal_cb.prm.p_spd_patch             = p_patchram_buf;
984        nfc_hal_cb.prm.spd_patch_len_remaining = (UINT16)patchram_len;
985        nfc_hal_cb.prm.spd_patch_offset        = 0;
986
987        /* Need delay for controller to finish resetting */
988        nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
989                                        (NFC_HAL_PRM_SPD_PRE_DOWNLOAD_DELAY * QUICK_TIMER_TICKS_PER_SEC) / 1000);
990    }
991    else
992    {
993        NCI_TRACE_ERROR0 ("Unexpected patch format.");
994        return FALSE;
995    }
996
997    return TRUE;
998}
999
1000/*******************************************************************************
1001**
1002** Function         HAL_NfcPrmDownloadContinue
1003**
1004** Description      Send next segment of patchram to controller. Called when
1005**                  NFC_HAL_PRM_CONTINUE_EVT is received.
1006**
1007**                  Only needed if HAL_NfcPrmDownloadStart was called with
1008**                  p_patchram_buf=NULL
1009**
1010** Input Params     p_patch_data    pointer to patch data
1011**                  patch_data_len  patch data len
1012**
1013** Returns          TRUE if successful, otherwise FALSE
1014**
1015*******************************************************************************/
1016BOOLEAN HAL_NfcPrmDownloadContinue (UINT8 *p_patch_data,
1017                                    UINT16 patch_data_len)
1018{
1019    NCI_TRACE_API2 ("HAL_NfcPrmDownloadContinue ():state = %d, patch_data_len=%d",
1020                     nfc_hal_cb.prm.state, patch_data_len);
1021
1022    /* Check if we are in a valid state for this API */
1023    if (  (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_COMPARE_VERSION)
1024        &&(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
1025        &&(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_DOWNLOADING)  )
1026        return FALSE;
1027
1028    if (patch_data_len == 0)
1029        return FALSE;
1030
1031    nfc_hal_cb.prm.cur_patch_offset = 0;
1032    nfc_hal_cb.prm.p_cur_patch_data = p_patch_data;
1033    nfc_hal_cb.prm.cur_patch_len_remaining = patch_data_len;
1034
1035    /* Call appropriate handler */
1036    if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_COMPARE_VERSION)
1037    {
1038        nfc_hal_prm_spd_check_version ();
1039    }
1040    else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
1041    {
1042        nfc_hal_prm_spd_handle_next_patch_start ();
1043    }
1044    else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_DOWNLOADING)
1045    {
1046        nfc_hal_prm_spd_send_next_segment ();
1047    }
1048    else
1049    {
1050        NCI_TRACE_ERROR1 ("Unexpected patch state:%d.", nfc_hal_cb.prm.state);
1051    }
1052
1053    return TRUE;
1054}
1055
1056/*******************************************************************************
1057**
1058** Function         HAL_NfcPrmSetI2cPatch
1059**
1060** Description      Specify patchfile for BCM20791B3 I2C fix. This fix
1061**                  must be downloaded prior to initial patch download for I2C
1062**                  transport
1063**
1064** Input Params     p_i2c_patchfile_buf: pointer to patch for i2c fix
1065**                  i2c_patchfile_len: length of patch
1066**                  prei2c_delay: the delay before downloading main patch
1067**                                if 0 is given, NFC_HAL_PRM_POST_I2C_FIX_DELAY is used instead.
1068**
1069** Returns          Nothing
1070**
1071**
1072*******************************************************************************/
1073void HAL_NfcPrmSetI2cPatch (UINT8 *p_i2c_patchfile_buf, UINT16 i2c_patchfile_len, UINT32 prei2c_delay)
1074{
1075#if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
1076    NCI_TRACE_API0 ("HAL_NfcPrmSetI2cPatch ()");
1077
1078    nfc_hal_cb.prm_i2c.prei2c_delay    = NFC_HAL_PRM_POST_I2C_FIX_DELAY;
1079    if (prei2c_delay)
1080        nfc_hal_cb.prm_i2c.prei2c_delay = prei2c_delay;
1081    nfc_hal_cb.prm_i2c.p_patch = p_i2c_patchfile_buf;
1082    nfc_hal_cb.prm_i2c.len = i2c_patchfile_len;
1083#endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
1084}
1085
1086/*******************************************************************************
1087**
1088** Function         HAL_NfcPrmSetSpdNciCmdPayloadSize
1089**
1090** Description      Set Host-to-NFCC NCI message size for secure patch download
1091**
1092**                  This API must be called before calling HAL_NfcPrmDownloadStart.
1093**                  If the API is not called, then PRM will use the default
1094**                  message size.
1095**
1096**                  Typically, this API is only called for platforms that have
1097**                  message-size limitations in the transport/driver.
1098**
1099**                  Valid message size range: NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE to 255.
1100**
1101** Returns          HAL_NFC_STATUS_OK if successful
1102**                  HAL_NFC_STATUS_FAILED otherwise
1103**
1104**
1105*******************************************************************************/
1106tHAL_NFC_STATUS HAL_NfcPrmSetSpdNciCmdPayloadSize (UINT8 max_payload_size)
1107{
1108    /* Validate: minimum size is NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE */
1109    if (max_payload_size < NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE)
1110    {
1111        NCI_TRACE_ERROR2 ("HAL_NfcPrmSetSpdNciCmdPayloadSize: invalid size (%i). Must be between %i and 255", max_payload_size, NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE);
1112        return (HAL_NFC_STATUS_FAILED);
1113    }
1114    else
1115    {
1116        NCI_TRACE_API1 ("HAL_NfcPrmSetSpdNciCmdPayloadSize: new message size during download: %i", max_payload_size);
1117        nfc_hal_cb.ncit_cb.nci_ctrl_size = max_payload_size;
1118        return (HAL_NFC_STATUS_OK);
1119    }
1120}
1121