/******************************************************************** DMW_RfDownload.c EPG Middleware utility API implementation Copyright 2004 Digital STREAM Technology, Inc. All Rights Reserved import from rf_FlashUpdate.c $Id: DMW_RfDownload.c v1.00 2004/04 cafrii Exp $ ********************************************************************/ /*_____ I N C L U D E __________________________________________*/ #include "DMW_Platform.h" //#include "DHL_PsiFilter.h" #include "DMW_Channel.h" #include "DMW_RfDownload.h" //#include #define USER_HEADER_SIZE 16 #define GETUpperByte(y) (((y)>>8)&0xff) #define GETLowerByte(y) ((y)&0xff) /* cafrii 070214, boot code size is now 64KB */ /* #define BOOTCODE_SIZE (64*1024) #define STAGE2_SIZE 8192 */ /* MonitorPrvt()¿Í ±×ÀÇ procedure°£ÀÇ argument·Î »ç¿ë */ typedef struct PrvtEventProcData { int index; DHL_RESULT err; /*ouput*/ DHL_OS_SEMA_ID waitsem; /*input*/ UINT8 receiveOk; UINT8 receiveCheckOk; tDHL_PSI_ControlHandle hPsiCtl; tDHL_PSI_DataArray *desc; } PrvtEventProcData; DHL_RESULT RfDownload_MonitorPrvt(tDHL_TSD tsd, tDHL_PSI_Mode psiMode ,tDHL_PSI_Update updateMode, tDHL_PSI_EventProc eventProc, UINT16 pid, UINT8 tableId, int tableIdExt, UINT32 userParam, tDHL_PSI_ControlHandle *psiCtl); DHL_RESULT RfDownload_ParsePrvt(const tDHL_PSI_DataArray *desc, prvtPtr_t *prvtPtr); #if COMMENT ______________(){} #endif int g_Trace_bRfUpdate = 1; static int RfUpdate_DebugPrint(char *fmt, ...) { DHL_OS_TASK_INFO tInfo; char msgPrefix[50], sTaskName[20]; va_list v; int n; int priority; DHL_OS_GetTaskInfo(DHL_OS_GetTaskID(), &tInfo); if (g_Trace_bRfUpdate == 0) return 0; priority = tInfo.priority; #if SUPPORT_THREADX if (1) { char *s; strncpy(sTaskName, tInfo.name, 10); if (sTaskName[2]==':') { sTaskName[7] = 0; /* ¾ÕÀÇ ¼¼ÀÚ¸® »©°í 4 ÀÚ¸® Ç¥½Ã */ s = sTaskName + 3; } else { sTaskName[4] = 0; /* 4 ÀÚ¸® Ç¥½Ã */ s = sTaskName; } sprintf(msgPrefix, "[RFUPDATE %02x %s] ", priority, s); } #else strncpy(sTaskName, tInfo.name, 6); sTaskName[6] = 0; sprintf(msgPrefix, "[RFUPDATE %d %s] ", priority, sTaskName); #endif va_start(v, fmt); n = DHL_OS_Printf(msgPrefix, fmt, v); va_end(v); return n; } #define dprint RfUpdate_DebugPrint /* ========================================================================= */ /* CRC32 - refer to /drivers/graphics/ZLIB/crc32.c*/ /*static int FLASH_crc_table_empty = 1;*/ static UINT32 crc_table_rf_update[256]; /* memory size¸¦ ÁÙÀ̱âÀ§Çؼ­ dynamic ÀÌ¿ëÇϵµ·Ï ÇÔ. Çѹø¸¸ È£ÃâµÊ */ static void ConstructCRCTable() { unsigned int c; unsigned int n; int k; unsigned int poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* make exclusive-or pattern from polynomial (0xedb88320L) */ poly = 0L; for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) poly |= 1L << (31 - p[n]); for (n = 0; n < 256; n++) { c = (unsigned int)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table_rf_update[n] = c; } /* for (n=0; n<256; n++) dprint("%08x %s", FLASH_crc_table[n], n%5==4 ? "\n" : ""); */ } /* DST ÀÚüÀûÀÎ CRC üũ ·çƾ. */ static UINT32 CalculateCRC32(UINT32 out_crc, const UINT8 *buf, UINT32 len) { #define CRC32DO1(buf) out_crc = \ crc_table_rf_update[((int)out_crc ^ (*buf++)) & 0xff]\ ^ (out_crc >> 8); #define CRC32DO2(buf) CRC32DO1(buf); CRC32DO1(buf); #define CRC32DO4(buf) CRC32DO2(buf); CRC32DO2(buf); #define CRC32DO8(buf) CRC32DO4(buf); CRC32DO4(buf); if (buf == NULL) return 0L; if (crc_table_rf_update[1] == 0) ConstructCRCTable(); out_crc = out_crc ^ 0xffffffffL; while (len >= 8) { CRC32DO8(buf); len -= 8; } if (len) { do { CRC32DO1(buf); } while (--len); } return out_crc ^ 0xffffffffL; } #if COMMENT ______________(){} #endif /* caller°¡ Ưº°È÷ memory allocator¸¦ ÁöÁ¤ÇÏÁö ¾Ê¾ÒÀ» °æ¿ì »ç¿ëµÇ´Â µðÆúÆ® handlerÀÌ´Ù. */ static void *_Default_MemAlloc(UINT32 size) { void *ptr = DHL_OS_Malloc(size); return ptr; } static void _Default_MemFree(void *ptr) { /* ptr´Â free ÇÒ mem blockÀÇ ÁÖ¼ÒÀÌ´Ù. */ if (ptr) DHL_OS_Free((void**)&ptr); } MEM_ALLOC_FN RfDownload_AllocLargeMem = _Default_MemAlloc; MEM_FREE_FN RfDownload_FreeLargeMem = _Default_MemFree; #if COMMENT ______________(){} #endif void PrvtSyncEventProc(tDHL_PSI_Event event, tDHL_PSI_ControlHandle psiCtl, UINT32 userParam) { PrvtEventProcData *procData = (PrvtEventProcData *)userParam; tDHL_PSI_DataArray *desc; DHL_RESULT err; /* dprint("@@ PrvtSyncEventProc[%d]...\n", procData->index); */ switch (event) { case ePSIEVENT_DATARECEIVED: err = DHL_PSI_ReadPSIData(psiCtl, &desc); if (err) { dprint("!! DHL_PSI_ReadPSIData returned %s, %d\n", ErrorString(err), err); procData->desc = NULL; } else { procData->desc = desc; } if (procData->hPsiCtl != psiCtl) dprint("@@ !! psiCtl mismatch?\n"); procData->receiveOk = 1; /* ¿¡·¯°¡ ³µ´Â ¾È³µµç ¼ö½ÅÀº µÈ °ÍÀÌ´Ù. */ procData->err = err; dprint("@@ table[%d] data received\n", procData->index); DHL_OS_GiveSemaphore(procData->waitsem); break; case ePSIEVENT_SCRAMBLEDERROR: dprint("@@ ePSIEVENT_SCRAMBLEDERROR\n"); procData->err = DHL_FAIL_SCRAMBLED; procData->receiveOk = 1; DHL_OS_GiveSemaphore(procData->waitsem); break; default: if (event != ePSIEVENT_LOSTPACKET && event != ePSIEVENT_SYNCERR) dprint("!! unknown event %s, %d\n",DHL_PSIEventString(event), event); break; } } /*============================================================================== DHL_RESULT MonitorPrvt(tDHL_PSI_Update updateMode, tDHL_PSI_EventProc eventProc, UINT32 pid , UINT8 iTableId , UINT32 userParam, tDHL_PSI_ControlHandle *psiCtl) updateMode: Update mode (ePSIUPDATE_ONESHOT,psiVersionChange,psiContinuous). eventProc: Callback function to catch monitor events. userParam: Passed back to the eventProc. psiCtl: PSI Object for PSI layer. Configures the TID & PID filters for Privaet secions with a given TableId. ==============================================================================*/ DHL_RESULT RfDownload_MonitorPrvt(tDHL_TSD tsd, tDHL_PSI_Mode psiMode ,tDHL_PSI_Update updateMode, tDHL_PSI_EventProc eventProc, UINT16 pid, UINT8 tableId, int tableIdExt, UINT32 userParam, tDHL_PSI_ControlHandle *psiCtl) { tDHL_PSI_Filter *pref = NULL; DHL_RESULT err; UINT32 maxSections; /* Set up the Table ID filter */ if (tableIdExt >= 0) { dprint("%s: tidex 0x%04x\n", __FUNCTION__, tableId); err = DHL_PSI_AllocFilterWithTidEx(&pref, tableId, tableIdExt, TRUE); } else { err = DHL_PSI_AllocFilterWithTid(&pref, tableId, TRUE); /* ignore table id extension. */ } if (err) { return(err); } maxSections = (psiMode == ePSIMODE_TABLE) ? 256 : 1; /* Set up PID Filter */ if ((err = DHL_PSI_StartMonitor(tsd, pid, psiMode, updateMode, pref, 4096, maxSections, eventProc, userParam, psiCtl))) { dprint("!! %s: DHL_PSI_StartMonitor() err %d\n", __FUNCTION__, err); /* ÁÖÀÇ: pref´Â OS_Malloc¿¡ ÀÇÇØ¼­ ÇÒ´çµÈ °ÍÀ̹ǷΠOS_Free·Î Ç®¾î¾ß ÇÑ´Ù. */ /* OS_Free((void *)&pref); */ DHL_PSI_FreeFilter(pref); } return(err); } void RfDownload_FreePrvt(prvtPtr_t prvt) { if (prvt == NULL) return; if (prvt->private_data_byte) { (*RfDownload_FreeLargeMem)(prvt->private_data_byte); prvt->private_data_byte = NULL; } DHL_OS_Free((void**)&prvt); } /*============================================================================== DHL_RESULT RfDownload_ParsePrvt (UINT8 **sectionArr, prvtPtr_t *prvtPtr) **sectionArr: Array of pointers to all TVCT sections. *prvtPtr: Returned pointer to the parsed PRVT. Parses an PRVT and returns the parsed table via the return pointer. ==============================================================================*/ DHL_RESULT RfDownload_ParsePrvt(const tDHL_PSI_DataArray *desc, prvtPtr_t *prvtPtr) { UINT16 numSections; UINT32 i; DHL_RESULT err = DHL_OK; UINT32 section_length; UINT16 table_id_extension = 0; UINT8 version_number = 0; // UINT8 current_next_indicator = 0; // UINT8 section_number = 0; // UINT8 last_section_number = 0; UINT32 private_data_length = 0; UINT32 sizeDataBytes; UINT8 *const *sectionArr; prvtPtr_t prvt = NULL; dprint("%s:\n", __FUNCTION__); if (desc == NULL || desc->sectPtr == NULL || prvtPtr == NULL) { dprint("!! invalid argument (desc %x, prvtptr %x)\n", desc, prvtPtr); return (DHL_FAIL_INVALID_PARAM); } sectionArr = desc->sectPtr; *prvtPtr = NULL; numSections = get_last_section_number(sectionArr[0]) + 1; dprint("\t num sections = %d\n" , (int)numSections); /* now verify all other sections are present and calculate total payload data byte size.. */ sizeDataBytes = 0; for (i=0; iprivate_data_byte = (*RfDownload_AllocLargeMem)(sizeDataBytes); checkMemoryError(prvt->private_data_byte); prvt->private_data_length = 0; /* ÀÌ °ªÀº µ¥ÀÌÅ͸¦ ¹ÞÀ¸¸é¼­ Á¡Â÷ÀûÀ¸·Î Áõ°¡ÇÑ´Ù. */ for (i=0; iversion_number = version_number; prvt->table_id_extension = table_id_extension; } else if (prvt->version_number != version_number || prvt->table_id_extension != table_id_extension) { dprint("!! warning: sect[%d]'s (ver %d, tidex %d) != sect[0]'s (v %d, t %d)\n", version_number, table_id_extension, prvt->version_number, prvt->table_id_extension); } /* section_length max = 12bit = 4095. header frame after section length = 5 bytes. (without protocol version) crc = 4 bytes. total maximum payload size = 4095 - 5 - 4 = 4086 --> ÀÌ·ÐÀûÀ¸·Î ÃÖ´ë 4086±îÁö °¡´ÉÇѵ¥, encodingÀ» ÇÒ ¶§ ÃÖ´ë 4084·Î ÇÑ °Í °°´Ù. */ if (private_data_length > 0 && private_data_length <= 4084) { memcpy(prvt->private_data_byte+prvt->private_data_length, &(sectionArr[i][8]), private_data_length); /* update private_data_length field. */ prvt->private_data_length += private_data_length; } else { dprint("!! data length %d invalid range\n", private_data_length); } } /* for( i = 0 ; i < numSections ; i++ ) */ dprint("\tParsePrtv end. byte length %d\n", prvt->private_data_length); /* parsing complete */ /* *(((memId_t *)(*prvtPtr))-1) = memId; */ /* memId = NULL; // so memChain not deleted */ *prvtPtr = prvt; return DHL_OK; ParseExit: if (prvt && prvt->private_data_byte) { (*RfDownload_FreeLargeMem)(prvt->private_data_byte); prvt->private_data_byte = NULL; } if (prvt) DHL_OS_Free((void**)&prvt); return (err); } /*============================================================================== DHL_RESULT GetPrvtEx tDHL_TSD tsd, prvtPtr_t *prvtPtr, int timeOut) *tsd Pointer to a TSD structure from which this stream is coming *tvctPtr: Return pointer to a PRVT. timeOut: Synchronous wait timeout for PRVT. Synchronous function which waits (up to the timeout specified) for the arrival of a PRVT. If the PRVT arrives before the timeout, the table is parsed and returned to the caller. ==============================================================================*/ STATUS RfDownload_GetPrvt(tDHL_TSD tsd, prvtPtr_t *prvtPtr, UINT16 pid, UINT16 tableid, UINT16 iTableNumber, int timeOut, BOOL (*checkfn)(void)) { PrvtEventProcData procData; tDHL_PSI_ControlHandle psiCtl = (tDHL_PSI_ControlHandle)0; int semErr; STATUS err = (STATUS)DHL_OK; UINT32 tickStart; if (prvtPtr == NULL) return statusInvalidArgument; memset(&procData, 0, sizeof(procData)); procData.index = 0; procData.desc = NULL; procData.err = DHL_OK; procData.waitsem = DHL_OS_CreateCountingSemaphore("GetPrvt", OS_SEM_PRIO, 0); if (!procData.waitsem) { err = statusOutOfResource; goto GetSectionExit; } err = (STATUS)RfDownload_MonitorPrvt(tsd, ePSIMODE_TABLE, ePSIUPDATE_ONESHOT, PrvtSyncEventProc, pid, tableid, iTableNumber, (UINT32)&procData, &psiCtl); if (err) { dprint("!! %s: MonitorPrvt err %d\n", __FUNCTION__, err); goto GetSectionExit; } procData.hPsiCtl = psiCtl; tickStart = DHL_OS_GetMsCount(); while (1) { semErr = DHL_OS_TakeSemaphore(procData.waitsem, 1000/10); if (semErr == DHL_OK) break; if (checkfn && checkfn()) { err = statusCancelled; goto GetSectionExit; } if ((int)(DHL_OS_GetMsCount() - tickStart) > timeOut) { err = statusTimeout; dprint("!! %s: timeout err\n", __FUNCTION__); goto GetSectionExit; } } if ((err = (STATUS)procData.err)) { dprint("!! %s: procData.err err %d\n", __FUNCTION__, procData.err); goto GetSectionExit; } err = (STATUS)RfDownload_ParsePrvt(procData.desc, prvtPtr); if (err) { dprint("!! %s: Parse err %d, prvt 0x%x\n", err, *prvtPtr); } GetSectionExit: if (psiCtl) DHL_PSI_StopMonitor(psiCtl); if (procData.desc) DHL_PSI_FreePSIData(procData.desc); if (procData.waitsem) DHL_OS_DeleteSemaphore(procData.waitsem); return (err); } void TestGetPrvt(int idx) { int err; tDHL_TSD tsd = DHL_DMX_GetTsd(); prvtPtr_t prvt; int pid = 0x1FEF; /* 8175 */ int table_id = 0xFD; /* 253 */ printf("Get prvt idx %d, pid 0x%x, tid 0x%x\n", idx, pid, table_id); /* Get iTableNumber 0.. first table. */ err = (DHL_RESULT)RfDownload_GetPrvt(tsd, &prvt, pid, table_id, idx, 1000*10, NULL); if (err) { printf("!! RfDownload_GetPrvt err %d\n", err); return; } printf("Prvt rx ok. ver %d, tidex 0x%x, data len %d, p 0x%x\n", prvt->version_number, prvt->table_id_extension, prvt->private_data_length, prvt->private_data_byte); RfDownload_FreePrvt(prvt); } #if COMMENT ______________(){} #endif /*-------------------------- RfUpdate_VerifyHeader INPUT: pInfo OUTPUT: list ´Ù¿î·Îµå°¡ ¿Ï·áµÈ µ¥ÀÌÅÍ (pInfo)¸¦ verifyÇÑ´Ù. header Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© Á¦´ë·Î ¼ö½Å µÈ °ÍÀÎÁö È®ÀÎÇÏ°í ½ÇÁ¦·Î Á¤È®ÇÑ µ¥ÀÌÅÍ Å©±â·Î Á¶Á¤µµ ÇÑ´Ù. ¹®Á¦°¡ ¾øÀ¸¸é PRVT Å×À̺í Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© data list¸¦ »ý¼ºÇØ ³½´Ù. */ int RfDownload_VerifyHeader(RfDownloadInfo *pInfo, DataChunkList *list) { UINT8 headerChecksum = 0; UINT32 dataChecksum = 0; UINT32 givenDataChecksum = 0; int i = 0; UINT8 *pImagePart =NULL; int iImagePartSize = 0; UINT32 nRealImageSize = 0, tmpSize = 0; BOOL bFirst = TRUE; int tableCount = pInfo->NumPrvts; prvtPtr_t *pPrvts = pInfo->PrvtList; dprint("%s: (%d tables)\n", __FUNCTION__, tableCount); if (!pPrvts || tableCount == 0) { dprint("!! Null PRVT list or 0 count\n"); return -1; } for (i=0; iprivate_data_byte; /* 16 bytes DST header +------+------+------+------+ | AA | 'D' | 'S' | 'T' | +------+------+------+------+ | Type | SZ_0 | SZ_1 | SZ_2 | +------+------+------+------+ | SZ_3 | CHK | | | +------+------+------+------+ | CRC0 | CRC1 | CRC2 | CRC3 | +------+------+------+------+ "\xAADST": marker Type: flash type SZ_X: total image size in byte CHK : Header checksum. sum from 'Type' to 'SZ_3' CRCX: CRC32 of total image bytes */ /* first verification... */ memdump3(pImagePart, 16, "Image Header", 0, 0); if( !( pImagePart[0] == 0xAA && pImagePart[1] == 0x44 && /*D*/ pImagePart[2] == 0x53 && /*S*/ pImagePart[3] == 0x54 ) ) /*T*/ { dprint("!! header marker err\n"); return -1; } /* second verifiction... */ dprint("\t User header checsum check...\n"); for (i = 4 ; i < 9 ; i++) headerChecksum += pImagePart[i]; if (headerChecksum != pImagePart[9]) { dprint("!! header checksum err\n"); return -1; } dprint("\t image flash type %d\n", ((pImagePart[4]>>6)&0x03)); nRealImageSize = ((pImagePart[5] << 24 ) & 0xFF000000) | ((pImagePart[6] << 16 ) & 0x00FF0000) | ((pImagePart[7] << 8 ) & 0x0000FF00) | ( pImagePart[8] & 0x000000FF); dprint("\t image size: %d (0x%x)\n", nRealImageSize, nRealImageSize); dprint("\t data checksum check...\n"); givenDataChecksum = (( pImagePart[12] << 24 ) & 0xff000000 ) | (( pImagePart[13] << 16 ) & 0x00ff0000 ) | (( pImagePart[14] << 8 ) & 0x0000ff00 ) | ( pImagePart[15] & 0x000000ff ); /* ù ¹øÂ° table byte calculation for checksum..... */ iImagePartSize = pPrvts[0]->private_data_length - 16; dataChecksum = CalculateCRC32(0/*seed*/,pPrvts[0]->private_data_byte+16,iImagePartSize); if (bFirst == TRUE && (unsigned int)iImagePartSize > nRealImageSize) { /* PRVT ÇѰ³¹Û¿¡ ¾ø´Â °æ¿ì.. */ pPrvts[0]->private_data_length = nRealImageSize + 16; bFirst = FALSE; } tmpSize = iImagePartSize; /* ¸¶Áö¸· tableÀÇ °æ¿ì dummy data¸¦ Æ÷ÇÔÇϰí Àֱ⠶§¹®¿¡ Çì´õ¿¡¼­ ÃßÃâÇÑ ½ÇÁ¦ µ¥ÀÌÅÍ Å©±â Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© data length¸¦ Á¶ÀýÇØ Áà¾ß ÇÑ´Ù. ÀÌ ºÎºÐÀÇ Äڵ尡 Àß ´«¿¡ µé¾î¿ÀÁö ¾Ê´Â´Ù. ÁÖÀÇÇØ¼­ º¸ÀÚ. */ for (i = 1; i < tableCount; i++) { pImagePart = pPrvts[i]->private_data_byte; iImagePartSize = pPrvts[i]->private_data_length; dataChecksum = CalculateCRC32(dataChecksum, pImagePart,iImagePartSize); if( bFirst == TRUE && tmpSize + iImagePartSize > nRealImageSize ) { pPrvts[i]->private_data_length = nRealImageSize - tmpSize; /* Á¶Á¤! */ bFirst = FALSE; } tmpSize += iImagePartSize; } dprint("\tCRC given: 0x%x, calculated: 0x%x\n", givenDataChecksum, dataChecksum); if (dataChecksum != givenDataChecksum) { dprint("!! CRC mismatch\n"); return -1; } list->NumChunk = pInfo->NumPrvts; list->ChunkSize = DHL_OS_Malloc(list->NumChunk * sizeof(int)); list->ChunkList = DHL_OS_Malloc(list->NumChunk * sizeof(UINT8 *)); list->TotalPayloadSize = nRealImageSize; if (list->ChunkSize == NULL || list->ChunkList == NULL) { dprint("!! out of memory for data list\n"); return -2; } nRealImageSize = 0; for (i=0; iNumChunk; i++) { if (i == 0) { /* ¸Ç ¾ÕÀÇ header ºÎºÐÀº Á¦¿ÜÇÑ´Ù. */ list->ChunkList[0] = pInfo->PrvtList[0]->private_data_byte + USER_HEADER_SIZE; list->ChunkSize[0] = pInfo->PrvtList[0]->private_data_length - USER_HEADER_SIZE; } else { list->ChunkList[i] = pInfo->PrvtList[i]->private_data_byte; list->ChunkSize[i] = pInfo->PrvtList[i]->private_data_length; } nRealImageSize += list->ChunkSize[i]; dprint("\t [%d] ChunkSize: %d\n", i, list->ChunkSize[i]); } dprint("\t%d PRVTs, actual image size %d, calc %d\n", list->NumChunk, list->TotalPayloadSize, nRealImageSize); if (list->TotalPayloadSize != nRealImageSize) dprint("!! warning! image size mismatch\n"); return 0; } void RfDownload_CleanUp(RfDownloadInfo *pInfo, DataChunkList *list) { int i; if (pInfo == NULL) return; dprint("RfUpdate_CleanUp:\n"); dprint(" free all prvts..\n"); for (i=0; iNumPrvts && pInfo->PrvtList; i++) { if (pInfo->PrvtList[i]) { RfDownload_FreePrvt(pInfo->PrvtList[i]); pInfo->PrvtList[i] = NULL; } } DHL_OS_Free((void**)&pInfo->PrvtList); DHL_OS_Free((void**)&list->ChunkList); DHL_OS_Free((void**)&list->ChunkSize); } STATUS RfDownload_Download(RfDownloadInfo *pInfo, UINT32 nRxTimeOutSec, RFDOWNLOAD_CALLBACK callback, BOOL (*checkfn)()) { tDHL_TSD tsd = 0; prvtPtr_t prvt = 0; /* temporary PRVT pointer */ prvtPtr_t *pPrvtsList = NULL; /* PRVT list */ PrvtEventProcData *pProcData = NULL; DHL_OS_SEMA_ID waitsem = 0; /* sema4 for notify table received */ DHL_RESULT err = DHL_OK; int i, result; STATUS status = statusOK; int iCurrentTable = 0, iLastTable = 0; int nReceivedCount = 0; /* number of received tables */ int nPrvtMonitor = 0; /* number of monitor */ int _second = 1000; int tickStart = DHL_OS_GetMsCount(); dprint("%s: rx timeout %d\n", __FUNCTION__, nRxTimeOutSec); waitsem = DHL_OS_CreateCountingSemaphore("GetPrvt", OS_SEM_PRIO, 0); if (waitsem == (DHL_OS_SEMA_ID)NULL) { dprint("!! %s: sema4 create err\n", __FUNCTION__); return statusOutOfMemory; /* outOfCPUMemoryError; */ } tsd = DHL_DMX_GetTsd(); if (!tsd) { dprint("!! TSD NULL\n"); return statusInvalidState; /* illegalOperationError; */ } dprint(" Get first prvt table..\n"); /* Get iTableNumber 0.. first table. */ err = (DHL_RESULT)RfDownload_GetPrvt(tsd, &prvt, pInfo->Pid, pInfo->TableId, 0, nRxTimeOutSec*1000, checkfn); if (err != DHL_OK) { dprint("!! GetPrvt() err %d\n", err); return statusError; /* err; */ } iCurrentTable = GETUpperByte(prvt->table_id_extension); iLastTable = GETLowerByte(prvt->table_id_extension); dprint(" PRVT: ver %d, tidex 0x%x (cur %d, last %d), len %d\n", (int)prvt->version_number, (int)prvt->table_id_extension, iCurrentTable, iLastTable, prvt->private_data_length); dprint(" total %d tables (0 ~ %d)\n", iLastTable+1, iLastTable); if (callback) callback(RFDOWNLOAD_REPORT_DOWNLOAD, (iCurrentTable+1)*100/(iLastTable+1)); /* PRVT array ¸Þ¸ð¸® ÇÒ´ç. */ pPrvtsList = DHL_OS_Malloc((iLastTable+1) * sizeof(prvtPtr_t *)); if (pPrvtsList == NULL) return statusOutOfMemory; /* outOfCPUMemoryError; */ pPrvtsList[0] = prvt; prvt = NULL; if (iLastTable <= 0) { dprint(" only 1 table exist. receive complete..\n"); nReceivedCount = 1; goto label_prvts_received; } pProcData = (PrvtEventProcData *) DHL_OS_Malloc(sizeof(PrvtEventProcData) * (iLastTable+1)); if (pProcData == NULL) { dprint("!! pProcData allocation failed...\n"); /* err = outOfCPUMemoryError; */ status = statusOutOfMemory; goto label_exit; } memset(pProcData, 0, sizeof(PrvtEventProcData)*(iLastTable+1)); /* ÀÌÁ¦ ³ª¸ÓÁö´Â monitoringÀ» °ÉÀÚ... */ for (i = 0 ; i <= iLastTable; i++) { if (i == iCurrentTable) { dprint(" monitor[%d] skip! already exist\n", i); pProcData[i].receiveOk = 1; pProcData[i].receiveCheckOk = 1; continue; } pProcData[i].index = i; pProcData[i].err = DHL_OK; pProcData[i].receiveOk = 0; pProcData[i].receiveCheckOk = 0; pProcData[i].waitsem = waitsem; dprint(" monitor[%d] start\n", i); err = RfDownload_MonitorPrvt(tsd, ePSIMODE_TABLE, ePSIUPDATE_ONESHOT, PrvtSyncEventProc, pInfo->Pid, pInfo->TableId, (UINT16)i, (UINT32)&pProcData[i], &pProcData[i].hPsiCtl); if (err == DHL_OK) { nPrvtMonitor++; } else { dprint("!! PrvtMonitor[%d] err %d.. total %d monitors\n", i, err, nPrvtMonitor); status = statusInvalidVCT; goto label_exit; } } dprint(" total %d monitors ok. now wait..\n", nPrvtMonitor); if (checkfn && checkfn()) goto label_cancelled; nReceivedCount = 1; /* ÀÌ¹Ì ÇѰ³¸¦ ¹ÞÀº »óÅÂÀ̹ǷΠ1ºÎÅÍ ½ÃÀÛ. */ while (nReceivedCount <= iLastTable) { int nLeftTimeTick = (int)nRxTimeOutSec*_second - (int)(DHL_OS_GetMsCount()-tickStart); if (checkfn && checkfn()) goto label_cancelled; if (nLeftTimeTick <= 0) { /* err = timeoutError; */ status = statusTimeout; dprint("!! timeout %d seconds\n" , nRxTimeOutSec); goto label_exit; } result = DHL_OS_TakeSemaphore(waitsem, 100); if (checkfn && checkfn()) goto label_cancelled; if (result == DHL_OK) dprint(" some tables may be received\n"); for (i = 0; i < iLastTable+1; i++) { if (pProcData[i].receiveOk == 0) /* ¾ÆÁ÷ ¼ö½Å ¾ÈµÈ table. */ continue; if (pProcData[i].receiveCheckOk == 1) /* ¼ö½Å µÇ°í ó¸® ´Ù µÈ table. */ continue; #if DEVELOPMENT_BUILD DHL_ASSERT(pProcData[i].receiveOk == 1 && pProcData[i].receiveCheckOk == 0, ""); #endif if (pProcData[i].err) { dprint("!! PRVT[%d] received err %d\n", pProcData[i].err); break; } if (pProcData[i].hPsiCtl == (tDHL_PSI_ControlHandle)0) { dprint("!! PRVT[%d] received but no psictl !!\n", i); } if (pPrvtsList[i]) dprint("!! warning! PRVT[%d] non-NULL before parsing..\n", i); dprint(" PRVT[%d] received. parsing..\n", i); err = RfDownload_ParsePrvt(pProcData[i].desc, &pPrvtsList[i]); if (err) { dprint("!! PRVT[%d] parsing err %d\n", i, err); status = statusInvalidVCT; goto label_exit; } DHL_PSI_StopMonitor(pProcData[i].hPsiCtl); pProcData[i].hPsiCtl = (tDHL_PSI_ControlHandle)0; if (pProcData[i].desc) { DHL_PSI_FreePSIData(pProcData[i].desc); pProcData[i].desc = NULL; } pProcData[i].hPsiCtl = (tDHL_PSI_ControlHandle)0; pProcData[i].desc = NULL; pProcData[i].receiveCheckOk = 1; nReceivedCount++; dprint(" PRVT[%d] parsed. total rx count %d\n", i, nReceivedCount); iCurrentTable = GETUpperByte(pPrvtsList[i]->table_id_extension); iLastTable = GETLowerByte(pPrvtsList[i]->table_id_extension); dprint(" PRVT: ver %d, tidex 0x%x (cur %d, last %d), len %d\n", (int)pPrvtsList[i]->version_number, (int)pPrvtsList[i]->table_id_extension, iCurrentTable, iLastTable, pPrvtsList[i]->private_data_length); if (callback) callback(RFDOWNLOAD_REPORT_DOWNLOAD, (iCurrentTable+1)*100/(iLastTable+1)); } /* for( i = 0 ; i < iLastTable + 1 ; i++ ) */ if (nReceivedCount == iLastTable+1) { dprint(" all %d tables received\n", nReceivedCount); break; } } label_prvts_received: if (nReceivedCount != iLastTable+1) { dprint("!! only %d tables received !!\n", nReceivedCount); /* err = generalError; */ status = statusNotFound; goto label_exit; } pInfo->PrvtList = pPrvtsList; pInfo->NumPrvts = iLastTable+1; dprint(" download completed. num prvts %d\n", pInfo->NumPrvts); /* err = DHL_OK; */ status = statusOK; goto label_exit; label_cancelled: /* err = userCancelError; */ status = statusCancelled; label_exit: dprint(" cancel all remaining monitors..\n"); for (i = 0; pProcData && i < iLastTable+1; i++) { if (pProcData[i].hPsiCtl) { dprint(" DHL_PSI_StopMonitor(%d)\n", i); DHL_PSI_StopMonitor(pProcData[i].hPsiCtl); pProcData[i].hPsiCtl = (tDHL_PSI_ControlHandle)0; } } if (pProcData) { DHL_OS_Free((void**)&pProcData); pProcData = NULL; } if (waitsem) { DHL_OS_DeleteSemaphore(waitsem); waitsem = (DHL_OS_SEMA_ID)NULL; } return status; } #if 0 int RfUpdate_Vprint(const char *format, va_list va) { char buff[100]; int n; n = vsprintf(buff, format, va); dprint(buff); return n; } /* Çϳª ÀÌ»óÀÇ chunk·Î ÀÌ·ç¾î Á®¼­ flash write°¡ ÀÌ·ç¾îÁö¹Ç·Î driver¿¡¼­ reportµÇ´Â percentage´Â ÀüüÀûÀÎ progress percentage°¡ ¾Æ´Ï´Ù. µû¶ó¼­ ÇöÀç ¾î´À chunk°¡ ÁøÇàÁßÀÎÁö ¾Ë°í ÀÖ¾î¾ß ÇÑ´Ù. */ int g_RfUpdate_CurrentChunkIdx; /* ÇöÀç ÁøÇàÁßÀÎ chunk index (0 ~ ..) */ int g_RfUpdate_NumChunk; /* Àüü chunk °¹¼ö. */ void (*g_RfUpdate_ReportFn)(RfUpdateReport msg, UINT32 value); static void RfUpdate_FlashStatusCallback(enum SFlashReport msg, UINT32 value) { if (msg == SFLASH_REPORT_ERASE) { if (value <= 100) g_RfUpdate_ReportFn(RFUPDATE_REPORT_ERASE, value); } else if (msg == SFLASH_REPORT_BLANKCHECK) { if (value <= 100) g_RfUpdate_ReportFn(RFUPDATE_REPORT_BLANKCHECK, value); } else if (msg == SFLASH_REPORT_WRITE) { int percentage = (100*g_RfUpdate_CurrentChunkIdx + value)/g_RfUpdate_NumChunk; if (value <= 100) g_RfUpdate_ReportFn(RFUPDATE_REPORT_WRITE, percentage); } else if (msg == SFLASH_REPORT_VERIFY) { if (value <= 100) g_RfUpdate_ReportFn(RFUPDATE_REPORT_VERIFY, value); } else { /* dprint("---- report: msg [%d], value [%d]\n", msg, value); */ /* g_RfUpdate_ReportFn(msg, value); */ } OS_Delay(1000/10); } static int SafeUpdateStage2Code(UINT8 *buf) { int err = 0; int i; for (i=0; i<5; i++) { if (!err) err = SFlash_Erase(0, STAGE2_SIZE); if (!err) err = SFlash_BlankCheck(0, STAGE2_SIZE); if (!err) err = SFlash_Write(0, buf, STAGE2_SIZE); if (!err) err = SFlash_Verify(0, buf, STAGE2_SIZE); if (err == 0) { dprint("## stage2 updated successfully\n"); return 0; } dprint("## stage2 update err, retry..\n"); OS_Delay(1000/4); } dprint("## stage2 update failed !!\n"); return -1; } #endif /* #if 0 */ /* end of file */