1052 lines
34 KiB
C++
1052 lines
34 KiB
C++
/*
|
|
* Copyright 2018-2022 NXP
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
/*************************************************************************************/
|
|
/* INCLUDES */
|
|
/*************************************************************************************/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include "phNxpLog.h"
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <phTmlUwb_spi.h>
|
|
#include "phNxpUciHal_fwd.h"
|
|
#include <phNxpUciHal_utils.h>
|
|
#include "phNxpConfig.h"
|
|
using namespace std;
|
|
#define FILEPATH_MAXLEN 500
|
|
|
|
static uint8_t chip_id = 0x00;
|
|
static uint8_t deviceLcInfo = 0x00;
|
|
static uint8_t is_fw_download_log_enabled = 0x00;
|
|
const char* default_prod_fw = "libsr100t_prod_fw.bin";
|
|
const char* default_dev_fw = "libsr100t_dev_fw.bin";
|
|
|
|
char* configured_fw_name = NULL;
|
|
char default_fw_path[FILEPATH_MAXLEN] = "/vendor/firmware/uwb/";
|
|
/*************************************************************************************/
|
|
/* LOCAL FUNCTIONS */
|
|
/*************************************************************************************/
|
|
static void setOpts(void)
|
|
{
|
|
gOpts.link = Link_Default;
|
|
gOpts.mode = Mode_Default;
|
|
gOpts.capture = Capture_Default;
|
|
gOpts.imgFile = NULL;
|
|
gOpts.fImg = NULL;
|
|
gOpts.mosiFile = (char*)"Mosi.bin";
|
|
gOpts.fMosi = NULL;
|
|
gOpts.misoFile = (char*)"Miso.bin";
|
|
gOpts.fMiso = NULL;
|
|
|
|
gPasswd = FALSE;
|
|
gImg = FALSE;
|
|
}
|
|
|
|
|
|
static int init(void) {
|
|
const uint16_t fw_max_len = 260;
|
|
configured_fw_name = (char*)malloc(fw_max_len * sizeof(char));
|
|
const char *pDefaultFwFileName = NULL;
|
|
int maxSrcLen = (FILEPATH_MAXLEN-strlen(default_fw_path)) - 1;
|
|
if (configured_fw_name == NULL) {
|
|
ALOGD("malloc of configured_fw_name failed ");
|
|
return 1;
|
|
}
|
|
if((deviceLcInfo == PHHBCI_HELIOS_PROD_KEY_1) || (deviceLcInfo == PHHBCI_HELIOS_PROD_KEY_2)) {
|
|
pDefaultFwFileName = default_prod_fw;
|
|
if (!GetNxpConfigStrValue(NAME_NXP_UWB_PROD_FW_FILENAME, configured_fw_name, fw_max_len)) {
|
|
ALOGD("Invalid Prod Fw name keeping the default name: %s", pDefaultFwFileName);
|
|
strncat(default_fw_path, pDefaultFwFileName, maxSrcLen);
|
|
} else{
|
|
ALOGD("configured_fw_name : %s", configured_fw_name);
|
|
strncat(default_fw_path, configured_fw_name, maxSrcLen);
|
|
}
|
|
} else if (deviceLcInfo == PHHBCI_HELIOS_DEV_KEY) {
|
|
pDefaultFwFileName = default_dev_fw;
|
|
if (!GetNxpConfigStrValue(NAME_NXP_UWB_DEV_FW_FILENAME, configured_fw_name, fw_max_len)) {
|
|
ALOGD("Invalid Dev Fw name keeping the default name: %s", pDefaultFwFileName);
|
|
strncat(default_fw_path, pDefaultFwFileName, maxSrcLen);
|
|
} else{
|
|
ALOGD("configured_fw_name : %s", configured_fw_name);
|
|
strncat(default_fw_path, configured_fw_name, maxSrcLen);
|
|
}
|
|
} else {
|
|
ALOGD("Invalid DeviceLCInfo : 0x%x\n", deviceLcInfo);
|
|
return 1;
|
|
}
|
|
|
|
ALOGD("Referring FW path..........: %s", default_fw_path);
|
|
if (gImg && (NULL == (gOpts.fImg = fopen(default_fw_path, "rb")))) {
|
|
ALOGD("ERROR: Cannot open %s file for reading!\n", gOpts.imgFile);
|
|
return 1;
|
|
} else {
|
|
ALOGD("FW FILE OPEN SUCCESS....\n");
|
|
gImg = true;
|
|
// gOpts.capture = Capture_Apdu_With_Dummy_Miso;
|
|
}
|
|
|
|
if (Capture_Off != gOpts.capture) {
|
|
ALOGD("Not Capture_Off.....\n");
|
|
if (NULL == (gOpts.fMosi = fopen(gOpts.mosiFile, "wb"))) {
|
|
ALOGD("ERROR: Cannot open %s file for writing!\n", gOpts.mosiFile);
|
|
return 1;
|
|
}
|
|
|
|
if (NULL == (gOpts.fMiso = fopen(gOpts.misoFile, "wb"))) {
|
|
ALOGD("ERROR: Cannot open %s file for writing!\n", gOpts.misoFile);
|
|
return 1;
|
|
}
|
|
|
|
if (Capture_Apdu_With_Dummy_Miso == gOpts.capture) {
|
|
memset(gDummyMiso, 0xEE, sizeof(gDummyMiso));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cleanup(void)
|
|
{
|
|
ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_SET_FWD, 0);
|
|
if(configured_fw_name !=NULL){
|
|
free(configured_fw_name);
|
|
memset(default_fw_path, '\0', sizeof(char)*256);
|
|
strcpy(default_fw_path, "/vendor/firmware/uwb/");
|
|
}
|
|
if (NULL != gOpts.fImg)
|
|
{
|
|
fclose(gOpts.fImg);
|
|
}
|
|
|
|
if (NULL != gOpts.fMosi)
|
|
{
|
|
fclose(gOpts.fMosi);
|
|
}
|
|
|
|
if (NULL != gOpts.fMiso)
|
|
{
|
|
fclose(gOpts.fMiso);
|
|
}
|
|
}
|
|
phHbci_Status_t phHbci_GetStatus(void)
|
|
{
|
|
ALOGD("phHbci_GetStatus Enter\n");
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
|
|
gphHbci_MosiApdu.len = 0;
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&gphHbci_MisoApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
phHbci_Status_t phHbci_GeneralStatus(phHbci_General_Command_t mode)
|
|
{
|
|
ALOGD("phHbci_GeneralStatus Enter\n");
|
|
switch (gphHbci_MisoApdu.cls)
|
|
{
|
|
case phHbci_Class_General | phHbci_SubClass_Answer:
|
|
switch (gphHbci_MisoApdu.ins)
|
|
{
|
|
case phHbci_General_Ans_HBCI_Ready:
|
|
if (!mode)
|
|
{
|
|
return phHbci_Success;
|
|
}
|
|
|
|
ALOGD("ERROR: Unexpected General Status 0x%02x In Mode 0x%02x\n", gphHbci_MisoApdu.ins, mode);
|
|
break;
|
|
|
|
case phHbci_General_Ans_Mode_Patch_ROM_Ready:
|
|
if (phHbci_General_Cmd_Mode_Patch_ROM == mode)
|
|
{
|
|
return phHbci_Success;
|
|
}
|
|
|
|
ALOGD("ERROR: Unexpected General Status 0x%02x In Mode 0x%02x\n", gphHbci_MisoApdu.ins, mode);
|
|
break;
|
|
|
|
case phHbci_General_Ans_Mode_HIF_Image_Ready:
|
|
if (phHbci_General_Cmd_Mode_HIF_Image == mode)
|
|
{
|
|
return phHbci_Success;
|
|
}
|
|
|
|
ALOGD("ERROR: Unexpected General Status 0x%02x In Mode 0x%02x\n", gphHbci_MisoApdu.ins, mode);
|
|
break;
|
|
|
|
case phHbci_General_Ans_HBCI_Fail:
|
|
case phHbci_General_Ans_Boot_Autoload_Fail:
|
|
case phHbci_General_Ans_Boot_GPIOConf_CRC_Fail:
|
|
case phHbci_General_Ans_Boot_TRIM_CRC_Fail:
|
|
case phHbci_General_Ans_Boot_GPIOTRIM_CRC_Fail:
|
|
ALOGD("ERROR: HBCI Interface Failed With 0x%02x\n", gphHbci_MisoApdu.ins);
|
|
break;
|
|
|
|
case phHbci_General_Ans_Mode_Patch_ROM_Fail:
|
|
ALOGD("ERROR: Patch ROM Mode Failed!\n");
|
|
break;
|
|
|
|
case phHbci_General_Ans_Mode_HIF_Image_Fail:
|
|
ALOGD("ERROR: HIF Image Mode Failed!\n");
|
|
break;
|
|
|
|
default:
|
|
ALOGD("ERROR: Unknown General Status 0x%02x\n", gphHbci_MisoApdu.ins);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case phHbci_Class_General | phHbci_SubClass_Ack:
|
|
switch (gphHbci_MisoApdu.ins)
|
|
{
|
|
case phHbci_Invlaid_Class:
|
|
ALOGD ("ERROR: Invalid Class Error From Slave!\n");
|
|
break;
|
|
|
|
case phHbci_Invalid_Instruction:
|
|
ALOGD ("ERROR: Invalid Instruction Error From Slave!\n");
|
|
break;
|
|
|
|
default:
|
|
ALOGD("ERROR: Unexpected Instruction From Slave 0x%02x\n", gphHbci_MisoApdu.ins);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ALOGD("ERROR: Unknown General Class 0x%02x\n", gphHbci_MisoApdu.cls);
|
|
break;
|
|
}
|
|
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
phHbci_Status_t phHbci_QueryInfo(uint8_t *pInfo, uint32_t *pInfoSz, uint32_t maxSz, bool matchMaxSz)
|
|
{
|
|
ALOGD("phHbci_QueryInfo Enter\n");
|
|
uint8_t expCls, expIns;
|
|
uint16_t lrc, dataSz, payloadSz, segment;
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
|
|
if (maxSz > PHHBCI_MAX_LEN_DATA_MISO)
|
|
{
|
|
ALOGD("ERROR: Info Size Cannot Be Greater Than %u Bytes!\n", PHHBCI_MAX_LEN_DATA_MISO);
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
expCls = (gphHbci_MosiApdu.cls & (uint8_t)PHHBCI_CLASS_MASK) | phHbci_SubClass_Answer;
|
|
expIns = gphHbci_MosiApdu.ins;
|
|
|
|
gphHbci_MosiApdu.len = 0;
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&gphHbci_MisoApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
payloadSz = gphHbci_MisoApdu.len;
|
|
segment = payloadSz & PHHBCI_APDU_SEG_FLAG;
|
|
|
|
if (!segment)
|
|
{
|
|
lrc = payloadSz ? PHHBCI_LEN_LRC : 0;
|
|
dataSz = payloadSz - lrc;
|
|
|
|
if (!dataSz)
|
|
{
|
|
ALOGD("ERROR: No Info From Slave!\n");
|
|
return phHbci_Failure;
|
|
}
|
|
}
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Ack);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_Valid_APDU;
|
|
|
|
if (gphHbci_MisoApdu.cls != expCls)
|
|
{
|
|
ALOGD("ERROR: Invalid Class - Exp 0x%02x, Got 0x%02x\n", expCls, gphHbci_MisoApdu.cls);
|
|
gphHbci_MosiApdu.ins = phHbci_Invlaid_Class;
|
|
}
|
|
else if (gphHbci_MisoApdu.ins != expIns)
|
|
{
|
|
ALOGD("ERROR: Invalid Instruction - Exp 0x%02x, Got 0x%02x\n", expIns, gphHbci_MisoApdu.ins);
|
|
gphHbci_MosiApdu.ins = phHbci_Invalid_Instruction;
|
|
}
|
|
else if (segment)
|
|
{
|
|
ALOGD("ERROR: Invalid Payload Length!\n");
|
|
gphHbci_MosiApdu.ins = phHbci_Invalid_Segment_Length;
|
|
}
|
|
else if (dataSz > maxSz)
|
|
{
|
|
ALOGD("ERROR: Total Size (%u) Greater Than Max. Size (%u)!\n", dataSz, maxSz);
|
|
gphHbci_MosiApdu.ins = phHbci_Invalid_Segment_Length;
|
|
}
|
|
else if (matchMaxSz && (dataSz != maxSz))
|
|
{
|
|
ALOGD("ERROR: Total Size (%u) Not Equal To Expected Size (%u)!\n", dataSz, maxSz);
|
|
gphHbci_MosiApdu.ins = phHbci_Invalid_Segment_Length;
|
|
}
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (gphHbci_MosiApdu.ins & PHHBCI_ERROR_STATUS_MASK)
|
|
{
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)gphHbci_MisoApdu.payload, payloadSz)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (gphHbci_MisoApdu.payload[dataSz] != phHbci_CalcLrc((uint8_t *)&gphHbci_MisoApdu, PHHBCI_LEN_HDR + dataSz))
|
|
{
|
|
ALOGD("ERROR: Invalid LRC!\n");
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
memcpy(&pInfo[*pInfoSz], gphHbci_MisoApdu.payload, dataSz);
|
|
*pInfoSz += dataSz;
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
phHbci_Status_t phHbci_GetGeneralInfo(uint8_t *pInfo, uint32_t *pInfoSz)
|
|
{
|
|
ALOGD("phHbci_GetGeneralInfo\n");
|
|
if (gphHbci_MosiApdu.cls != (uint8_t)(phHbci_Class_General | phHbci_SubClass_Query))
|
|
{
|
|
ALOGD("ERROR: Invalid General Info Class = 0x%02x\n", gphHbci_MosiApdu.cls);
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
switch (gphHbci_MosiApdu.ins)
|
|
{
|
|
case phHbci_General_Qry_Chip_ID:
|
|
return phHbci_QueryInfo(pInfo, pInfoSz, PHHBCI_HELIOS_CHIP_ID_SZ, TRUE);
|
|
|
|
case phHbci_General_Qry_Helios_ID:
|
|
return phHbci_QueryInfo(pInfo, pInfoSz, PHHBCI_HELIOS_ID_SZ, TRUE);
|
|
|
|
//case phHbci_General_Qry_CA_Root_Pub_Key:
|
|
// return phHbci_QueryInfo(pInfo, pInfoSz, PHHBCI_HELIOS_CA_ROOT_PUB_KEY_SZ, TRUE);
|
|
|
|
case phHbci_General_Qry_NXP_Pub_Key:
|
|
return phHbci_QueryInfo(pInfo, pInfoSz, PHHBCI_HELIOS_NXP_PUB_KEY_SZ, TRUE);
|
|
|
|
case phHbci_General_Qry_ROM_Version:
|
|
return phHbci_QueryInfo(pInfo, pInfoSz, PHHBCI_HELIOS_ROM_VERSION_SZ, TRUE);
|
|
|
|
case phHbci_General_Qry_OTP_AutoLoad_Info:
|
|
return phHbci_QueryInfo(pInfo, pInfoSz, PHHBCI_HELIOS_OTP_AUTOLOAD_INFO_SZ, TRUE);
|
|
default:
|
|
ALOGD("ERROR: Undefined General Query = 0x%02x\n", gphHbci_MosiApdu.ins);
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
phHbci_Status_t phHbci_GetInfo(uint8_t *pInfo, uint32_t *pInfoSz)
|
|
{
|
|
ALOGD("phHbci_GetInfo Enter\n");
|
|
switch (gphHbci_MosiApdu.cls)
|
|
{
|
|
case phHbci_Class_General | phHbci_SubClass_Query:
|
|
return phHbci_GetGeneralInfo(pInfo, pInfoSz);
|
|
break;
|
|
|
|
default:
|
|
ALOGD("ERROR: No Info Defined For Class = 0x%02x\n", gphHbci_MosiApdu.cls);
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
phHbci_Status_t phHbci_PutCommand(uint8_t *pImg, uint32_t imgSz)
|
|
{
|
|
ALOGD("phHbci_PutCommand Enter\n");
|
|
uint8_t ackCls, ackIns;
|
|
uint16_t lrc, dataSz, payloadSz;
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
|
|
ackCls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Ack);
|
|
ackIns = (uint8_t)phHbci_Valid_APDU;
|
|
|
|
do
|
|
{
|
|
//ALOGD("fwd while loop...imgSz: %d\n",imgSz);
|
|
if (imgSz > PHHBCI_MAX_LEN_DATA_MOSI)
|
|
{
|
|
dataSz = PHHBCI_MAX_LEN_DATA_MOSI;
|
|
payloadSz = PHHBCI_APDU_SEG_FLAG;
|
|
}
|
|
else
|
|
{
|
|
lrc = imgSz ? PHHBCI_LEN_LRC : 0;
|
|
dataSz = imgSz;
|
|
payloadSz = dataSz + lrc;
|
|
}
|
|
//ALOGD("dataSz : %d\n",dataSz);
|
|
gphHbci_MosiApdu.len = payloadSz;
|
|
usleep(1);
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
usleep(1);
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&gphHbci_MisoApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if ((gphHbci_MisoApdu.cls != ackCls) || (gphHbci_MisoApdu.ins != ackIns))
|
|
{
|
|
ALOGD("ERROR: NACK (CLS = 0x%02x, INS = 0x%02x)\n", gphHbci_MisoApdu.cls, gphHbci_MisoApdu.ins);
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
if (dataSz)
|
|
{
|
|
//ALOGD("dataSz is not zero......");
|
|
memcpy(gphHbci_MosiApdu.payload, pImg, dataSz);
|
|
gphHbci_MosiApdu.payload[dataSz] = phHbci_CalcLrc((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR + dataSz);
|
|
|
|
pImg += dataSz;
|
|
imgSz -= dataSz;
|
|
payloadSz = dataSz + PHHBCI_LEN_LRC;
|
|
if(chip_id == PHHBCI_FW_B2_VERSION)
|
|
{
|
|
usleep(250);
|
|
}
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)gphHbci_MosiApdu.payload, payloadSz)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&gphHbci_MisoApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if ((gphHbci_MisoApdu.cls != ackCls) || (gphHbci_MisoApdu.ins != ackIns))
|
|
{
|
|
ALOGD("ERROR: NACK (CLS = 0x%02x, INS = 0x%02x)\n", gphHbci_MisoApdu.cls, gphHbci_MisoApdu.ins);
|
|
return phHbci_Failure;
|
|
}
|
|
}
|
|
}
|
|
while (imgSz);
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
static phHbci_Status_t phHbci_MasterPatchROM(uint8_t *pImg, uint32_t imgSz)
|
|
{
|
|
ALOGD("phHbci_MasterPatchROM enter");
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Query);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_General_Qry_Status;
|
|
|
|
while (1)
|
|
{
|
|
if (phHbci_Success != (ret = phHbci_GetStatus()))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
switch (gphHbci_MisoApdu.cls)
|
|
{
|
|
case phHbci_Class_General | phHbci_SubClass_Answer:
|
|
case phHbci_Class_General | phHbci_SubClass_Ack:
|
|
if (phHbci_Success != (ret = phHbci_GeneralStatus(phHbci_General_Cmd_Mode_Patch_ROM)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_Patch_ROM | phHbci_SubClass_Command);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_Patch_ROM_Cmd_Download_Patch;
|
|
|
|
/* Reset GPIO event flag */
|
|
//cppResetGPIOEvent();
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutCommand(pImg, imgSz)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
/* Wait for GPIO event */
|
|
/*if (0 > cppWaitForGPIOEvent(PHHBCI_GPIO_TIMEOUT_MS))
|
|
{
|
|
ALOGD("ERROR: GPIO notification timeout!\n");
|
|
}*/
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_Patch_ROM | phHbci_SubClass_Query);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_Patch_ROM_Qry_Patch_Status;
|
|
break;
|
|
|
|
case phHbci_Class_Patch_ROM | phHbci_SubClass_Answer:
|
|
switch (gphHbci_MisoApdu.ins)
|
|
{
|
|
case phHbci_Patch_ROM_Ans_Patch_Success:
|
|
ALOGD("Patch ROM Transfer Complete.\n");
|
|
ret = phHbci_Success;
|
|
break;
|
|
|
|
case phHbci_Patch_ROM_Ans_File_Too_Large:
|
|
case phHbci_Patch_ROM_Ans_Invalid_Patch_File_Marker:
|
|
case phHbci_Patch_ROM_Ans_Too_Many_Patch_Table_Entries:
|
|
case phHbci_Patch_ROM_Ans_Invalid_Patch_Code_Size:
|
|
case phHbci_Patch_ROM_Ans_Invalid_Global_Patch_Marker:
|
|
case phHbci_Patch_ROM_Ans_Invalid_Signature_Size:
|
|
case phHbci_Patch_ROM_Ans_Invalid_Signature:
|
|
ALOGD("EROOR: Patch ROM Transfer Failed With 0x%02x!\n", gphHbci_MisoApdu.ins);
|
|
ret = phHbci_Failure;
|
|
break;
|
|
|
|
default:
|
|
ALOGD("ERROR: Unknown Patch ROM Status 0x%02x\n", gphHbci_MisoApdu.ins);
|
|
ret = phHbci_Failure;
|
|
break;
|
|
}
|
|
return ret;
|
|
|
|
default:
|
|
ALOGD("ERROR: Unknown Class 0x%02x\n", gphHbci_MisoApdu.cls);
|
|
return phHbci_Failure;
|
|
}
|
|
}
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
static phHbci_Status_t phHbci_MasterHIFImage(uint8_t *pImg, uint32_t imgSz)
|
|
{
|
|
ALOGD("phHbci_MasterHIFImage enter");
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Query);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_General_Qry_Status;
|
|
|
|
while (1)
|
|
{
|
|
if (phHbci_Success != (ret = phHbci_GetStatus()))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
switch (gphHbci_MisoApdu.cls)
|
|
{
|
|
case phHbci_Class_General | phHbci_SubClass_Answer:
|
|
case phHbci_Class_General | phHbci_SubClass_Ack:
|
|
if (phHbci_Success != (ret = phHbci_GeneralStatus(phHbci_General_Cmd_Mode_HIF_Image)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_HIF_Image | phHbci_SubClass_Command);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_HIF_Image_Cmd_Download_Image;
|
|
|
|
/* Reset GPIO event flag */
|
|
// cppResetGPIOEvent();
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutCommand(pImg, imgSz)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
/* Wait for GPIO event */
|
|
/* if (0 > cppWaitForGPIOEvent(PHHBCI_GPIO_TIMEOUT_MS))
|
|
{
|
|
ALOGD("ERROR: GPIO notification timeout!\n");
|
|
}*/
|
|
usleep(100000);
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_HIF_Image | phHbci_SubClass_Query);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_HIF_Image_Qry_Image_Status;
|
|
break;
|
|
|
|
case phHbci_Class_HIF_Image | phHbci_SubClass_Answer:
|
|
switch (gphHbci_MisoApdu.ins)
|
|
{
|
|
case phHbci_HIF_Image_Ans_Image_Success:
|
|
ALOGD("HIF Image Transfer Complete.\n");
|
|
/*Check FW download throughput measurement*/
|
|
//ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_GET_THROUGHPUT, 0);
|
|
return phHbci_Success;
|
|
|
|
case phHbci_HIF_Image_Ans_Header_Too_Large:
|
|
case phHbci_HIF_Image_Ans_Header_Parse_Error:
|
|
case phHbci_HIF_Image_Ans_Invalid_Cipher_Type_Crypto:
|
|
case phHbci_HIF_Image_Ans_Invalid_Cipher_Type_Hash:
|
|
case phHbci_HIF_Image_Ans_Invalid_Cipher_Type_Curve:
|
|
case phHbci_HIF_Image_Ans_Invalid_ECC_Key_Length:
|
|
case phHbci_HIF_Image_Ans_Invalid_Payload_Description:
|
|
case phHbci_HIF_Image_Ans_Invalid_Firmware_Version:
|
|
case phHbci_HIF_Image_Ans_Invalid_ECID_Mask:
|
|
case phHbci_HIF_Image_Ans_Invalid_ECID_Value:
|
|
case phHbci_HIF_Image_Ans_Invalid_Encrypted_Payload_Hash:
|
|
case phHbci_HIF_Image_Ans_Invalid_Header_Signature:
|
|
case phHbci_HIF_Image_Ans_Install_Settings_Too_Large:
|
|
case phHbci_HIF_Image_Ans_Install_Settings_Parse_Error:
|
|
case phHbci_HIF_Image_Ans_Payload_Too_Large:
|
|
case phHbci_HIF_Image_Ans_Quickboot_Settings_Parse_Error:
|
|
case phHbci_HIF_Image_Ans_Invalid_Static_Hash:
|
|
case phHbci_HIF_Image_Ans_Invalid_Dynamic_Hash:
|
|
case phHbci_HIF_Image_Ans_Execution_Settings_Parse_Error:
|
|
case phHbci_HIF_Image_Ans_Key_Read_Error:
|
|
ALOGD("EROOR: HIF Image Transfer Failed With 0x%02x!\n", gphHbci_MisoApdu.ins);
|
|
return phHbci_Failure;
|
|
|
|
default:
|
|
ALOGD("ERROR: Unknown HIF Status 0x%02x\n", gphHbci_MisoApdu.ins);
|
|
return phHbci_Failure;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ALOGD("ERROR: Unknown Class 0x%02x\n", gphHbci_MisoApdu.cls);
|
|
return phHbci_Failure;
|
|
}
|
|
}
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
/*********************************************************************************************************************/
|
|
/* GLOBAL FUNCTIONS */
|
|
/*********************************************************************************************************************/
|
|
phHbci_Status_t phHbci_Master(phHbci_General_Command_t mode, uint8_t *pImg, uint32_t imgSz)
|
|
{
|
|
ALOGD("phHbci_Master Enter\n");
|
|
// uint8_t info[PHHBCI_MAX_LEN_DATA_MISO];
|
|
// uint32_t infoSz = 0;
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Query);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_General_Qry_Status;
|
|
|
|
if (phHbci_Success != (ret = phHbci_GetStatus()))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (phHbci_Success != (ret = phHbci_GeneralStatus((phHbci_General_Command_t)0)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Command);
|
|
gphHbci_MosiApdu.ins = (uint8_t)mode;
|
|
ALOGD("STARTING FW DOWNLOAD.....\n");
|
|
if (phHbci_Success != (ret = phHbci_PutCommand(pImg, 0)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case phHbci_General_Cmd_Mode_Patch_ROM:
|
|
return phHbci_MasterPatchROM(pImg, imgSz);
|
|
|
|
case phHbci_General_Cmd_Mode_HIF_Image:
|
|
return phHbci_MasterHIFImage(pImg, imgSz);
|
|
|
|
default:
|
|
ALOGD("ERROR: Undefined mode 0x%02x\n", mode);
|
|
break;
|
|
}
|
|
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
/*********************************************************************************************************************/
|
|
/* GLOBAL FUNCTIONS */
|
|
/*********************************************************************************************************************/
|
|
uint8_t phHbci_CalcLrc(uint8_t *pBuf, uint16_t bufSz)
|
|
{
|
|
//ALOGD("phHbci_CalcLrc....\n");
|
|
uint8_t lrc = 0;
|
|
uint16_t i;
|
|
|
|
if (!pBuf || !bufSz)
|
|
return lrc;
|
|
|
|
/* ISO 1155:1978 Information processing -- Use of longitudinal parity to detect errors in information messages */
|
|
for (i = 0; i < bufSz; i++)
|
|
{
|
|
lrc += *pBuf++;
|
|
}
|
|
|
|
lrc ^= 0xFF;
|
|
lrc += 1;
|
|
|
|
return lrc;
|
|
}
|
|
/*********************************************************************************************************************/
|
|
/* GLOBAL FUNCTIONS */
|
|
/*********************************************************************************************************************/
|
|
phHbci_Status_t phHbci_GetApdu(uint8_t *pApdu, uint16_t sz)
|
|
{
|
|
// ALOGD("phHbci_GetApdu Enter\n");
|
|
uint16_t ret;
|
|
int ret_Read;
|
|
if (sz == 0 || sz > PHHBCI_MAX_LEN_PAYLOAD_MISO) {
|
|
ALOGD("ERROR: phHbci_GetApdu data len is 0 or greater than max palyload length supported\n");
|
|
return phHbci_Failure;
|
|
}
|
|
ret_Read = read((intptr_t)tPalConfig.pDevHandle, (void*)pApdu, (sz));
|
|
if (ret_Read < 0)
|
|
{
|
|
ALOGD("ERROR: Get APDU %u bytes failed!\n", sz);
|
|
return phHbci_Failure;
|
|
}
|
|
|
|
if(is_fw_download_log_enabled == 0x01)
|
|
phNxpUciHal_print_packet("RECV",pApdu,ret_Read);
|
|
|
|
switch (gOpts.capture)
|
|
{
|
|
case Capture_Apdu_With_Dummy_Miso:
|
|
if (sz != (ret = fwrite(gDummyMiso, sizeof(uint8_t), sz, gOpts.fMosi)))
|
|
{
|
|
ALOGD("ERROR: %s dummy write returned %d, expected %d\n", gOpts.mosiFile, ret, sz);
|
|
}
|
|
if (sz != (ret = fwrite(pApdu, sizeof(uint8_t), sz, gOpts.fMiso)))
|
|
{
|
|
ALOGD("ERROR: %s write returned %d, expected %d\n", gOpts.misoFile, ret, sz);
|
|
}
|
|
break;
|
|
case Capture_Apdu:
|
|
if (sz != (ret = fwrite(pApdu, sizeof(uint8_t), sz, gOpts.fMiso)))
|
|
{
|
|
ALOGD("ERROR: %s write returned %d, expected %d\n", gOpts.misoFile, ret, sz);
|
|
}
|
|
break;
|
|
|
|
case Capture_Off:
|
|
default:
|
|
break;
|
|
}
|
|
//ALOGD("Rx --> 0X%x 0X%x 0X%x 0X%x.\n", pApdu[0], pApdu[1], pApdu[2],pApdu[3]);
|
|
return phHbci_Success;
|
|
}
|
|
|
|
phHbci_Status_t phHbci_PutApdu(uint8_t *pApdu, uint16_t sz)
|
|
{
|
|
// ALOGD("phHbci_PutApdu Enter\n");
|
|
int ret;
|
|
int numWrote = 0;
|
|
if(is_fw_download_log_enabled == 0x01)
|
|
phNxpUciHal_print_packet("SEND",pApdu,sz);
|
|
|
|
ret = write((intptr_t)tPalConfig.pDevHandle, pApdu,sz);
|
|
if (ret > 0) {
|
|
numWrote += ret;
|
|
} else if (ret == 0) {
|
|
ALOGD("_spi_write() EOF");
|
|
return (phHbci_Status_t)1;
|
|
} else {
|
|
ALOGD("_spi_write() errno : %x", ret);
|
|
return (phHbci_Status_t)1;
|
|
}
|
|
switch (gOpts.capture)
|
|
{
|
|
case Capture_Apdu_With_Dummy_Miso:
|
|
case Capture_Apdu:
|
|
ALOGD("Write dummy apdu......\n");
|
|
ret = write((intptr_t)tPalConfig.pDevHandle, pApdu,sz);
|
|
if (ret > 0) {
|
|
numWrote += ret;
|
|
} else if (ret == 0) {
|
|
ALOGD("_spi_write() EOF");
|
|
return (phHbci_Status_t)1;
|
|
} else {
|
|
ALOGD("_spi_write() errno : %x", ret);
|
|
return (phHbci_Status_t)1;
|
|
}
|
|
/*if (sz != (ret = fwrite(pApdu, sizeof(uint8_t), sz, gOpts.fMosi)))
|
|
{
|
|
ALOGD("ERROR: %s write returned %d, expected %d\n", gOpts.mosiFile, ret, sz);
|
|
}*/
|
|
break;
|
|
|
|
case Capture_Off:
|
|
default:
|
|
break;
|
|
}
|
|
//ALOGD("Tx-->0X%x 0X%x 0X%x 0X%x......\n", pApdu[0], pApdu[1], pApdu[2],pApdu[3]);
|
|
return phHbci_Success;
|
|
}
|
|
|
|
phHbci_Status_t phHbci_GetChipIdInfo(){
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
uint8_t FwdExtndLenIndication = 0, totalBtyesToReadMsb = 0;
|
|
uint16_t totalBtyesToRead = 0;
|
|
uint8_t hbciData[PHHBCI_MAX_LEN_PAYLOAD_MISO];
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Query);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_General_Qry_Chip_ID;
|
|
|
|
gphHbci_MosiApdu.len = 0;
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
usleep(1);
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&hbciData[0], PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
FwdExtndLenIndication = ((hbciData[PHHBCI_MODE_LEN_MSB_OFFSET] & 0xF0) >> 4);
|
|
totalBtyesToReadMsb = (hbciData[PHHBCI_MODE_LEN_MSB_OFFSET] & 0x0F);
|
|
totalBtyesToRead = (hbciData[PHHBCI_MODE_LEN_LSB_OFFSET] | (totalBtyesToReadMsb << 8));
|
|
|
|
if (totalBtyesToRead == 0) {
|
|
ALOGD("ERROR: hbci data len is 0\n");
|
|
return phHbci_Failure;
|
|
}
|
|
gphHbci_MosiApdu.cls = (uint8_t)phHbci_SubClass_Ack;
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_SubClass_Query;
|
|
gphHbci_MosiApdu.len = 0;
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
usleep(1);
|
|
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&hbciData[0], totalBtyesToRead)))
|
|
{
|
|
return ret;
|
|
}
|
|
chip_id = hbciData[PHHBCI_MODE_CHIP_ID_OFFSET];
|
|
ALOGD("Recived ChipId = 0x%02x\n", chip_id);
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function phHbci_GetDeviceLcInfo
|
|
*
|
|
* Description This function is called to get the OTP Autoload Info
|
|
* Returns return 0 on success and -1
|
|
*
|
|
******************************************************************************/
|
|
phHbci_Status_t phHbci_GetDeviceLcInfo(){
|
|
phHbci_Status_t ret = phHbci_Failure;
|
|
uint8_t FwdExtndLenIndication = 0,totalBtyesToReadMsb = 0;
|
|
uint16_t totalBtyesToRead = 0;
|
|
uint8_t hbciData[PHHBCI_MAX_LEN_PAYLOAD_MISO];
|
|
|
|
gphHbci_MosiApdu.cls = (uint8_t)(phHbci_Class_General | phHbci_SubClass_Query);
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_General_Qry_OTP_AutoLoad_Info;
|
|
|
|
gphHbci_MosiApdu.len = 0;
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
usleep(1);
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&hbciData[0], PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
FwdExtndLenIndication = ((hbciData[PHHBCI_MODE_LEN_MSB_OFFSET] & 0xF0) >> 4);
|
|
totalBtyesToReadMsb = (hbciData[PHHBCI_MODE_LEN_MSB_OFFSET] & 0x0F);
|
|
totalBtyesToRead = (uint16_t)(hbciData[PHHBCI_MODE_LEN_LSB_OFFSET] | (totalBtyesToReadMsb << 8));
|
|
|
|
if (totalBtyesToRead == 0) {
|
|
ALOGD("ERROR: hbci data len is 0\n");
|
|
return phHbci_Failure;
|
|
}
|
|
gphHbci_MosiApdu.cls = (uint8_t)phHbci_SubClass_Ack;
|
|
gphHbci_MosiApdu.ins = (uint8_t)phHbci_SubClass_Query;
|
|
gphHbci_MosiApdu.len = 0;
|
|
|
|
if (phHbci_Success != (ret = phHbci_PutApdu((uint8_t *)&gphHbci_MosiApdu, PHHBCI_LEN_HDR)))
|
|
{
|
|
return ret;
|
|
}
|
|
usleep(1);
|
|
if (phHbci_Success != (ret = phHbci_GetApdu((uint8_t *)&hbciData[0], totalBtyesToRead)))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
deviceLcInfo = hbciData[PHHBCI_MODE_DEV_LIFE_CYCLE_INFO_OFFSET];
|
|
ALOGD("Recived devLifeCycleId = 0x%02x\n", deviceLcInfo);
|
|
|
|
return phHbci_Success;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function phNxpUciHal_fw_download
|
|
*
|
|
* Description This function is called by jni when wired mode is
|
|
* performed.First SR100 driver will give the access
|
|
* permission whether wired mode is allowed or not
|
|
* arg (0):
|
|
* Returns return 0 on success and -1 on fail, On success
|
|
* update the acutual state of operation in arg pointer
|
|
*
|
|
******************************************************************************/
|
|
int phNxpUciHal_fw_download() {
|
|
uint8_t *pImg = gphHbci_ImgHelios;
|
|
uint32_t imgSz=0, maxSz, err = 0;
|
|
unsigned long num = 0;
|
|
phHbci_General_Command_t cmd;
|
|
ALOGE("phNxpUciHal_fw_download enter and FW download started.....\n");
|
|
setOpts();
|
|
|
|
|
|
ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_SET_FWD, 1);
|
|
/* Always display chip id information */
|
|
is_fw_download_log_enabled = true;
|
|
if (phHbci_Success != phHbci_GetDeviceLcInfo())
|
|
{
|
|
ALOGD("phHbci_GetDeviceLcInfo Failure!\n");
|
|
return 1;
|
|
}
|
|
|
|
if (phHbci_Success != phHbci_GetChipIdInfo())
|
|
{
|
|
ALOGD("phHbci_GetChipIdInfo Failure!\n");
|
|
return 1;
|
|
}
|
|
is_fw_download_log_enabled = false;
|
|
|
|
if(GetNxpConfigNumValue(NAME_UWB_FW_DOWNLOAD_LOG, &num, sizeof(num))){
|
|
is_fw_download_log_enabled = (uint8_t)num;
|
|
ALOGD("NAME_UWB_FW_DOWNLOAD_LOG: 0x%02x\n",is_fw_download_log_enabled);
|
|
} else {
|
|
ALOGD("NAME_UWB_FW_DOWNLOAD_LOG: failed 0x%02x\n",is_fw_download_log_enabled);
|
|
}
|
|
if (init())
|
|
{
|
|
ALOGD("INIT Failed.....\n");
|
|
cleanup();
|
|
return 1;
|
|
}
|
|
|
|
switch (gOpts.mode)
|
|
{
|
|
case Mode_Patch_ROM:
|
|
cmd = phHbci_General_Cmd_Mode_Patch_ROM;
|
|
maxSz = PHHBCI_PATCHROM_MAX_IMAGE_SZ;
|
|
break;
|
|
|
|
case Mode_HIF_Image:
|
|
cmd = phHbci_General_Cmd_Mode_HIF_Image;
|
|
maxSz = PHHIF_MAX_IMAGE_SZ;
|
|
break;
|
|
|
|
default:
|
|
ALOGD("ERROR: Undefined Master Mode = %u\n", gOpts.mode);
|
|
return 1;
|
|
}
|
|
if (gImg)
|
|
{
|
|
if(gOpts.fImg == NULL) {
|
|
gOpts.fImg = fopen(default_fw_path, "rb");
|
|
}
|
|
if(gOpts.fImg == NULL) {
|
|
ALOGD("Firmware file does not exist:");
|
|
return phHbci_File_Not_found;
|
|
}
|
|
fseek(gOpts.fImg, 0, SEEK_END);
|
|
imgSz = (uint32_t)ftell(gOpts.fImg);
|
|
ALOGD("FWD file size ftell returns: %d\n",imgSz);
|
|
if (!imgSz || (maxSz < imgSz))
|
|
{
|
|
ALOGD("ERROR: %s image size (%d) not supported!\n", gOpts.imgFile, imgSz);
|
|
cleanup();
|
|
return 1;
|
|
}
|
|
|
|
rewind(gOpts.fImg);
|
|
}
|
|
ALOGD("FWD file size: %d\n",imgSz);
|
|
if (!gImg || (imgSz == fread(pImg, sizeof(uint8_t), imgSz, gOpts.fImg)))
|
|
{
|
|
if(cmd == phHbci_General_Cmd_Mode_HIF_Image) {
|
|
ALOGD("HIF Image mode.\n");
|
|
}
|
|
err = phHbci_Master(cmd, pImg, imgSz);
|
|
if (phHbci_Success != err)
|
|
{
|
|
ALOGD("Failure!\n");
|
|
err = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ALOGD("ERROR: Image read failed!\n");
|
|
err = 1;
|
|
}
|
|
|
|
cleanup();
|
|
return err;
|
|
|
|
}
|
|
|
|
void setDeviceHandle(void* pDevHandle)
|
|
{
|
|
ALOGD("Set the device handle!\n");
|
|
|
|
if(pDevHandle == NULL) {
|
|
ALOGD("device handle is NULL!\n");
|
|
} else {
|
|
tPalConfig.pDevHandle = (void*) ((intptr_t)pDevHandle);
|
|
}
|
|
|
|
}
|