/**************************************************************************** *_Copyright (c) 2004 DST Technologies Inc. All Rights Reserved. * * file name dsthalPsiApi.c * Author: hwatk * Description: DSMCC * * ***************************************************************************/ #include "dsthalcommon.h" #include "dstoslayer.h" #include "dsthalerror.h" #include #include #include #include "dsthalPsiMemChain.h" #include "dsthalPsiBitBuffer.h" #include "dsthalPsiAtscPsip.h" #include "dsthalPsiMpegSi.h" /****************************************************************************** * Global variable declaration ******************************************************************************/ DSMCCDatabase_t *pDsmccDB = NULL; /****************************************************************************** * Imported variable declaration ******************************************************************************/ extern DHL_PSI_HANDLE gPsiHandle; /****************************************************************************** * Imported function declaration ******************************************************************************/ extern void hal_cbPSISyncEventProc ( PSIEvent event , DHL_TBL_HANDLE hTblHandle , DS_U32 userParam ); /****************************************************************************** * Local definitions ******************************************************************************/ /****************************************************************************** * Local typedefs ******************************************************************************/ typedef void *(*fnAlloc_t)(int); typedef void (*fnFree_t)(void *); /****************************************************************************** * Local variables declaration ******************************************************************************/ static const DS_U8 XltIdx2Bit[ ] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; static fnAlloc_t g_pDsmccAllocFunc = (fnAlloc_t)0; static fnFree_t g_pDsmccFreeFunc = (fnFree_t)0; /****************************************************************************** * Local function prototypes ******************************************************************************/ void DHL_PSI_CancelAllDsmccMonitors( void ); DHL_RESULT DHL_PSI_ParseDsmccDIISection( DS_U8 *section, dsmccDIISectionPtr_t *ppDsmccDIISection ); #if 0 ___DSMCC_FUNCTION___() #endif /************************************************************************** * Function Name : DsmccMainTask * * Description : DSM-CC DDB thread * * Parameters : None * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ void *DSMCC_MALLOC(int size) { if (g_pDsmccAllocFunc) return (g_pDsmccAllocFunc)(size); else return malloc(size); } void DSMCC_FREE(void *addr) { if (g_pDsmccFreeFunc) (g_pDsmccFreeFunc)(addr); else free(addr); } /************************************************************************** * Function Name : DHL_PSI_ActivateDsmcc * * Description : Initializes DSM-CC module, creates DSM-CC msg queue, sema4, * thread, and launches it. * * Parameters : * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ DHL_RESULT DHL_PSI_ActivateDsmcc( int *pAppTaskPriority ) { DHL_RESULT err = DHL_OK; //DsmccMsg_t dsmccMsg; //OS_TASK_ID dsmccTaskID = (OS_TASK_ID)0; OS_SEMAPHORE_ID mutexSema4 = (OS_SEMAPHORE_ID)NULL; OS_SEMAPHORE_ID controlSema4 = (OS_SEMAPHORE_ID)NULL; if ( *pAppTaskPriority >= DSMCCDDB_TASK_PRIO ) *pAppTaskPriority = DSMCCDDB_TASK_PRIO - 1; if (!g_pDsmccAllocFunc) g_pDsmccAllocFunc = (fnAlloc_t)malloc; if (!g_pDsmccFreeFunc) g_pDsmccFreeFunc = free; /* Take the global dsmcc binary sema4 created in the TLSys here * Allow only one instance of DSM-CC processing thread */ if ( pDsmccDB != NULL ) { /* Give the global dsmcc binary sema4 */ return DHL_FAIL_CORE_DRIVER; } /* Create and initialize our own Database */ pDsmccDB = (DSMCCDatabase_t *)malloc( sizeof(DSMCCDatabase_t) ); /* Give the global dsmcc binary sema4 */ if ( pDsmccDB == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto doneError; } /* Clear the DSMCC database block */ memset( pDsmccDB, 0, sizeof(DSMCCDatabase_t) ); /* Create Mutex Sema4 */ mutexSema4 = OS_CreateMutex("dsmccMutexSema4"); if ( mutexSema4 == (OS_MUTEX_ID)NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto doneError; } /* Create Control Sema4 */ controlSema4 = OS_CreateCountingSemaphore("dsmccControlSema4",0,0); if(controlSema4 == (OS_SEMAPHORE_ID)NULL) { err = DHL_FAIL_OUT_OF_RESOURCE; goto doneError; } /* Copy all the information into the common area in DSMCC DB structure */ ///pDsmccDB->dsmccTaskID = dsmccTaskID; ///pDsmccDB->dsmccQ = dsmccQ; pDsmccDB->mutexSema4 = mutexSema4; ///pDsmccDB->syncSema4 = syncSema4; #if 0 // Main Task´Â Á¦°ÅÇϰí, °¢ DDB Monitor´ç Task »ý¼º. /* Spawn the DSMCC thread */ dsmccTaskID = OS_SpawnTask( (OS_TASKFUNCTION)DsmccDDBTask, "tDsmccMainTask", DSMCCDDB_TASK_PRIO, 16*1024, (DS_S32)0); /* Synchronize with the thread launched */ dsmccMsg.event = eDsmccActivate; dsmccMsg.param = (void *)pDsmccDB; OS_SendMessage(pDsmccDB->dsmccQ, (DS_U32 *)&dsmccMsg, sizeof(DsmccMsg_t)); OS_TakeSemaphore(pDsmccDB->syncSema4); #endif pDsmccDB->isActive = _TRUE_; return err; doneError: // if (dsmccQ) { OS_DeleteMessageQueue(dsmccQ); } if (mutexSema4) { OS_DeleteSemaphore(mutexSema4); } // if (syncSema4) { OS_DeleteSemaphore(syncSema4); } if (controlSema4) { OS_DeleteSemaphore(controlSema4); } if (pDsmccDB) { free(pDsmccDB); pDsmccDB = NULL; } return err; } /************************************************************************** * Function Name : DHL_PSI_DeactivateDsmcc * * Description : Issues request to DSM-CC thread to stop and terminate * itself. All active DII and DDB monitors will be * terminated. * Parameters : * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ DHL_RESULT DHL_PSI_DeactivateDsmcc( void ) { DHL_RESULT err = DHL_OK; // DsmccMsg_t dsmccMsg; // DS_U32 i; if ( pDsmccDB && pDsmccDB->isActive ) { #if 0 dsmccMsg.event = eDsmccDeactivate; OS_SendMessage(pDsmccDB->dsmccQ, &dsmccMsg, sizeof(DsmccMsg_t)); OS_TakeSemaphore(pDsmccDB->syncSema4); #else // ¿©±â¼­ DDB °ü·Ã Thread¸¦ ¸ðµÎ ¾ø¾ÖÀÚ! --+ #endif // OS_DeleteSemaphore(pDsmccDB->syncSema4); OS_DeleteSemaphore(pDsmccDB->mutexSema4); OS_DeleteSemaphore(pDsmccDB->controlSema4); // OS_DeleteMessageQueue(pDsmccDB->dsmccQ); free(pDsmccDB); pDsmccDB = NULL; } return err; } /************************************************************************** * Function Name : DHL_PSI_CancelAllDsmccMonitors * * Description : Terminate all DII and DDB monitors and * free up the resources being used for monitoring * * Parameters : * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ void DHL_PSI_CancelAllDsmccMonitors( void ) { DDBMsgMonContextPtr_t pDDBMsgMonContext; DS_U16 i; OS_TakeSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex access for ( i = 0; i < NUM_DII_MON_CONTEXTS; i++ ) { if ( pDsmccDB->DIIMonContexts[ i ].isUsed && pDsmccDB->DIIMonContexts[ i ].psiCtl ) { DHL_PSI_CancelMonitor( pDsmccDB->DIIMonContexts[ i ].psiCtl ); ////(*pDsmccDB->DIIMonContexts[ i ].pfCallbackProc)( NULL ); // Notify client with NULL? } } for ( i = 0; i < NUM_DDB_MON_CONTEXTS; i++ ) { if ( pDsmccDB->DDBMonContexts[ i ].isUsed ) { pDDBMsgMonContext = &pDsmccDB->DDBMonContexts[ i ]; if ( pDDBMsgMonContext->psiCtl ) DHL_PSI_CancelMonitor( pDDBMsgMonContext->psiCtl ); if ( pDDBMsgMonContext->pDDBModule != NULL ) // Free DDB module mem chain buffer memChainDestroy( pDDBMsgMonContext->memId ); if ( pDDBMsgMonContext->pBlockRecvBitFlags ) // Free receive bit buffer free( (pDDBMsgMonContext->pBlockRecvBitFlags) ); } } OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release } static DHL_RESULT CreateDIIContext( DsmccEventProc_t pfCallbackProc, DS_U32 *pDIIMonContextId ) { DHL_RESULT err = DHL_OK; DIIMsgMonContextPtr_t pDIIMsgMonContext; DS_U32 i; // Alloc memory block for DDB monitoring context and store all the DDB monitoring parameters // in the allocated memory block for ( i = 0; i < NUM_DII_MON_CONTEXTS; i++ ) { if ( !pDsmccDB->DIIMonContexts[ i ].isUsed ) { break; } } if ( i >= NUM_DII_MON_CONTEXTS ) { printf( "CreateDIIContext: Out of monitoring context\n" ); err = DHL_FAIL_TOO_MANY_INSTANCES; return err; } // Initialize DII monitoring context structure pDIIMsgMonContext = &pDsmccDB->DIIMonContexts[ i ]; memset( (DS_U8*)pDIIMsgMonContext, 0, sizeof(DIIMsgMonContext_t) ); pDIIMsgMonContext->isUsed = _TRUE_; // This context is now being used pDIIMsgMonContext->pfCallbackProc = pfCallbackProc; // Client callback func ptr *pDIIMonContextId = i; // Return context ID return err; } static void FreeDIIContext( DS_U32 DIIMonContextId ) { if ( DIIMonContextId < NUM_DII_MON_CONTEXTS ) { OS_TakeSemaphore( pDsmccDB->mutexSema4 ); // Mutex access pDsmccDB->DIIMonContexts[ DIIMonContextId ].isUsed = _FALSE_; pDsmccDB->DIIMonContexts[ DIIMonContextId ].psiCtl = NULL; OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // Mutex release } } /************************************************************************** * Function Name : FreeDsmccMemChain * * Description : Destroy the previously allocated memory chain structure * * Parameters : * * Return : ErrCode * noErrror - success **************************************************************************/ DHL_RESULT FreeDsmccMemChain(void* pDsmccMem) { DHL_RESULT rval = DHL_OK; if ( pDsmccMem != NULL ) { rval = memChainDestroy(*(((memId_t *)pDsmccMem)-1)); } return (rval); } /************************************************************************** * Function Name : DHL_PSI_MonitorDsmccDII * * Description : Setup DII message monitoring and filters * * Parameters : transactionId - version of DII * pfCallbackProc - client callback proc * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ //DHL_RESULT DHL_PSI_MonitorDsmccDII( DHL_PSI_HANDLE sysInfo, DS_U16 Pid, DS_U16 transactionId, DsmccEventProc_t pfCallbackProc, DHL_TBL_HANDLE *returnPsiCtl ) DHL_RESULT DHL_PSI_MonitorDsmccDII( DHL_PSI_HANDLE sysInfo, DS_U16 Pid, DS_U16 transactionId, DsmccEventProc_t pfCallbackProc, DS_U32 userParam, DHL_TBL_HANDLE *returnPsiCtl ) { DHL_RESULT err = DHL_OK; PSIMask_t *pref; DS_U32 DIIMonContextId; DS_BOOL isActive; int Priority=80; // Check if the dsmcc thread is up and running... isActive = (pDsmccDB) ? pDsmccDB->isActive : _FALSE_; if ( !isActive ) { err = DHL_PSI_ActivateDsmcc(&Priority); if ( err != DHL_OK ) { printf( "DHL_PSI_ActivateDsmcc: failure. (0x%x)\n", err ); return( DHL_FAIL_NOT_CONNECTED ); } else { isActive = (pDsmccDB) ? pDsmccDB->isActive : _FALSE_; if ( !isActive ) { printf( "CreateDIIContext: DSMCC thread is not active\n" ); return( DHL_FAIL_NOT_CONNECTED ); } } } // Check function arguments if ( (sysInfo == NULL) || (returnPsiCtl == NULL) ) { printf( "%s(): sysInfo = %lx returnPsiCtl = %lu\n", __FUNCTION__, (sysInfo)?(DS_U32)sysInfo:0, (returnPsiCtl)?(DS_U32)returnPsiCtl:0 ); return( DHL_FAIL_NULL_POINTER ); } // Acquire the table data by the specified filter(s) // Currently we do not use transaction_id, since hardware PSI filter doesn't support more than 16 bytes section filter. if ((err = DD_PSI_GetDsmccPSIMask ( &pref, tid_dsmcc_download_info_indication, // DII Table ID DSMCC_MESSAGE_DII, _TRUE_))) { printf("|%s| ERROR, LINE=%d (0x%x)\n", __FUNCTION__, __LINE__, err); return( err ); } // Create DII monitoring context and setup DII monitor filter // OS_TakeSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex access err = CreateDIIContext( pfCallbackProc, &DIIMonContextId ); if ( err != DHL_OK ) { OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release printf("|%s| ERROR, LINE=%d\n", __FUNCTION__, __LINE__); return( err ); } // Start monitoring for the dsmcc DII table if ( (err = DD_PSI_MonitorPSIPid( sysInfo, // Transport Demux Unit Pid, // Packet ID to filter the DSM-CC DII msgs tableMode, // All section received table mode //psiCRCChange, // Only if there's a CRC change in the DII table psiOneShot, pref, // PSI filter MAX_DSMCC_SECTION_LENGTH, // 4Kb MAX_DSMCC_SECTIONS, // 256? hal_cbPSISyncEventProc, // DII event handler //DIIMonContextId, // DII context ID userParam, returnPsiCtl ) ) ) { //printf("|%s| ERROR, LINE=%d (0x%x)\n", __FUNCTION__, __LINE__, err); } if ( err == DHL_OK ) { // Save the current PSI monitor control in the monitor context pDsmccDB->DIIMonContexts[ DIIMonContextId ].psiCtl = *returnPsiCtl; } else { pDsmccDB->DIIMonContexts[ DIIMonContextId ].isUsed = _FALSE_; } OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release return( err ); } /************************************************************************** * Function Name : DHL_PSI_CancelDII * * Description : Cancel DII message monitoring * * Parameters : * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ DHL_RESULT DHL_PSI_CancelDII( DHL_TBL_HANDLE psiCtl ) { DS_U32 i; for ( i = 0; i < NUM_DII_MON_CONTEXTS; i++ ) { if ( pDsmccDB->DIIMonContexts[ i ].isUsed && pDsmccDB->DIIMonContexts[ i ].psiCtl ) { if ( pDsmccDB->DIIMonContexts[ i ].psiCtl == psiCtl ) break; } } if ( i < NUM_DII_MON_CONTEXTS ) { DHL_PSI_CancelMonitor( psiCtl ); FreeDIIContext( i ); return DHL_OK; } else { return DHL_FAIL_NOT_FOUND; } } /************************************************************************** * Function Name : DHL_PSI_ParseDsmccDII * * Description : Parse the entire DSMCC DII table and return the parsed * data * Parameters : * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ DHL_RESULT DHL_PSI_ParseDsmccDII( PSIDataArray_t *desc, DsmccDIIMsgPtr_t *ppDsmccDIIMsg ) { DHL_RESULT err = DHL_OK; DS_U8 **sectionArr; memId_t memId = NULL; memChainSetup_t memSetup = { DSMCC_DII_MEM_LIMIT, NULL, NULL }; DS_U8 numSections; dsmccDIISectionPtr_t pDsmccDIISection; // DSMCC DII msg section DIIMsgPtr_t spDIIMsgSection, dpDIIMsgSection; // DII msg section DsmccMsgHeaderPtr_t spDsmccMsgHeader, dpDsmccMsgHeader; // Dsmcc msg header dsmccDIIAdaptHeaderPtr_t spDsmccAdaptationHeader; // Dsmcc adaptation header //CompatblDescInfoPtr_t spCompatblDescInfo; // Comp descriptor ModuleInfoPtr_t spDIIModuleInfo, dpDIIModuleInfo; // Module info DS_U8* spModuleInfoByte; // Module info bytes DS_U8* spPrivateDataByte; // Private data bytes DS_U16 i, j; if ( (desc == NULL) || (ppDsmccDIIMsg == NULL) ) { return( DHL_FAIL_INVALID_PARAM ); } // sectionArr is array of pointers to DSMCC-encapsulated DII table data sections // sectionArr = (DS_U8 **)desc->sectPtr; // Do sanity check if ( sectionArr[0] == NULL ) { return ( DHL_FAIL_CORE_DRIVER ); } // Assume section counts is last_sectionNo + 1 // Get the last_sectionNo from the first section // For DII message the first section is the only section and should be the last section // numSections = get_last_section_number( sectionArr[0] ) + 1; if ( desc->numSections != numSections ) { return (DHL_FAIL_CORE_DRIVER); } // Check whether we have all the sections in the section array for ( i = 1; i < numSections; i++ ) { if ( sectionArr[i] == NULL ) { return (DHL_FAIL_CORE_DRIVER); } } // DII memChain creation and allocation err = memChainCreate( &memId, &memSetup ); if ( err ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Allocate memory for DsmccDII *ppDsmccDIIMsg = (DsmccDIIMsgPtr_t)((memId_t *)(memChainAlloc(memId, sizeof(DsmccDIIMsg_t) + sizeof(memId_t))) + 1); if (*ppDsmccDIIMsg == NULL) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Total section numbers and allocate the memory to hold the DII msg sections (*ppDsmccDIIMsg)->numSections = numSections; (*ppDsmccDIIMsg)->ptrDIIMsgSections = (DIIMsgPtr_t)memChainAlloc(memId, numSections * sizeof(DIIMsg_t)); if ( (*ppDsmccDIIMsg)->ptrDIIMsgSections == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } //****************************************************************************/ // Start processing the DII message sections */ // Parse each DSMCC DII section and copy the parsed contents */ //****************************************************************************/ #if DSMCC_DEBUG printf( "*** ParseDsmccDII() number of sections = %d ***\n", numSections ); #endif // Initialize destination pointer to DII message sections dpDIIMsgSection = (*ppDsmccDIIMsg)->ptrDIIMsgSections; for ( i = 0; i < numSections; i++, dpDIIMsgSection++ ) { // Parse the current section err = DHL_PSI_ParseDsmccDIISection( sectionArr[ i ], &pDsmccDIISection ); if ( (err != DHL_OK) || (pDsmccDIISection == NULL) ) goto ParseExit; // Initialize the "source" pointers used for data copying spDIIMsgSection = pDsmccDIISection->ptrDIIMsgSection; spDsmccMsgHeader = spDIIMsgSection->ptrDsmccMsgHeader; spDsmccAdaptationHeader = spDsmccMsgHeader->ptrDsmccAdaptationHeader; //spCompatblDescInfo = spDIIMsgSection->compatblDesc.ptrCompatblDescInfo; spDIIModuleInfo = spDIIMsgSection->ptrDIIModuleInfo; spModuleInfoByte = spDIIModuleInfo->ptrModuleInfoByte; spPrivateDataByte = spDIIMsgSection->ptrPrivateDataByte; // Copy important repeated information into the main container structure once only if ( i == 0 ) { (*ppDsmccDIIMsg)->table_id = pDsmccDIISection->table_id; (*ppDsmccDIIMsg)->dsmcc_section_length = pDsmccDIISection->dsmcc_section_length; (*ppDsmccDIIMsg)->table_id_extension = pDsmccDIISection->table_id_extension; (*ppDsmccDIIMsg)->version_number = pDsmccDIISection->version_number; (*ppDsmccDIIMsg)->current_next_indicator= pDsmccDIISection->current_next_indicator; (*ppDsmccDIIMsg)->section_number = pDsmccDIISection->section_number; (*ppDsmccDIIMsg)->last_section_number = pDsmccDIISection->last_section_number; (*ppDsmccDIIMsg)->transaction_id = spDsmccMsgHeader->transaction_id; (*ppDsmccDIIMsg)->downloadId = spDIIMsgSection->downloadId; (*ppDsmccDIIMsg)->blockSize = spDIIMsgSection->blockSize; } // Copy DII dsmcc msg header section data dpDIIMsgSection->ptrDsmccMsgHeader = (DsmccMsgHeaderPtr_t)memChainAlloc( memId, sizeof(DsmccMsgHeader_t) ); if ( dpDIIMsgSection->ptrDsmccMsgHeader == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } dpDsmccMsgHeader = dpDIIMsgSection->ptrDsmccMsgHeader; memcpy( dpDsmccMsgHeader, spDsmccMsgHeader, sizeof(DsmccMsgHeader_t) ); // Copy the adaptation header block if ( dpDsmccMsgHeader->adaptationLength > 0 ) { dpDsmccMsgHeader->ptrDsmccAdaptationHeader = (dsmccDIIAdaptHeaderPtr_t)memChainAlloc( memId, spDsmccMsgHeader->adaptationLength ); if ( dpDsmccMsgHeader->ptrDsmccAdaptationHeader == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } memcpy( dpDsmccMsgHeader->ptrDsmccAdaptationHeader, spDsmccMsgHeader->ptrDsmccAdaptationHeader, dpDsmccMsgHeader->adaptationLength ); } // Copy DII msg section data dpDIIMsgSection->downloadId = spDIIMsgSection->downloadId; dpDIIMsgSection->blockSize = spDIIMsgSection->blockSize; dpDIIMsgSection->windowSize = spDIIMsgSection->windowSize; dpDIIMsgSection->ackPeriod = spDIIMsgSection->ackPeriod; dpDIIMsgSection->tCDownloadWindow = spDIIMsgSection->tCDownloadWindow; dpDIIMsgSection->tCDownloadScenario = spDIIMsgSection->tCDownloadScenario; // Copy compatibility descriptor block memcpy( (DS_U8*)&dpDIIMsgSection->compatblDesc, (DS_U8*)&spDIIMsgSection->compatblDesc, sizeof(CompatblDesc_t) ); if ( dpDIIMsgSection->compatblDesc.descLength > 2 ) { DS_U8 *p_compat_sys = (DS_U8 *)NULL; dpDIIMsgSection->compatblDesc.descriptors = (DS_U8 *)memChainAlloc( memId, dpDIIMsgSection->compatblDesc.descLength-2 ); if ( dpDIIMsgSection->compatblDesc.descriptors == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } memcpy( dpDIIMsgSection->compatblDesc.descriptors, spDIIMsgSection->compatblDesc.descriptors, dpDIIMsgSection->compatblDesc.descLength-2 ); err=GetMpegDescriptor( dpDIIMsgSection->compatblDesc.descriptors, dpDIIMsgSection->compatblDesc.descLength-2, COMPATBL_DESC_SYSTEM_HW, 0, &p_compat_sys ); if (err!=DHL_OK) { /* If cannot find SYSTEM_HW, then try with SYSTEM_SW. */ err=GetMpegDescriptor( dpDIIMsgSection->compatblDesc.descriptors, dpDIIMsgSection->compatblDesc.descLength-2, COMPATBL_DESC_SYSTEM_HW, 0, &p_compat_sys ); } if (err==DHL_OK) { /* We found System_HW compatibility descriptor. */ CompatblDescInfoPtr_t p_desc = (CompatblDescInfoPtr_t)&dpDIIMsgSection->compatblDesc.compatblDescInfo; bitBufferPtr_t bits = NULL; err = bitBufferCreate( &bits, p_compat_sys, dpDIIMsgSection->compatblDesc.descLength-2 ); if ( err ) { goto ParseExit; } p_desc->descType = bitBufferGetBits(bits, 8); p_desc->descLength = bitBufferGetBits(bits, 8); p_desc->specifierType = bitBufferGetBits(bits, 8); p_desc->specifierData = bitBufferGetBits(bits, 24); p_desc->model = bitBufferGetBits(bits, 16); p_desc->version = bitBufferGetBits(bits, 16); p_desc->bValid = DS_TRUE; p_desc->subDescCount = bitBufferGetBits(bits, 8); if ( bits ) { // clean up the bitBuffer bitBufferDestroy( bits ); } } } // Copy the DII module information data section dpDIIMsgSection->numberOfModules = spDIIMsgSection->numberOfModules; if ( dpDIIMsgSection->numberOfModules > 0 ) { dpDIIMsgSection->ptrDIIModuleInfo = (ModuleInfoPtr_t)memChainAlloc( memId, dpDIIMsgSection->numberOfModules * sizeof(ModuleInfo_t) ); if ( dpDIIMsgSection->ptrDIIModuleInfo == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Init module info destination ptr dpDIIModuleInfo = dpDIIMsgSection->ptrDIIModuleInfo; for ( j = 0; j < dpDIIMsgSection->numberOfModules; j++, dpDIIModuleInfo++, spDIIModuleInfo++ ) { memcpy( dpDIIModuleInfo, spDIIModuleInfo, sizeof(ModuleInfo_t) ); if ( dpDIIModuleInfo->moduleInfoLength > 0 ) { DS_U8* p_desc = (DS_U8 *)NULL; dpDIIModuleInfo->ptrModuleInfoByte = (DS_U8*)memChainAlloc( memId, dpDIIModuleInfo->moduleInfoLength ); if ( dpDIIModuleInfo->ptrModuleInfoByte == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Copy the module information data bytes memcpy( dpDIIModuleInfo->ptrModuleInfoByte, spDIIModuleInfo->ptrModuleInfoByte, dpDIIModuleInfo->moduleInfoLength ); /* * Parse module info descriptor. */ err=GetMpegDescriptor( dpDIIModuleInfo->ptrModuleInfoByte, dpDIIModuleInfo->moduleInfoLength, 0xB7 /* Module Info descriptor = 0xB7 */, 0, &p_desc ); if (err==DHL_OK) { dpDIIModuleInfo->module_name_length = p_desc[3]; dpDIIModuleInfo->ptrModuleName = (DS_U8 *)memChainAlloc( memId, dpDIIModuleInfo->module_name_length ); if ( dpDIIModuleInfo->ptrModuleName == (DS_U8 *)NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } memcpy( dpDIIModuleInfo->ptrModuleName, &p_desc[4], dpDIIModuleInfo->module_name_length ); } /* * Parse CRC32 descriptor. */ err=GetMpegDescriptor( dpDIIModuleInfo->ptrModuleInfoByte, dpDIIModuleInfo->moduleInfoLength, 0xB5 /* CRC32 descriptor = 0xB5 */, 0, &p_desc ); if (err==DHL_OK) { dpDIIModuleInfo->bCrcFieldValid = DS_TRUE; dpDIIModuleInfo->Crc32_descriptor = p_desc[2] << 24; dpDIIModuleInfo->Crc32_descriptor += p_desc[3] << 16; dpDIIModuleInfo->Crc32_descriptor += p_desc[4] << 8; dpDIIModuleInfo->Crc32_descriptor += p_desc[5] << 0; } } } } else { dpDIIMsgSection->ptrDIIModuleInfo = NULL; } // Copy the DII private data section dpDIIMsgSection->privateDataLength = spDIIMsgSection->privateDataLength; if ( dpDIIMsgSection->privateDataLength > 0 ) { dpDIIMsgSection->ptrPrivateDataByte = (DS_U8*)memChainAlloc( memId, dpDIIMsgSection->privateDataLength ); if ( dpDIIMsgSection->ptrPrivateDataByte == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Copy the private information data bytes memcpy( dpDIIMsgSection->ptrPrivateDataByte, spDIIMsgSection->ptrPrivateDataByte, dpDIIMsgSection->privateDataLength ); } else { dpDIIMsgSection->ptrPrivateDataByte = NULL; } FreeDsmccMemChain( pDsmccDIISection ); } // Parsing/copying is complete, save memId into the memChain alloc-ed *(((memId_t *)(*ppDsmccDIIMsg))-1) = memId; memId = NULL; // Reset memId so its memChain won't get destroyed ParseExit: if ( memId ) { memChainDestroy( memId ); *ppDsmccDIIMsg = NULL; } return ( err ); } /************************************************************************** * Function Name : DHL_PSI_ParseDsmccDIISection * * Description : Parse a DSMCC DII message section * * Parameters : * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ DHL_RESULT DHL_PSI_ParseDsmccDIISection( DS_U8 *section, dsmccDIISectionPtr_t *ppDsmccDIISection ) { DHL_RESULT err = DHL_OK; dsmccDIISectionPtr_t dsmccDIISectPtr = NULL; DsmccMsgHeaderPtr_t pDsmccMsgHeader; DIIMsgPtr_t pDIIMsg; ModuleInfoPtr_t pDIIModuleInfo; memId_t memId = NULL; memChainSetup_t memSetup = { DSMCC_DII_MEM_LIMIT, NULL, NULL }; DS_U8 table_id; DS_U16 dsmcc_section_length; bitBufferPtr_t bits = NULL; DS_U16 descLength; DS_U8 *dpData; DS_U16 i, j; // Argument check if ( section == NULL ) { printf("ParseDsmccDIISection: NULL section addr!\n"); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } // Perform DSM-CC DII table data validation // Get table_id table_id = get_table_id(section); if ( table_id != DSMCC_DII_TABLE_ID ) { printf("ParseDsmccDIISection: invalid table_id = %0x\n", (int) table_id); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } // Get syntax indicator: 1 = valid if (get_section_syntax_indicator(section) != 1) { printf("ParseDsmccDIISection: section_syntax_indicator not set\n"); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } // Get section length dsmcc_section_length = get_section_length(section); if ( dsmcc_section_length > (MAX_DSMCC_SECTION_LENGTH - 3) ) { printf("ParseDsmccDIISection: invalid section_length = %0d\n", (int) dsmcc_section_length); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } // Create the bitBuffer object and initialize it with the current section data err = bitBufferCreate( &bits, section + 3, dsmcc_section_length ); if ( err ) { goto ParseExit; } // Create the memChain & allocate memory for dsmccDIISection data structure err = memChainCreate( &memId, &memSetup ); if (err) { goto ParseExit; } dsmccDIISectPtr = (dsmccDIISectionPtr_t)((memId_t *)( memChainAlloc(memId, sizeof(dsmccDIISection_t) + sizeof(memId_t)) ) + 1); if ( dsmccDIISectPtr == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Parse the section and fill the DSM-CC DII section data structure dsmccDIISectPtr->table_id = table_id; dsmccDIISectPtr->dsmcc_section_length = dsmcc_section_length; dsmccDIISectPtr->table_id_extension = bitBufferGetBits(bits, 16); // DII transaction number bitBufferSkipBits( bits, 2 ); // Reserved dsmccDIISectPtr->version_number = bitBufferGetBits(bits, 5); // version number dsmccDIISectPtr->current_next_indicator = bitBufferGetBits(bits, 1); // current next indicator if ( dsmccDIISectPtr->current_next_indicator != 1 ) { printf("ParseDsmccDIISection: current_next_indicator not set\n"); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } dsmccDIISectPtr->section_number = bitBufferGetBits(bits, 8); // section_number dsmccDIISectPtr->last_section_number = bitBufferGetBits(bits, 8); // last_section_number //****************************************************************************/ //* Section contents handling */ //****************************************************************************/ // Allocate DII section memory dsmccDIISectPtr->ptrDIIMsgSection = (DIIMsgPtr_t)memChainAlloc( memId, sizeof(DIIMsg_t) ); if ( dsmccDIISectPtr->ptrDIIMsgSection == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } dsmccDIISectPtr->ptrDIIMsgSection->ptrDsmccMsgHeader = (DsmccMsgHeaderPtr_t)memChainAlloc( memId, sizeof(DsmccMsgHeader_t) ); if ( dsmccDIISectPtr->ptrDIIMsgSection->ptrDsmccMsgHeader == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Parse DII dsmcc header and assign them to the section data structure pDsmccMsgHeader = dsmccDIISectPtr->ptrDIIMsgSection->ptrDsmccMsgHeader; pDsmccMsgHeader->protocolDiscriminator = bitBufferGetBits(bits, 8); if ( pDsmccMsgHeader->protocolDiscriminator != 0x11 ) { printf("ParseDsmccDIISection: Invalid protocolDiscriminator = %0x\n", (int) pDsmccMsgHeader->protocolDiscriminator); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } pDsmccMsgHeader->dsmccType = bitBufferGetBits(bits, 8); if ( pDsmccMsgHeader->dsmccType != 0x03 ) { printf("ParseDsmccDIISection: Invalid dsmccType = %0x\n", (int) pDsmccMsgHeader->dsmccType); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } pDsmccMsgHeader->messageId = bitBufferGetBits(bits, 16); if ( pDsmccMsgHeader->messageId != 0x1002 ) { printf("ParseDsmccDIISection: Invalid messageId = %0x\n", (int) pDsmccMsgHeader->messageId); err = DHL_FAIL_INVALID_PARAM; goto ParseExit; } pDsmccMsgHeader->transaction_id = bitBufferGetBits(bits, 32); bitBufferSkipBits( bits, 8 ); // Reserved pDsmccMsgHeader->adaptationLength = bitBufferGetBits(bits, 8); pDsmccMsgHeader->messageLength = bitBufferGetBits(bits, 16); #if DSMCC_DEBUG printf("ParseDsmccDIISection: protocolDiscriminator = 0x%02x\n", pDsmccMsgHeader->protocolDiscriminator ); printf("ParseDsmccDIISection: dsmccType = 0x%02x\n", pDsmccMsgHeader->dsmccType ); printf("ParseDsmccDIISection: messageId = 0x%04x\n", pDsmccMsgHeader->messageId ); printf("ParseDsmccDIISection: transaction_id = 0x%08x\n", pDsmccMsgHeader->transaction_id ); printf("ParseDsmccDIISection: adaptationLength = %d\n", pDsmccMsgHeader->adaptationLength ); printf("ParseDsmccDIISection: messageLength = %d\n", pDsmccMsgHeader->messageLength ); #endif if ( pDsmccMsgHeader->adaptationLength > 0 ) { pDsmccMsgHeader->ptrDsmccAdaptationHeader = (dsmccDIIAdaptHeaderPtr_t)memChainAlloc( memId, pDsmccMsgHeader->adaptationLength ); if ( pDsmccMsgHeader->ptrDsmccAdaptationHeader == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Copy the entire adaptation header block dpData = (DS_U8*)pDsmccMsgHeader->ptrDsmccAdaptationHeader; for ( j = 0; j < pDsmccMsgHeader->adaptationLength; j++ ) dpData[j] = bitBufferGetBits(bits, 8); } else { pDsmccMsgHeader->ptrDsmccAdaptationHeader = NULL; } // Parse DII msg body section and assign them to the proper data structure pDIIMsg = dsmccDIISectPtr->ptrDIIMsgSection; pDIIMsg->downloadId = bitBufferGetBits(bits, 32); pDIIMsg->blockSize = bitBufferGetBits(bits, 16); pDIIMsg->windowSize = bitBufferGetBits(bits, 8); pDIIMsg->ackPeriod = bitBufferGetBits(bits, 8); pDIIMsg->tCDownloadWindow = bitBufferGetBits(bits, 32); pDIIMsg->tCDownloadScenario = bitBufferGetBits(bits, 32); // Parse DII msg compatibility descriptor block and assign them to the proper data structure pDIIMsg->compatblDesc.descLength = bitBufferGetBits(bits, 16); pDIIMsg->compatblDesc.descCount = bitBufferGetBits(bits, 16); pDIIMsg->compatblDesc.compatblDescInfo.bValid = DS_FALSE; #if DSMCC_DEBUG printf("ParseDsmccDIISection: downloadId = 0x%08x\n", pDIIMsg->downloadId ); printf("ParseDsmccDIISection: blockSize = %d\n", pDIIMsg->blockSize ); printf("ParseDsmccDIISection: descLength = %d\n", pDIIMsg->compatblDesc.descLength ); #endif if ( pDIIMsg->compatblDesc.descLength > 2 ) { descLength = pDIIMsg->compatblDesc.descLength - 2; pDIIMsg->compatblDesc.descriptors = (DS_U8 *)memChainAlloc( memId, descLength ); if ( pDIIMsg->compatblDesc.descriptors == (DS_U8 *)NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Copy the entire compatibility descriptor block dpData = (DS_U8*)pDIIMsg->compatblDesc.descriptors; for ( j = 0; j < descLength; j++ ) dpData[j] = bitBufferGetBits(bits, 8); } else { pDIIMsg->compatblDesc.descriptors = NULL; } // Parse DII module information block and assign them to the proper data structure pDIIMsg->numberOfModules = bitBufferGetBits(bits, 16); #if DSMCC_DEBUG printf("ParseDsmccDIISection: numberOfModules = %d\n", pDIIMsg->numberOfModules ); #endif if ( pDIIMsg->numberOfModules > 0 ) { pDIIMsg->ptrDIIModuleInfo = (ModuleInfoPtr_t)memChainAlloc( memId, pDIIMsg->numberOfModules * sizeof(ModuleInfo_t) ); if ( pDIIMsg->ptrDIIModuleInfo == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } pDIIModuleInfo = pDIIMsg->ptrDIIModuleInfo; for ( i = 0; i < pDIIMsg->numberOfModules; i++, pDIIModuleInfo++ ) { pDIIModuleInfo->moduleId = bitBufferGetBits(bits, 16); pDIIModuleInfo->moduleSize = bitBufferGetBits(bits, 32); pDIIModuleInfo->moduleVersion = bitBufferGetBits(bits, 8); pDIIModuleInfo->moduleInfoLength = bitBufferGetBits(bits, 8); pDIIModuleInfo->module_name_length = 0; pDIIModuleInfo->bCrcFieldValid = DS_FALSE; pDIIModuleInfo->ptrModuleName = (DS_U8 *)NULL; if ( pDIIModuleInfo->moduleInfoLength > 0 ) { pDIIModuleInfo->ptrModuleInfoByte = (DS_U8*)memChainAlloc( memId, pDIIModuleInfo->moduleInfoLength ); if ( pDIIModuleInfo->ptrModuleInfoByte == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } for ( j = 0; j < pDIIModuleInfo->moduleInfoLength; j++ ) pDIIModuleInfo->ptrModuleInfoByte[j] = bitBufferGetBits(bits, 8); } } } else { pDIIMsg->ptrDIIModuleInfo = NULL; } // Parse DII private data block and assign them to the proper data structure pDIIMsg->privateDataLength = bitBufferGetBits(bits, 16); #if DSMCC_DEBUG printf("ParseDsmccDIISection: privateDataLength = %d\n", pDIIMsg->privateDataLength ); #endif if ( pDIIMsg->privateDataLength > 0 ) { pDIIMsg->ptrPrivateDataByte = (DS_U8*)memChainAlloc( memId, pDIIMsg->privateDataLength ); if ( pDIIMsg->ptrPrivateDataByte == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } for ( j = 0; j < pDIIMsg->privateDataLength; j++ ) pDIIMsg->ptrPrivateDataByte[j] = bitBufferGetBits(bits, 8); } else { pDIIMsg->ptrPrivateDataByte = NULL; } // Parsing complete and save memId into the memChain alloc-ed *(((memId_t *)dsmccDIISectPtr)-1) = memId; memId = NULL; // Reset memId, so dsmccDIISectPtr memChain will not get deleted ParseExit: if ( bits ) { // clean up the bitBuffer bitBufferDestroy( bits ); } if ( memId ) { // Incomplete parsing error, delete the dsmccDII section memChain alloc-ed memChainDestroy( memId ); dsmccDIISectPtr = NULL; } *ppDsmccDIISection = dsmccDIISectPtr; return ( err ); } /************************************************************************** * Function Name : PrintDsmccDII * * Description : Dump DsmccDII message for debugging * * Parameters : * * Return : DHL_RESULT * DHL_OK - success **************************************************************************/ void DHL_PSI_PrintDsmccDII( const DsmccDIIMsgPtr_t pDsmccDIIMsg ) { #if 1 DsmccDIIMsgPtr_t ptr = pDsmccDIIMsg; DsmccMsgHeaderPtr_t pDsmccMsgHeader; dsmccDIIAdaptHeaderPtr_t pDsmccAdaptationHeader; DS_U8* pAdaptByte; CompatblDescInfoPtr_t pCompatblDescInfo; //DS_U16 descCount; //DS_U8 subDescCount, subDescLength; //CompatblSubDescPtr_t pCompatblSubDesc; //DS_U8* pSubDescAddtlInfo; DS_U16 numberOfModules; ModuleInfoPtr_t pDIIModuleInfo; // DS_U8* pModuleInfoByte; DS_U8 moduleInfoLength; DS_U16 privateDataLength; DS_U8* pPrivateDataByte; int i, j, k; /* Argument check */ printf("\n*** DSMCC Download Info Indication Message Dump ***\n"); // Main container data structure dump printf(" table_id = 0x%02X\n", (int) ptr->table_id ); /* table_id */ printf(" dsmcc_section_length = %d\n", (int) ptr->dsmcc_section_length );/* dsmcc_section_length */ printf(" table_id_extension = %d\n", (int) ptr->table_id_extension ); /* table_id_extension */ printf(" version_number = %d\n", (int) ptr->version_number ); /* version_number */ printf(" current_next_indicator = %d\n", (int) ptr->current_next_indicator );/* current_next_indicator */ printf(" firt section_number = %d\n", (int) ptr->section_number ); /* section_number */ printf(" last_section_number = %d\n", (int) ptr->last_section_number ); /* last_section_number */ printf(" transaction_id = 0x%08lX\n", ptr->transaction_id ); /* transaction_id */ printf(" downloadId = 0x%08lX\n", ptr->downloadId ); /* downloadId */ printf(" blockSize = %d\n", (int) ptr->blockSize ); /* blockSize */ printf(" numSections = %d\n", (int) ptr->numSections ); /* numSections */ // Iterate the sections for( i = 0; i < ptr->numSections; i++ ) { // Dump the header section pDsmccMsgHeader = ptr->ptrDIIMsgSections[i].ptrDsmccMsgHeader; printf("\nDIIMsgSections[%d].DsmccMsgHeader:\n", i ); printf(" protocolDiscriminator = 0x%02X\n",(int)pDsmccMsgHeader->protocolDiscriminator ); printf(" dsmccType = 0x%02X\n",(int)pDsmccMsgHeader->dsmccType ); printf(" messageId = 0x%04X\n",(int)pDsmccMsgHeader->messageId ); printf(" transaction_id = 0x%08lX\n",pDsmccMsgHeader->transaction_id ); printf(" adaptationLength = %d\n", (int)pDsmccMsgHeader->adaptationLength ); printf(" messageLength = %d\n", (int)pDsmccMsgHeader->messageLength ); if ( pDsmccMsgHeader->adaptationLength > 0 ) { pDsmccAdaptationHeader = pDsmccMsgHeader->ptrDsmccAdaptationHeader; printf(" adaptationType = 0x%X\n", (int) pDsmccAdaptationHeader->adaptationType ); if ( pDsmccAdaptationHeader->adaptationType == 0x03 ) { printf(" DIIMsgNumber = 0x%X\n", (int) pDsmccAdaptationHeader->DIIMsgNumber ); } else { pAdaptByte = (DS_U8*)&pDsmccAdaptationHeader->DIIMsgNumber; printf(" Adaptation data bytes:"); for ( j = 0; j < pDsmccMsgHeader->adaptationLength-1; j++ ) { if ( (j % 36) == 0 ) printf("\n0x%02X ", (int) pAdaptByte[j] ); else printf("0x%02X ", (int) pAdaptByte[j] ); } } } // Dump the body section printf("DIIMsgSections[%d].downloadId = 0x%08lX\n", i, ptr->ptrDIIMsgSections[i].downloadId ); printf("DIIMsgSections[%d].blockSize = %d\n", i, (int) ptr->ptrDIIMsgSections[i].blockSize ); printf("DIIMsgSections[%d].windowSize = %d\n", i, (int) ptr->ptrDIIMsgSections[i].windowSize ); printf("DIIMsgSections[%d].ackPeriod = %d\n", i, (int) ptr->ptrDIIMsgSections[i].ackPeriod ); printf("DIIMsgSections[%d].tCDownloadWindow = %lu\n", i, ptr->ptrDIIMsgSections[i].tCDownloadWindow ); printf("DIIMsgSections[%d].tCDownloadScenario = %lu\n", i, ptr->ptrDIIMsgSections[i].tCDownloadScenario ); // Dump the compatibility descriptor section printf("\nDIIMsgSections[%d].compatblDesc:\n", i ); printf(" descLength = %d\n", (int) ptr->ptrDIIMsgSections[i].compatblDesc.descLength ); printf(" descCount = %d\n", (int) ptr->ptrDIIMsgSections[i].compatblDesc.descCount ); if ( ptr->ptrDIIMsgSections[i].compatblDesc.descCount > 0 && ptr->ptrDIIMsgSections[i].compatblDesc.compatblDescInfo.bValid ) { pCompatblDescInfo = &(ptr->ptrDIIMsgSections[i].compatblDesc.compatblDescInfo); #if 1 printf(" descriptorType = 0x%02X\n", (int) pCompatblDescInfo->descType ); printf(" descriptorLength = %d\n", (int) pCompatblDescInfo->descLength ); printf(" specifierType = 0x%02X\n", (int) pCompatblDescInfo->specifierType ); printf(" specifierType = 0x%06X (%s)\n", (int) pCompatblDescInfo->specifierData, pCompatblDescInfo->specifierData == 0x108A ? "Teralogic" : pCompatblDescInfo->specifierData == 0x1E1B ? "Digital Stream Technology" : "Unknown" ); printf(" model = 0x%04X\n", (int) pCompatblDescInfo->model ); printf(" version = 0x%04X\n", (int) pCompatblDescInfo->version ); printf(" subDescriptorCount = %d\n", (int) pCompatblDescInfo->subDescCount ); #else descCount = ptr->ptrDIIMsgSections[i].compatblDesc.descCount; for ( j = 0; j < descCount; j++ ) { printf("\n"); printf(" descriptorType = 0x%02X\n", (int) pCompatblDescInfo->descType ); printf(" descriptorLength = %d\n", (int) pCompatblDescInfo->descLength ); printf(" specifierType = 0x%02X\n", (int) pCompatblDescInfo->specifierType ); printf(" model = %d\n", (int) pCompatblDescInfo->model ); printf(" version = %d\n", (int) pCompatblDescInfo->version ); printf(" subDescriptorCount = %d\n", (int) pCompatblDescInfo->subDescCount ); if ( (subDescCount = pCompatblDescInfo[j].subDescCount) > 0 ) { pCompatblSubDesc = (CompatblSubDescPtr_t)((DS_U8*)&pCompatblDescInfo->subDescCount + 1); for ( k = 0; k < subDescCount; k++ ) { printf(" subDescriptor[%d].subDescriptorType = 0x%02X\n", k, (int) pCompatblSubDesc->subDescType ); printf(" subDescriptor[%d].subDescriptorLength = %d\n", k, (int) pCompatblSubDesc->subDescLength ); if ( (subDescLength = pCompatblSubDesc->subDescLength) > 0 ) { printf(" subDescriptor[%d].additionalInformation:\n", k); pSubDescAddtlInfo = (DS_U8*)&pCompatblSubDesc->subDescInfoByte; for ( l = 0; l < subDescLength; l++ ) { if ( (l % 36) == 0 ) printf("\n0x%02X ", (int) pSubDescAddtlInfo[l] ); else printf("0x%02X ", (int) pSubDescAddtlInfo[l] ); } } // Next compatibility subDescriptor section pCompatblSubDesc = (CompatblSubDescPtr_t)(((DS_U8*)pCompatblSubDesc) + subDescLength + 2); } } // Next compatibilityDescriptor section pCompatblDescInfo = (CompatblDescInfoPtr_t)(((DS_U8*)pCompatblDescInfo) + pCompatblDescInfo->descLength + 2); } #endif } // Dump the module info section printf("\nDIIMsgSections[%d].numberOfModules = %d\n\n", i, (int) ptr->ptrDIIMsgSections[i].numberOfModules ); if ( (numberOfModules = ptr->ptrDIIMsgSections[i].numberOfModules) > 0 ) { pDIIModuleInfo = ptr->ptrDIIMsgSections[i].ptrDIIModuleInfo; for ( j = 0; j < numberOfModules; j++ ) { printf("DIIModuleInfo[%d]: \n", j); printf(" moduleId = %d\n", (int) pDIIModuleInfo[j].moduleId ); printf(" moduleSize = %lu\n", pDIIModuleInfo[j].moduleSize ); printf(" moduleVersion = %d\n", (int) pDIIModuleInfo[j].moduleVersion ); printf(" moduleInfoLength= %d\n", (int) pDIIModuleInfo[j].moduleInfoLength ); if ( (moduleInfoLength = pDIIModuleInfo[j].moduleInfoLength) > 0 ) { printf(" module info bytes\n"); if ( pDIIModuleInfo[j].bCrcFieldValid ) printf(" CRC32: 0x%08lX\n", pDIIModuleInfo[j].Crc32_descriptor ); if ( pDIIModuleInfo[j].module_name_length ) { #ifndef CONV_TO_ASCII #define CONV_TO_ASCII(x) ( ((x) >= ' ' && (x) <= '~') ? (x) : '.' ) #endif printf(" ModuleName: "); for ( k = 0; k < pDIIModuleInfo[j].module_name_length; k++ ) { printf("%c", CONV_TO_ASCII(pDIIModuleInfo[j].ptrModuleName[k])); } printf("\n"); #undef CONV_TO_ASCII } #if 0 pModuleInfoByte = pDIIModuleInfo[j].ptrModuleInfoByte; for ( k = 0; k < moduleInfoLength; k++ ) { if ( (k % 36) == 0 ) printf("\n0x%02X ", (int) pModuleInfoByte[k] ); else printf("0x%02X ", (int) pModuleInfoByte[k] ); } #endif } } } // Dump the private data section printf("\nDIIMsgSections[%d].privateDataLength = %d\n", i, (int) ptr->ptrDIIMsgSections[i].privateDataLength ); if ( (privateDataLength = ptr->ptrDIIMsgSections[i].privateDataLength) > 0 ) { printf("DIIMsgSections[%d].privateData:\n", i); pPrivateDataByte = ptr->ptrDIIMsgSections[i].ptrPrivateDataByte; for ( j = 0; j < privateDataLength; j++ ) { if ( (j % 36) == 0 ) printf("\n0x%02X ", (int) pPrivateDataByte[j] ); else printf("0x%02X ", (int) pPrivateDataByte[j] ); } } } #endif } DHL_RESULT DHL_PSI_GetDsmccDII( DHL_PSI_HANDLE sysInfo, DS_U16 pid, DS_U16 transactionId, DsmccDIIMsgPtr_t *returnDII, int timeOut ) { void *returnPSICtl = NULL; DHL_RESULT err = DHL_OK; PSIEventProcData_t procData; int res = 0; procData.desc = NULL; procData.err = (DS_U32)DHL_OK; procData.hEvent = OS_CreateBinarySemaphore( "semDsmccDII", 0, 0 ); if (procData.hEvent == (OS_SEMAPHORE_ID)0) { printf ("DHL_PSI_GetPAT : OS_CreateBinarySemaphore() fails.\r\n"); return DHL_FAIL_OUT_OF_RESOURCE; } //DHL_RESULT DHL_PSI_MonitorDsmccDII( DHL_PSI_HANDLE sysInfo, DS_U16 Pid, DS_U16 transactionId, DsmccEventProc_t pfCallbackProc, DHL_TBL_HANDLE *returnPsiCtl ) if ((err = DHL_PSI_MonitorDsmccDII(sysInfo, pid, transactionId, 0, (DS_U32)&procData, &returnPSICtl))) { goto done; } //res = AtiCore_EventWait( procData.hEvent , _TRUE_ , timeOut ); res = OS_TakeSemaphore_Wait( procData.hEvent, timeOut ); if (res != 0) { #ifdef PSI_DBG printf("DHL_PSI_GetPMT : OS_TakeSemaphore_Wait TIMEOUT %d \r\n", timeOut); #endif //Do nothing for this. //AtiCore_EventReset( procData.hEvent ); err = DHL_FAIL_TIMEOUT; goto done2; } if ((err = (DHL_RESULT)(procData.err))) { printf("DHL_PSI_GetPMT : procData.err = %d \r\n", err ); goto done2; } *returnDII = NULL; err = DHL_PSI_ParseDsmccDII( (PSIDataArray_t *)procData.desc, returnDII ); done2: DHL_PSI_CancelDII(returnPSICtl); if( procData.desc ) DD_PSI_FreePSIData(procData.desc); done: if(procData.hEvent) { //AtiCore_EventDelete(procData.hEvent); OS_DeleteSemaphore(procData.hEvent); } return(err); } /************************************************************************** * Function Name : dsmccDDBEventProc * * Description : DII event handler * * Parameters : * * Return : * **************************************************************************/ static void dsmccDDBEventProc( PSIEvent psiEvent, DHL_TBL_HANDLE psiCtl, DS_U32 userParam ) { DHL_RESULT err = DHL_OK; DsmccMsg_t dsmccMsg; PSIDataArray_t *desc = NULL; DS_U32 DDBMonContextId = userParam; if ( pDsmccDB ) { // PSI callback should not block ////OS_TakeSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex access switch ( psiEvent ) { case psiDataReceived : { err = DD_PSI_ReadPSIData( psiCtl, &desc ); if ( err != DHL_OK || (desc == NULL) ) { printf("\ndsmccDDBEventProc: DD_PSI_ReadPSIData returned 0x%x\n",err); break; } // Dispatch the event and data received to dsmcc main thread dsmccMsg.event = eDsmccDDBDataReceived; dsmccMsg.userParam = userParam; dsmccMsg.psiCtl = psiCtl; dsmccMsg.desc = desc; OS_SendMessage( pDsmccDB->DDBMonContexts[ DDBMonContextId ].dsmccQ, (DS_U32 *)&dsmccMsg, sizeof(dsmccMsg) ); break; } default: break; } ////OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release } } /************************************************************************** * Function Name : DHL_PSI_MonitorDsmccDDB * * Description : Setup DDB message monitoring and filters * * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ static DHL_RESULT CreateDDBContext( DS_U32 downloadId, DS_U16 moduleId, DS_U8 moduleVersion, DS_U32 moduleSize, DS_U16 blockSize, DsmccEventProc_t pfCallbackProc, DsmccStatusProc_t pfStatusProc, DS_U32 *pDDBMonContextId ); DHL_RESULT InitDDBContext( DDBMsgMonContextPtr_t pDDBMsgMonContext ); static void FreeDDBContext( DS_U32 DDBMonContextId ); static DHL_RESULT InitDsmccDDBThread(DS_U32 DDBMonContextId); //static DHL_RESULT CloseDsmccDDBThread(DS_U32 DDBMonContextId); DHL_RESULT DHL_PSI_MonitorDsmccDDB( DHL_PSI_HANDLE sysInfo, DS_U16 Pid, DS_U32 downloadId, DS_U16 moduleId, DS_U8 moduleVersion, DS_U32 moduleSize, DS_U16 blockSize, DsmccEventProc_t pfCallbackProc, DsmccStatusProc_t pfStatusProc, DHL_PSI_HANDLE *returnPsiCtl ) { DHL_RESULT err = DHL_OK; PSIMask_t *pref; DS_U32 DDBMonContextId; DS_BOOL isActive; int Priority = 80; // Check if the dsmcc thread is up and running... isActive = (pDsmccDB) ? pDsmccDB->isActive : _FALSE_; if ( !isActive ) { err = DHL_PSI_ActivateDsmcc(&Priority); if ( err != DHL_OK ) { printf( "DHL_PSI_ActivateDsmcc: failure. (0x%x)\n", err ); return( DHL_FAIL_NOT_CONNECTED ); } else { isActive = (pDsmccDB) ? pDsmccDB->isActive : _FALSE_; if ( !isActive ) { printf( "CreateDIIContext: DSMCC thread is not active\n" ); return( DHL_FAIL_NOT_CONNECTED ); } } } // Check function arguments if ( (sysInfo == NULL) || (returnPsiCtl == NULL) ) { return( DHL_FAIL_NULL_POINTER ); } if ( !(moduleSize && blockSize) ) { return( DHL_FAIL_INVALID_PARAM ); } // Acquire the table data by the specified filter(s) // moduleId´Â ¾î¶»°Ô ¼³Á¤Çϳª? if ((err = DD_PSI_GetDsmccPSIMask ( &pref, tid_dsmcc_download_data_block, // DII Table ID DSMCC_MESSAGE_DDB, _TRUE_))) { return( err ); } // Create DDB monitoring context OS_TakeSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex access err = CreateDDBContext( downloadId, moduleId, moduleVersion, moduleSize, blockSize, pfCallbackProc, pfStatusProc, &DDBMonContextId ); if ( err != DHL_OK ) { OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release return( err ); } err = InitDDBContext(&pDsmccDB->DDBMonContexts[ DDBMonContextId ]); if ( err != DHL_OK ) { OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release FreeDDBContext(DDBMonContextId); return( err ); } err = InitDsmccDDBThread( DDBMonContextId ); if ( err != DHL_OK ) { OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release FreeDDBContext(DDBMonContextId); return( err ); } // Start monitoring for the dsmcc DDB section if ( (err = DD_PSI_MonitorPSIPid( sysInfo, // Transport Demux Unit Pid, // Packet ID to filter the DSM-CC DII msgs sectionMode, // Anytime a section is received psiContinuous, // Continuous mode pref, // PSI filter MAX_DSMCC_SECTION_LENGTH, // 4Kb MAX_DSMCC_SECTIONS, // MIN_DSMCC_SECTIONS, // Number of sections to be returned is 1 dsmccDDBEventProc, // DII event handler DDBMonContextId, // DDB monitor context ID returnPsiCtl ) ) ) { } if ( err == DHL_OK ) { // Save the current PSI monitor control in the monitor context pDsmccDB->DDBMonContexts[ DDBMonContextId ].psiCtl = *returnPsiCtl; } else { pDsmccDB->DDBMonContexts[ DDBMonContextId ].isUsed = _FALSE_; } OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // ==>> Mutex release return( err ); } /************************************************************************** * Function Name : DHL_PSI_CancelDDB * * Description : Cancel DDB message monitoring * * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ static void FreeDBBMemChain( DS_U32 DDBMonContextId ); static void FreeDDBContext( DS_U32 DDBMonContextId ); DHL_RESULT DHL_PSI_CancelDDB( DHL_PSI_HANDLE psiCtl ) { DHL_RESULT err=DHL_OK; DS_U32 i; for ( i = 0; i < NUM_DDB_MON_CONTEXTS; i++ ) { if ( pDsmccDB->DDBMonContexts[ i ].isUsed && pDsmccDB->DDBMonContexts[ i ].isInitialized && pDsmccDB->DDBMonContexts[ i ].psiCtl ) { if ( pDsmccDB->DDBMonContexts[ i ].psiCtl == psiCtl ) break; } } if ( i < NUM_DDB_MON_CONTEXTS ) { DHL_PSI_CancelMonitor( psiCtl ); //err = CloseDsmccDDBThread(i); if ( err != DHL_OK ) printf("%s| ERROR, LINE=%d. (0x%x)\n", __FUNCTION__, __LINE__, err); // Free the DDB module mem chain and all internal memory usage when finish FreeDBBMemChain( i ); FreeDDBContext( i ); return DHL_OK; } else { return DHL_FAIL_NOT_FOUND; } } static DDBMsgMonContext_t *DD_PSI_GetDsmccDDBContext(DHL_PSI_HANDLE psiCtl) { DS_U32 i; for ( i = 0; i < NUM_DDB_MON_CONTEXTS; i++ ) { if ( pDsmccDB->DDBMonContexts[ i ].isUsed && pDsmccDB->DDBMonContexts[ i ].isInitialized && pDsmccDB->DDBMonContexts[ i ].psiCtl ) { if ( pDsmccDB->DDBMonContexts[ i ].psiCtl == psiCtl ) break; } } if ( i < NUM_DDB_MON_CONTEXTS ) { return &pDsmccDB->DDBMonContexts[i]; } else { return (DDBMsgMonContext_t *)0; } } static DDBModule_t *DD_PSI_GetDsmccDDBModule(DHL_PSI_HANDLE psiCtl) { DS_U32 i; for ( i = 0; i < NUM_DDB_MON_CONTEXTS; i++ ) { if ( pDsmccDB->DDBMonContexts[ i ].isUsed && pDsmccDB->DDBMonContexts[ i ].isInitialized && pDsmccDB->DDBMonContexts[ i ].psiCtl ) { if ( pDsmccDB->DDBMonContexts[ i ].psiCtl == psiCtl ) break; } } if ( i < NUM_DDB_MON_CONTEXTS ) { return pDsmccDB->DDBMonContexts[i].pDDBModule; } else { return (DDBModule_t *)0; } } void *DHL_PSI_GetDsmccDDBBuffer(DHL_PSI_HANDLE psiCtl) { DDBModule_t *pDDBModule; if (psiCtl == (DHL_PSI_HANDLE)0) { printf("%s| ERROR, Null pointer is passed\n", __FUNCTION__); return (void *)0; } pDDBModule = DD_PSI_GetDsmccDDBModule(psiCtl); if ( pDDBModule == (DDBModule_t *)0 ) return (void *)0; return pDDBModule->pDDBBuffer; } void DHL_PSI_SetDsmccAllocFreeFunc(void *AllocFunc, void *FreeFunc) { g_pDsmccAllocFunc = (fnAlloc_t)AllocFunc; g_pDsmccFreeFunc = (fnFree_t)FreeFunc; } int DHL_PSI_GetDsmccDDBProgress(DHL_PSI_HANDLE psiCtl) { DDBMsgMonContext_t *pDDBCtx; int curProgress; if (psiCtl == (DHL_PSI_HANDLE)0) { printf("%s| ERROR, Null pointer is passed\n", __FUNCTION__); return -1; } pDDBCtx = DD_PSI_GetDsmccDDBContext(psiCtl); if ( pDDBCtx == (DDBMsgMonContext_t *)0 ) return -1; if (pDDBCtx->blockTotal) curProgress = (pDDBCtx->blockRecvd*100)/pDDBCtx->blockTotal; else return -1; return curProgress; } void DHL_PSI_FreeDDBBuffer(void *addr) { DSMCC_FREE(addr); } /************************************************************************** * Function Name : CreateDDBContext * * Description : This function is with "mutexSema4" protection * Allocate a memory block to store the DDB monitoring * parameters and other buffer addresses * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ static DHL_RESULT CreateDDBContext( DS_U32 downloadId, DS_U16 moduleId, DS_U8 moduleVersion, DS_U32 moduleSize, DS_U16 blockSize, DsmccEventProc_t pfCallbackProc, DsmccStatusProc_t pfStatusProc, DS_U32 *pDDBMonContextId ) { DHL_RESULT err = DHL_OK; DDBMsgMonContextPtr_t pDDBMsgMonContext; DS_U32 i; // Alloc memory block for DDB monitoring context and store all the DDB monitoring parameters // in the allocated memory block for ( i = 0; i < NUM_DDB_MON_CONTEXTS; i++ ) { if ( !pDsmccDB->DDBMonContexts[ i ].isUsed ) { break; } } if ( i >= NUM_DDB_MON_CONTEXTS ) { printf( "CreateDDBContext: Out of monitoring context\n" ); err = DHL_FAIL_OUT_OF_RESOURCE; return err; } // Initialize DDB monitoring context structure pDDBMsgMonContext = &pDsmccDB->DDBMonContexts[ i ]; memset( (DS_U8*)pDDBMsgMonContext, 0, sizeof(DDBMsgMonContext_t) ); pDDBMsgMonContext->isUsed = _TRUE_; // This context is now being used pDDBMsgMonContext->isInitialized = _FALSE_; // Buffers are not initialized pDDBMsgMonContext->downloadId = downloadId; // DDB download ID pDDBMsgMonContext->moduleId = moduleId; // DDB module ID pDDBMsgMonContext->moduleVersion = moduleVersion; // Module version pDDBMsgMonContext->moduleSize = moduleSize; // Module size pDDBMsgMonContext->blockSize = blockSize; // Module blcok size pDDBMsgMonContext->pfCallbackProc = pfCallbackProc; // Client callback func ptr pDDBMsgMonContext->pfStatusProc = pfStatusProc; // Client callback func ptr #if DSMCC_DISKFILE pDDBMsgMonContext->pFileBlockData = NULL; pDDBMsgMonContext->pFileBlockDir = NULL; pDDBMsgMonContext->fhDDBData = -1; pDDBMsgMonContext->fhDDBDir = -1; #endif *pDDBMonContextId = i; return err; } /************************************************************************** * Function Name : FreeDDBContext * * Description : Free all memory allocated for internal usage except * those allocated using memId memory chain * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ static void FreeDDBContext( DS_U32 DDBMonContextId ) { DDBMsgMonContextPtr_t pDDBMsgMonContext; if ( DDBMonContextId < NUM_DDB_MON_CONTEXTS ) { pDDBMsgMonContext = &pDsmccDB->DDBMonContexts[ DDBMonContextId ]; if ( pDDBMsgMonContext->pBlockRecvBitFlags ) free( (pDDBMsgMonContext->pBlockRecvBitFlags) ); OS_TakeSemaphore( pDsmccDB->mutexSema4 ); // Mutex access pDsmccDB->DDBMonContexts[ DDBMonContextId ].isUsed = _FALSE_; pDsmccDB->DDBMonContexts[ DDBMonContextId ].isInitialized = _FALSE_; pDsmccDB->DDBMonContexts[ DDBMonContextId ].psiCtl = NULL; OS_GiveSemaphore( pDsmccDB->mutexSema4 ); // Mutex release } } /************************************************************************** * Function Name : InitDDBContext * * Description : Allocate memory buffers for DDB msg monitoring and * initialize other variables * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ DHL_RESULT InitDDBContext( DDBMsgMonContextPtr_t pDDBMsgMonContext ) { DHL_RESULT err; DS_U16 bitFlagBytes; memId_t memId = NULL; memChainSetup_t memSetup = { (sizeof(DDBModule_t) + (DSMCC_DDB_MEM_LIMIT*256)), NULL, NULL }; err = memChainCreate( &memId, &memSetup ); if ( err ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto FailExit; } // Allocate memory for dsmcc DDB message pDDBMsgMonContext->pDDBModule = (DDBModulePtr_t)((memId_t *)(memChainAlloc(memId, sizeof(DDBModule_t) + sizeof(memId_t))) + 1); if ( pDDBMsgMonContext->pDDBModule == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; if ( pDDBMsgMonContext->pfStatusProc != NULL ) { (*pDDBMsgMonContext->pfStatusProc)( pDDBMsgMonContext->psiCtl, eDsmccDDBOutOfCPUMemory, -1 ); } goto FailExit; } //pDDBMsgMonContext->pDDBModule->pDDBBuffer = (DS_U8*)memChainAlloc(memId, pDDBMsgMonContext->moduleSize ); //pDDBMsgMonContext->pDDBModule->pDDBBuffer = (DS_U8*)GetTLPhysMemory(pDDBMsgMonContext->moduleSize, _TRUE_,displayUnit_main,0, "DMCC mem", 0); pDDBMsgMonContext->pDDBModule->pDDBBuffer = (DS_U8*)DSMCC_MALLOC(pDDBMsgMonContext->moduleSize); printf(" #### Allocated mem from Phy mem 0x%lx size = %lu \n\n\n",(DS_U32)pDDBMsgMonContext->pDDBModule->pDDBBuffer,pDDBMsgMonContext->moduleSize); if ( pDDBMsgMonContext->pDDBModule->pDDBBuffer == NULL ) { { // If unable to allocate memory for the module, return a out of memory error err = DHL_FAIL_OUT_OF_RESOURCE; goto FailExit; } } else { pDDBMsgMonContext->pDDBModule->dataType = eDDBMemData; // Memory buffering mode } // Calculate the total number of blocks to allocate block-received bit flag buffer // For a 256MB module the buffer size is about 64K (256/4 * 1024) pDDBMsgMonContext->blockTotal = pDDBMsgMonContext->moduleSize / (DS_U32)pDDBMsgMonContext->blockSize; pDDBMsgMonContext->lastBlockSize = pDDBMsgMonContext->moduleSize % (DS_U32)pDDBMsgMonContext->blockSize; if ( pDDBMsgMonContext->lastBlockSize ) pDDBMsgMonContext->blockTotal++; // Calculate the number of bytes required to hold the blocks' bit flags bitFlagBytes = pDDBMsgMonContext->blockTotal / 8; if ( pDDBMsgMonContext->blockTotal % 8 ) bitFlagBytes++; // Allocate the bit flags and clear all the flags pDDBMsgMonContext->pBlockRecvBitFlags = (DS_U8 *)malloc( bitFlagBytes ); if ( pDDBMsgMonContext->pBlockRecvBitFlags == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto FailExit; } memset( (DS_U8*)pDDBMsgMonContext->pBlockRecvBitFlags, 0, bitFlagBytes ); // At this point everything is setup and good to go! pDDBMsgMonContext->memId = memId; pDDBMsgMonContext->blockRecvd = 0; pDDBMsgMonContext->pDDBModule->moduleId = pDDBMsgMonContext->moduleId; pDDBMsgMonContext->pDDBModule->moduleVersion = pDDBMsgMonContext->moduleVersion; pDDBMsgMonContext->pDDBModule->moduleSize = pDDBMsgMonContext->moduleSize; pDDBMsgMonContext->pDDBModule->blockTotal = pDDBMsgMonContext->blockTotal; pDDBMsgMonContext->pDDBModule->blockSize = pDDBMsgMonContext->blockSize; pDDBMsgMonContext->isInitialized = _TRUE_; // Set the initialized flag to _TRUE_ // Save memId into the memChain alloc-ed *(((memId_t *)(pDDBMsgMonContext->pDDBModule))-1) = memId; memId = NULL; // Reset memId so its memChain won't get destroyed #if DSMCC_DEBUG printf( "DDBContext initialized: blockTotal = %d lastBlockSize = %d\n", pDDBMsgMonContext->blockTotal, (DS_U32)pDDBMsgMonContext->lastBlockSize ); #endif FailExit: if ( memId ) { memChainDestroy( memId ); } return ( err ); } /************************************************************************** * Function Name : FreeDBBMemChain * * Description : Free all memory allocated for internal usage except * those allocated using memId memory chain * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ static void FreeDBBMemChain( DS_U32 DDBMonContextId ) { DDBMsgMonContextPtr_t pDDBMsgMonContext; if ( DDBMonContextId < NUM_DDB_MON_CONTEXTS ) { pDDBMsgMonContext = &pDsmccDB->DDBMonContexts[ DDBMonContextId ]; if ( pDDBMsgMonContext->pDDBModule != NULL ) memChainDestroy( pDDBMsgMonContext->memId ); } } /************************************************************************** * Function Name : ParseDsmccDDB * * Description : Parse the entire DSMCC DDB message and return the parsed * data * Notice: DDB monitoring should operate in section mode only * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ DHL_RESULT ParseDsmccDDB( PSIDataArray_t *desc, DS_U16 LastBlockNum, DS_U16 BlockSize, DS_U16 LastBlockSize, DsmccDDBMsgPtr_t *ppDsmccDDBMsg ) { DHL_RESULT err = DHL_OK; DS_U8 *section; memId_t memId = NULL; memChainSetup_t memSetup = { DSMCC_DDB_MEM_LIMIT , NULL, NULL }; DS_U8 table_id; DS_U16 dsmcc_section_length; bitBufferPtr_t bits = NULL; DDBMsgPtr_t pDDBMsgSection; // DDB msg section DsmccDnldDataHdrPtr_t pDsmccDnldDataHdr; // Dsmcc Download Data Header // DS_U8* spBlockDataByte; // DDB msg payload DS_U8 *dpData; DS_U16 BlockDataSize; DS_U16 i; DS_U8 numSections; if ( (desc == NULL) || (ppDsmccDDBMsg == NULL) ) { return( DHL_FAIL_NULL_POINTER ); } // section pointer to DSMCC-encapsulated DDB table data sections // numSections = desc->numSections; section = desc->sectPtr[0] ; // Do sanity check if ( (numSections != 1) || (section == NULL) ) { return ( DHL_FAIL_INVALID_PARAM ); } // Create memory chain err = memChainCreate( &memId, &memSetup ); if ( err ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Allocate memory for DsmccDDB structure for the client *ppDsmccDDBMsg = (DsmccDDBMsgPtr_t)((memId_t *)(memChainAlloc(memId, sizeof(DsmccDDBMsg_t) + sizeof(memId_t))) + 1); if (*ppDsmccDDBMsg == NULL) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Allocate the memory to hold the DDB msg section (*ppDsmccDDBMsg)->ptrDDBMsgSection = (DDBMsgPtr_t)memChainAlloc(memId, sizeof(DDBMsg_t)); if ( (*ppDsmccDDBMsg)->ptrDDBMsgSection == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } #if DSMCC_DEBUG printf("\n*** ParseDsmccDDBSection: Start parsing (%d) section(s) ***\n", (DS_U32)numSections); #endif // Perform DSM-CC DDB section data validation // Get table_id table_id = get_table_id(section); if ( table_id != DSMCC_DDB_TABLE_ID ) { printf("ParseDsmccDDBSection: invalid table_id = %0x\n", (int)table_id); err = DHL_FAIL_NULL_POINTER; goto ParseExit; } // Get syntax indicator: 1 = valid if (get_section_syntax_indicator(section) != 1) { printf("ParseDsmccDDBSection: section_syntax_indicator not set\n"); err = DHL_FAIL_NULL_POINTER; goto ParseExit; } // Get section length dsmcc_section_length = get_section_length(section); if ( dsmcc_section_length > (MAX_DSMCC_SECTION_LENGTH - 3) ) { printf("ParseDsmccDDBSection: invalid section_length = %0d\n", (int)dsmcc_section_length); err = DHL_FAIL_NULL_POINTER; goto ParseExit; } // Create the bitBuffer object and initialize it with the current section data err = bitBufferCreate( &bits, section + 3, dsmcc_section_length ); if ( err != DHL_OK ) { printf( "ParseDsmccDDBSection::bitBufferCreate failed --> (0x%x)\n", err ); goto ParseExit; } // Parse the section and fill the DSM-CC DDB section data structure // #if DSMCC_DEBUG printf("ParseDsmccDDBSection: Fill DDB section data structure\n"); #endif (*ppDsmccDDBMsg)->table_id = table_id; (*ppDsmccDDBMsg)->dsmcc_section_length = dsmcc_section_length; (*ppDsmccDDBMsg)->table_id_extension = bitBufferGetBits(bits, 16); // Module ID bitBufferSkipBits( bits, 2 ); // Reserved (*ppDsmccDDBMsg)->version_number = bitBufferGetBits(bits, 5); // version number (*ppDsmccDDBMsg)->current_next_indicator = bitBufferGetBits(bits, 1); // current next indicator if ( (*ppDsmccDDBMsg)->current_next_indicator != 1 ) { printf("ParseDsmccDDBSection: current_next_indicator not set\n"); err = DHL_FAIL_NULL_POINTER; goto ParseExit; } (*ppDsmccDDBMsg)->section_number = bitBufferGetBits(bits, 8); // section_number (*ppDsmccDDBMsg)->last_section_number = bitBufferGetBits(bits, 8); // last_section_number #if DSMCC_DEBUG printf("ParseDsmccDDBSection: table_id = 0x%02x\n",(DS_U32)(*ppDsmccDDBMsg)->table_id ); printf("ParseDsmccDDBSection: dsmcc_section_length = %d\n", (DS_U32) (*ppDsmccDDBMsg)->dsmcc_section_length ); printf("ParseDsmccDDBSection: table_id_extension = 0x%04x\n", (DS_U32)(*ppDsmccDDBMsg)->table_id_extension ); printf("ParseDsmccDDBSection: version_number = %d\n", (DS_U32) (*ppDsmccDDBMsg)->version_number ); printf("ParseDsmccDDBSection: current_next_indicator = 0x%02x\n", (DS_U32)(*ppDsmccDDBMsg)->current_next_indicator ); printf("ParseDsmccDDBSection: section_number = %d\n", (DS_U32)(*ppDsmccDDBMsg)->section_number ); printf("ParseDsmccDDBSection: last_section_number = %d\n", (DS_U32) (*ppDsmccDDBMsg)->last_section_number ); #endif // Parse the DDB section and fill the DDB section data structure // // Initialize destination pointer to DDB message section pDDBMsgSection = (*ppDsmccDDBMsg)->ptrDDBMsgSection; pDDBMsgSection->ptrDsmccDnldDataHdr = (DsmccDnldDataHdrPtr_t)memChainAlloc( memId, sizeof(DsmccDnldDataHdr_t) ); if ( pDDBMsgSection->ptrDsmccDnldDataHdr == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Parse DDB dsmcc download data header and assign them to the section header data structure pDsmccDnldDataHdr = pDDBMsgSection->ptrDsmccDnldDataHdr; pDsmccDnldDataHdr->protocolDiscriminator = bitBufferGetBits(bits, 8); if ( pDsmccDnldDataHdr->protocolDiscriminator != 0x11 ) { printf("ParseDsmccDDBSection: Invalid protocolDiscriminator = %0x\n", (int) pDsmccDnldDataHdr->protocolDiscriminator); err = DHL_FAIL_NULL_POINTER; goto ParseExit; } pDsmccDnldDataHdr->dsmccType = bitBufferGetBits(bits, 8); if ( pDsmccDnldDataHdr->dsmccType != 0x03 ) { printf("ParseDsmccDDBSection: Invalid dsmccType = %0x\n", (int)pDsmccDnldDataHdr->dsmccType); err = DHL_FAIL_NULL_POINTER; goto ParseExit; } pDsmccDnldDataHdr->messageId = bitBufferGetBits(bits, 16); if ( pDsmccDnldDataHdr->messageId != 0x1003 ) { printf("ParseDsmccDDBSection: Invalid messageId = %0x\n", (int)pDsmccDnldDataHdr->messageId); err = DHL_FAIL_NULL_POINTER; goto ParseExit; } pDsmccDnldDataHdr->downloadId = bitBufferGetBits(bits, 32); bitBufferSkipBits( bits, 8 ); // Reserved pDsmccDnldDataHdr->adaptationLength = bitBufferGetBits(bits, 8); pDsmccDnldDataHdr->messageLength = bitBufferGetBits(bits, 16); if ( pDsmccDnldDataHdr->adaptationLength > 0 ) { pDsmccDnldDataHdr->ptrDsmccAdaptationHeader = (dsmccDDBAdaptHeaderPtr_t)memChainAlloc( memId, pDsmccDnldDataHdr->adaptationLength ); if ( pDsmccDnldDataHdr->ptrDsmccAdaptationHeader == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Copy the entire adaptation header block dpData = (DS_U8*)pDsmccDnldDataHdr->ptrDsmccAdaptationHeader; for ( i = 0; i < pDsmccDnldDataHdr->adaptationLength; i++ ) dpData[i] = bitBufferGetBits(bits, 8); } else { pDsmccDnldDataHdr->ptrDsmccAdaptationHeader = NULL; } // Parse DDB msg body section and assign them to the proper data structure pDDBMsgSection->moduleId = bitBufferGetBits(bits, 16); pDDBMsgSection->moduleVersion = bitBufferGetBits(bits, 8); bitBufferSkipBits( bits, 8 ); // Reserved pDDBMsgSection->blockNumber = bitBufferGetBits(bits, 16); if ( pDDBMsgSection->blockNumber == LastBlockNum ) BlockDataSize = LastBlockSize; else BlockDataSize = BlockSize; pDDBMsgSection->pBlockDataByte = (DS_U8*)memChainAlloc( memId, BlockDataSize ); if ( pDDBMsgSection->pBlockDataByte == NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto ParseExit; } // Copy the entire DDB payload data block for ( i = 0; i < BlockDataSize; i++ ) { pDDBMsgSection->pBlockDataByte[i] = bitBufferGetBits(bits, 8); } #if DSMCC_DEBUG printf("ParseDsmccDDBSection: protocolDiscriminator = 0x%02X\n", (DS_U32)pDsmccDnldDataHdr->protocolDiscriminator ); printf("ParseDsmccDDBSection: dsmccType = 0x%02X\n", (DS_U32)pDsmccDnldDataHdr->dsmccType ); printf("ParseDsmccDDBSection: messageId = 0x%04X\n", (DS_U32)pDsmccDnldDataHdr->messageId ); printf("ParseDsmccDDBSection: downloadId = 0x%08X\n", (DS_U32)pDsmccDnldDataHdr->downloadId ); printf("ParseDsmccDDBSection: adaptationLength = %d\n", (DS_U32) pDsmccDnldDataHdr->adaptationLength ); printf("ParseDsmccDDBSection: messageLength = %d\n", (DS_U32) pDsmccDnldDataHdr->messageLength ); printf("ParseDsmccDDBSection: moduleId = %d\n", (DS_U32) pDDBMsgSection->moduleId ); printf("ParseDsmccDDBSection: moduleVersion = %d\n", (DS_U32) pDDBMsgSection->moduleVersion ); printf("ParseDsmccDDBSection: blockNumber = %d\n", (DS_U32) pDDBMsgSection->blockNumber ); printf("ParseDsmccDDBSection: BlockDataSize = %d\n", (DS_U32) BlockDataSize ); #endif // Parsing/copying is complete, save memId into the memChain alloc-ed *(((memId_t *)(*ppDsmccDDBMsg))-1) = memId; memId = NULL; // Reset memId so its memChain won't get destroyed ParseExit: if ( bits ) { // clean up the bitBuffer bitBufferDestroy( bits ); } if ( memId ) { memChainDestroy( memId ); *ppDsmccDDBMsg = NULL; } return ( err ); } /************************************************************************** * Function Name : DDBSectionRecvd * * Description : Check for existing block * * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ DS_BOOL DDBSectionRecvd( DDBMsgMonContextPtr_t pDDBMsgMonContext, DS_U16 blockNumber ) { DS_U32 byteOffset = blockNumber / 8; DS_U8 bitFlagIdx = blockNumber % 8; DS_U8 *pBitFlags; if ( pDDBMsgMonContext && (pDDBMsgMonContext->pBlockRecvBitFlags) ) { pBitFlags = (DS_U8*)pDDBMsgMonContext->pBlockRecvBitFlags + byteOffset; return( ((*pBitFlags) & XltIdx2Bit[ bitFlagIdx ]) ? _TRUE_ : _FALSE_ ); } return _FALSE_; } /************************************************************************** * Function Name : ProcessDDBSection * * Description : * * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ eDSMCCRetval_t ProcessDDBSection( DDBMsgMonContextPtr_t pDDBMsgMonContext, DDBMsgPtr_t pDDBMsgSection ) { DS_U32 byteOffset; DS_U16 blockSize; DS_U8 bitFlagIdx; DS_U8 *pBitFlags; DS_U8 *pModuleBlock; // DS_U16 rcvBlockIdx; // Memory buffering mode if ( pDDBMsgMonContext->pDDBModule->dataType == eDDBMemData ) { #if 1//DSMCC_DEBUG printf( "ProcessDsmccDDB: DDB Section #%ld Total blocks: %ld\n", (DS_U32)pDDBMsgSection->blockNumber, pDDBMsgMonContext->blockTotal ); #endif byteOffset = pDDBMsgSection->blockNumber * pDDBMsgMonContext->blockSize; // Check for any bound error if ( byteOffset < pDDBMsgMonContext->moduleSize ) { pModuleBlock = (DS_U8*)pDDBMsgMonContext->pDDBModule->pDDBBuffer + byteOffset; // Check if this is the last block if ( pDDBMsgSection->blockNumber == (pDDBMsgMonContext->blockTotal-1) ) blockSize = pDDBMsgMonContext->lastBlockSize; else blockSize = pDDBMsgMonContext->blockSize; // Copy the data block into its correct spot memcpy( pModuleBlock, pDDBMsgSection->pBlockDataByte, blockSize ); // Set the bit flag for this block number byteOffset = pDDBMsgSection->blockNumber / 8; bitFlagIdx = pDDBMsgSection->blockNumber % 8; pBitFlags = (DS_U8*)pDDBMsgMonContext->pBlockRecvBitFlags + byteOffset; (*pBitFlags) |= XltIdx2Bit[ bitFlagIdx ]; } else { return eDsmccDDBMemOutOfBound; } } #if DSMCC_DISKFILE else // Diskfile buffering mode { rcvBlockIdx = pDDBMsgMonContext->recvdBlockIndex++; byteOffset = rcvBlockIdx * pDDBMsgMonContext->blockSize; pModuleBlock = (DS_U8*)pDDBMsgMonContext->pFileBlockData + byteOffset; // Check if this is the last block if ( pDDBMsgSection->blockNumber == (pDDBMsgMonContext->blockTotal-1) ) blockSize = pDDBMsgMonContext->lastBlockSize; else blockSize = pDDBMsgMonContext->blockSize; // Copy the data block into the current buffer empty slot memcpy( pModuleBlock, pDDBMsgSection->pBlockDataByte, blockSize ); // Set the corresponding block number and index pDDBMsgMonContext->pFileBlockDir[ rcvBlockIdx ].blockNumber = pDDBMsgSection->blockNumber; pDDBMsgMonContext->pFileBlockDir[ rcvBlockIdx ].blockIndex = (DS_U16)pDDBMsgMonContext->blockRecvd; // Set the bit flag for this block number byteOffset = pDDBMsgSection->blockNumber / 8; bitFlagIdx = pDDBMsgSection->blockNumber % 8; pBitFlags = (DS_U8*)pDDBMsgMonContext->pBlockRecvBitFlags + byteOffset; (*pBitFlags) |= XltIdx2Bit[ bitFlagIdx ]; // If buffers are filled up, write out the data into diskfiles if ( pDDBMsgMonContext->recvdBlockIndex >= DSMCC_FILE_BUFSECTIONS ) { WriteDDBCaptureFiles( pDDBMsgMonContext, pDDBMsgMonContext->recvdBlockIndex ); pDDBMsgMonContext->recvdBlockIndex = 0; // Reset receive block index } } #endif return eDsmccDDBBlockRecvd; } /************************************************************************** * Function Name : ProcessDsmccDDB * * Description : Parse and process DSMCC DDB message received * * Parameters : * * Return : DHL_RESULT * noErrror - success **************************************************************************/ eDSMCCRetval_t ProcessDsmccDDB( PSIDataArray_t *desc, DDBMsgMonContextPtr_t pDDBMsgMonContext, DDBModulePtr_t *ppDDBModule ) { DHL_RESULT err; // DS_U16 BlockDataSize; DsmccDDBMsgPtr_t pDsmccDDBMsg; DDBMsgPtr_t pDDBMsgSection; DsmccDnldDataHdrPtr_t pDsmccDnldDataHdr; eDSMCCRetval_t retVal; // Set DDB module return ptr to NULL (*ppDDBModule) = NULL; // Check if DDB monitor context has been setup if ( !pDDBMsgMonContext->isInitialized ) { err = InitDDBContext( pDDBMsgMonContext ); if ( err != DHL_OK ) { return ( eDsmccDDBInitContextFail ); } } // Parse the DDB message received err = ParseDsmccDDB( desc, pDDBMsgMonContext->blockTotal-1, pDDBMsgMonContext->blockSize, pDDBMsgMonContext->lastBlockSize, &pDsmccDDBMsg ); if ( err != DHL_OK ) { if ( err == DHL_FAIL_OUT_OF_RESOURCE ) { return( eDsmccDDBOutOfCPUMemory ); } } if ( pDsmccDDBMsg == NULL ) { printf( "ProcessDsmccDDB::pDsmccDDBMsg == NULL\n" ); return ( eDsmccDDBParseError ); } // Check and validate module information pDDBMsgSection = pDsmccDDBMsg->ptrDDBMsgSection; pDsmccDnldDataHdr = pDDBMsgSection->ptrDsmccDnldDataHdr; // Check and compare download ID if ( pDDBMsgMonContext->downloadId != pDsmccDnldDataHdr->downloadId ) { //printf( "ProcessDsmccDDB: Mismatched downloadId ( cur = %lu rcv = %lu )\n", pDDBMsgMonContext->downloadId, pDsmccDnldDataHdr->downloadId ); FreeDsmccMemChain( pDsmccDDBMsg ); return ( eDsmccDDBWrongDownloadId ); } // Check and compare module ID if ( pDDBMsgMonContext->moduleId != pDDBMsgSection->moduleId ) { printf( "ProcessDsmccDDB: Mismatched moduleId ( cur = %d rcv = %d )\n", (int) pDDBMsgMonContext->moduleId, (int) pDDBMsgSection->moduleId ); FreeDsmccMemChain( pDsmccDDBMsg ); return ( eDsmccDDBWrongModuleId ); } // Check and compare module version, if different should we flush the entire section received? if ( pDDBMsgMonContext->moduleVersion != pDDBMsgSection->moduleVersion ) { printf( "ProcessDsmccDDB: Mismatched version ( cur = %d rcv = %d\n", (int) pDDBMsgMonContext->moduleVersion, (int) pDDBMsgSection->moduleVersion ); FreeDsmccMemChain( pDsmccDDBMsg ); return ( eDsmccDDBWrongVersion ); } // Check for valid block number if ( pDDBMsgSection->blockNumber >= pDDBMsgMonContext->blockTotal ) { printf( "ProcessDsmccDDB: Invalid block number = %d block total = %d\n", (int) pDDBMsgSection->blockNumber, (int) pDDBMsgMonContext->blockTotal ); FreeDsmccMemChain( pDsmccDDBMsg ); return ( eDsmccDDBInvalidBlockNum ); } // Check if this block has been received before if ( DDBSectionRecvd(pDDBMsgMonContext, pDDBMsgSection->blockNumber) ) { ////printf( "ProcessDsmccDDB: DDB Section #%d has been received\n", pDDBMsgSection->blockNumber ); FreeDsmccMemChain( pDsmccDDBMsg ); return ( eDsmccDDBBlockRecvd ); } // Process and saved the block received retVal = ProcessDDBSection( pDDBMsgMonContext, pDsmccDDBMsg->ptrDDBMsgSection ); // Free the parsed DDB msg mem chain FreeDsmccMemChain( pDsmccDDBMsg ); if ( retVal == eDsmccDDBBlockRecvd ) { // Update the DDB monitor variables pDDBMsgMonContext->blockRecvd++; if ( pDDBMsgMonContext->pfStatusProc != NULL ) { (*pDDBMsgMonContext->pfStatusProc)( pDDBMsgMonContext->psiCtl, eDsmccDDBBlockRecvd, pDDBMsgMonContext->blockRecvd ); } // Check if all the DDB message sections have been received and // return the complete module to the client if ( pDDBMsgMonContext->blockRecvd >= pDDBMsgMonContext->blockTotal ) { #if DSMCC_DISKFILE if ( pDDBMsgMonContext->pDDBModule->dataType == eDDBFileData ) { WriteDDBCaptureFiles( pDDBMsgMonContext, pDDBMsgMonContext->recvdBlockIndex ); CloseDDBCaptureFiles( pDDBMsgMonContext ); } #endif (*ppDDBModule) = pDDBMsgMonContext->pDDBModule; return( eDsmccDDBTableIsComplete ); } } // DDB message section has been received and saved return ( retVal ); } void DsmccDDBTask( DS_U32 DDBMonContextId ) { DHL_RESULT err = DHL_OK; DsmccMsg_t dsmccMsg; PSIDataArray_t *desc; DS_U32 len/*, i*/; DsmccEventProc_t dsmccClientProc; DDBMsgMonContextPtr_t pDDBMsgMonContext; DDBModulePtr_t pDDBModule; eDSMCCRetval_t retVal; int processDsmccDDBData = _TRUE_; if ( DDBMonContextId >= NUM_DDB_MON_CONTEXTS ) { printf("%s:%d| Invalid DDBMonContextId, terminate DsmccDDBTask.\n", __FUNCTION__, __LINE__); return; } //printf("%s::Is Entering... DDBMonContextId=%ld\n", __FUNCTION__, DDBMonContextId); while( _TRUE_ ) { pDDBMsgMonContext = &pDsmccDB->DDBMonContexts[ DDBMonContextId ]; if ( pDDBMsgMonContext->isUsed != _TRUE_ ) printf("%s:%d| WARNING: MsgMonContext is used with isUsed = 0\n", __FUNCTION__, __LINE__); //OS_Delay(100); err = (DHL_RESULT)OS_ReceiveMessage(pDDBMsgMonContext->dsmccQ, (DS_U32 *)&dsmccMsg, sizeof(DsmccMsg_t), &len); if ( err != OS_OK ) { printf("Receive Message returned %d\n", err); } else { switch (dsmccMsg.event) { case eDsmccActivate : //printf("%s::Is Running... DDBMonContextId=%ld\n", __FUNCTION__, DDBMonContextId); /* Just for sanity check */ if ( pDDBMsgMonContext->isUsed != _TRUE_ ) printf("%s::ERROR! DDB Context is not initialized, but try to use this!\n", __FUNCTION__); OS_GiveSemaphore( pDsmccDB->DDBMonContexts[ DDBMonContextId ].syncSema4 ); // Signal that we're up and running break; case eDsmccDeactivate : #if DSMCC_DEBUG printf("%s::Is Shutting down...\n", __FUNCTION__); #endif //DHL_PSI_CancelAllDsmccMonitors(); // Terminate all active monitors #if 0 if( pDDBModule->pDDBBuffer != NULL) { DSMCC_FREE(pDDBModule->pDDBBuffer); //FreeTLPhysMemory(pDDBModule->pDDBBuffer); pDDBModule->pDDBBuffer = NULL; } #endif OS_GiveSemaphore( pDsmccDB->DDBMonContexts[ DDBMonContextId ].syncSema4 ); // Signal that we're shutting down OS_SelfDeleteTask(); return; case eDsmccDDBDataReceived : if (processDsmccDDBData == _FALSE_) { /* spurious response in the queue. ignore */ /* There is a memory leak here for PSI data. */ break; } // Get the DDB data desc = dsmccMsg.desc; // Get the DDB Monitor Context DDBMonContextId = dsmccMsg.userParam; // Verify the monitoring parameter if ( DDBMonContextId < NUM_DDB_MON_CONTEXTS ) { pDDBMsgMonContext = &pDsmccDB->DDBMonContexts[ DDBMonContextId ]; #if DSMCC_DEBUG printf("%s::ProcessDsmccDDB: eDsmccDDBDataReceived\n", __FUNCTION__); #endif retVal = ProcessDsmccDDB( desc, pDDBMsgMonContext, &pDDBModule ); // If the DDB module is ready, invoke the client's callback function // and pass the complete DDB module image if ( retVal == eDsmccDDBTableIsComplete ) { dsmccClientProc = pDDBMsgMonContext->pfCallbackProc; if ( dsmccClientProc != NULL ) { // Client must call: FreeDsmccMemChain(pDDBModule) (*dsmccClientProc)( pDDBMsgMonContext->psiCtl, (void *)pDDBModule ); } else { FreeDBBMemChain( DDBMonContextId ); } // Free the parsed DDB module and all internal memory usage when finish DHL_PSI_CancelMonitor( dsmccMsg.psiCtl ); //FreeDDBContext( DDBMonContextId ); /* ignore all further spurious responses in the queue */ processDsmccDDBData = _FALSE_; } else { #if DSMCC_DEBUG // Do other processing necessary as the retVal indicates printf("%s::ProcessDsmccDDB: retVal = %d\n", __FUNCTION__, retVal); #endif if ( pDDBMsgMonContext->pfStatusProc != NULL ) { (*pDDBMsgMonContext->pfStatusProc)( pDDBMsgMonContext->psiCtl, retVal, -1 ); } // If the return value is out of CPU memory maybe we should terminate the // DDB monitoring at this point if ( retVal == eDsmccDDBOutOfCPUMemory ) { printf("%s::ProcessDsmccDDB: Out of CPU memory\n", __FUNCTION__); DHL_PSI_CancelMonitor( dsmccMsg.psiCtl ); // Free the DDB module mem chain and all internal memory usage when finish FreeDBBMemChain( DDBMonContextId ); FreeDDBContext( DDBMonContextId ); /* ignore all further spurious responses in the queue */ processDsmccDDBData = _FALSE_; } } } else { // Invalid DDB monitor parameter block, abort this DDB monitoring printf("%s::Invalid DDBMsgMonContext: abort the DDB monitoring...\n", __FUNCTION__); DHL_PSI_CancelMonitor( dsmccMsg.psiCtl ); /* ignore all further spurious responses in the queue */ processDsmccDDBData = _FALSE_; // DDB monitor context is corrupted but we don't know if this is a valid context ptr // if ( pDDBMsgMonContext && pDDBMsgMonContext->memId ) // { // memChainDestroy( pDDBMsgMonContext->memId ); // } // FreeDDBContext( DDBMonContextId ); // Free all internal memory usage when finish } DD_PSI_FreePSIData( desc ); break; default: break; } } } } static DHL_RESULT InitDsmccDDBThread(DS_U32 DDBMonContextId) { DHL_RESULT err = DHL_OK; OS_MESSAGEQUEUE_ID dsmccQ = (OS_MESSAGEQUEUE_ID)NULL; DsmccMsg_t dsmccMsg; OS_TASK_ID dsmccTaskID = (OS_TASK_ID)0; OS_MUTEX_ID syncSema4 = (OS_MUTEX_ID)NULL; if ( !(pDsmccDB->DDBMonContexts[ DDBMonContextId ].dsmccTaskID) ) { /* Create the DSMCC thread Message Q */ dsmccQ = OS_CreateMessageQueue("dsmccQ",0,30, sizeof(DsmccMsg_t) ); if ( dsmccQ == (OS_MESSAGEQUEUE_ID)NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto doneError; } /* Create Event Sema4 */ syncSema4 = OS_CreateBinarySemaphore("dsmccSyncSema4", 0, _FALSE_); if ( syncSema4 == (OS_SEMAPHORE_ID)NULL ) { err = DHL_FAIL_OUT_OF_RESOURCE; goto doneError; } /* Spawn the DSMCC thread */ dsmccTaskID = OS_SpawnTask( (OS_TASKFUNCTION)DsmccDDBTask, "tDsmccDDBTask", DSMCCDDB_TASK_PRIO, 16*1024, (DS_S32)DDBMonContextId); if (dsmccTaskID == (OS_TASK_ID)NULL) { err = DHL_FAIL_OUT_OF_RESOURCE; goto doneError; } pDsmccDB->DDBMonContexts[ DDBMonContextId ].dsmccQ = dsmccQ; pDsmccDB->DDBMonContexts[ DDBMonContextId ].dsmccTaskID = dsmccTaskID; pDsmccDB->DDBMonContexts[ DDBMonContextId ].syncSema4 = syncSema4; } /* Synchronize with the thread launched */ dsmccMsg.event = eDsmccActivate; dsmccMsg.param = (void *)pDsmccDB; OS_SendMessage(pDsmccDB->DDBMonContexts[ DDBMonContextId ].dsmccQ, (DS_U32 *)&dsmccMsg, sizeof(DsmccMsg_t)); OS_TakeSemaphore(pDsmccDB->DDBMonContexts[ DDBMonContextId ].syncSema4); return err; doneError: if (err != DHL_OK) printf("%s| failure. (0x%x)\n", __FUNCTION__, err); return err; } #if 0 static DHL_RESULT CloseDsmccDDBThread(DS_U32 DDBMonContextId) { DsmccMsg_t dsmccMsg; if ( pDsmccDB && pDsmccDB->DDBMonContexts[ DDBMonContextId ].isUsed ) { dsmccMsg.event = eDsmccDeactivate; fprintf(stderr, "|%s:%d|\n", __FUNCTION__, __LINE__); OS_SendMessage(pDsmccDB->DDBMonContexts[ DDBMonContextId ].dsmccQ, (DS_U32 *)&dsmccMsg, sizeof(DsmccMsg_t)); fprintf(stderr, "|%s:%d|\n", __FUNCTION__, __LINE__); OS_TakeSemaphore(pDsmccDB->DDBMonContexts[ DDBMonContextId ].syncSema4); fprintf(stderr, "|%s:%d|\n", __FUNCTION__, __LINE__); //OS_DeleteSemaphore(pDsmccDB->DDBMonContexts[ DDBMonContextId ].syncSema4); fprintf(stderr, "|%s:%d|\n", __FUNCTION__, __LINE__); //OS_DeleteMessageQueue(pDsmccDB->DDBMonContexts[ DDBMonContextId ].dsmccQ); fprintf(stderr, "|%s:%d|\n", __FUNCTION__, __LINE__); } else { printf("%s| WARNING: DDB Thread %ld is already closed.\n", __FUNCTION__, DDBMonContextId); } return DHL_OK; } #endif #if 0 ___DEBUG_FUNCTION__() #endif void hpsi_test_dii(int pid, int timeOut) { DHL_RESULT dhlResult = DHL_OK; DsmccDIIMsgPtr_t DsmccDIIMsg; dhlResult = DHL_PSI_GetDsmccDII( gPsiHandle, pid, 0, &DsmccDIIMsg, timeOut ? timeOut : 500 ); if ( dhlResult != DHL_OK ) { printf("%s| DHL_PSI_GetDsmccDII() returns with 0x%x\n", __FUNCTION__, dhlResult); return; } DHL_PSI_PrintDsmccDII( DsmccDIIMsg ); FreeDsmccMemChain( DsmccDIIMsg); } static DS_U32 startTick=0; void DdbCallback( DHL_PSI_HANDLE *psiCtl, void *pDdbData ) { printf("Elapsed Time = %ld.%ld sec\n", (OS_GetTickCount()-startTick) / 100, (OS_GetTickCount()-startTick) % 100 ); } static int dsmccDdbErr = 0; void DdbStatus( DHL_PSI_HANDLE *psiCtl, eDSMCCRetval_t dsmccRetval, DS_U32 blkRcv ) { int curProgress; static int oldProgress = -1; switch(dsmccRetval) { case eDsmccDDBInitContextFail: printf("DDB Status: eDsmccDDBInitContextFail\n"); break; case eDsmccDDBOutOfCPUMemory: printf("DDB Status: eDsmccDDBOutOfCPUMemory\n"); dsmccDdbErr = 1; break; case eDsmccDDBParseError: printf("DDB Status: eDsmccDDBParseError\n"); dsmccDdbErr = 1; break; case eDsmccDDBWrongDownloadId: //printf("DDB Status: eDsmccDDBWrongDownloadId\n"); break; case eDsmccDDBWrongModuleId: printf("DDB Status: eDsmccDDBWrongModuleId\n"); break; case eDsmccDDBWrongVersion: printf("DDB Status: eDsmccDDBWrongVersion\n"); break; case eDsmccDDBInvalidBlockNum: printf("DDB Status: eDsmccDDBInvalidBlockNum\n"); dsmccDdbErr = 1; break; case eDsmccDDBMemOutOfBound: printf("DDB Status: eDsmccDDBMemOutOfBound\n"); dsmccDdbErr = 1; break; case eDsmccDDBTableIsComplete: case eDsmccDDBBlockRecvd: curProgress = DHL_PSI_GetDsmccDDBProgress( psiCtl ); if ( oldProgress != curProgress ) printf("Progress: %d\n", curProgress); oldProgress = curProgress; break; default: printf("DDB Status: spurious DSMCC return value %d\n", dsmccRetval); } } void hpsi_test_ddb(int pid, int dId, int mId, int mVer, int moduleSize, int blockSize, int timeOut) { DHL_RESULT dhlResult = DHL_OK; void *returnPSICtl = NULL; startTick = OS_GetTickCount(); dhlResult = DHL_PSI_MonitorDsmccDDB( gPsiHandle, pid, dId, mId, mVer, moduleSize, blockSize, (DsmccEventProc_t)DdbCallback, (DsmccStatusProc_t)DdbStatus, &returnPSICtl); if ( dhlResult != DHL_OK ) printf("%s:%d| ERROR, return(0x%x)\n", __FUNCTION__, __LINE__, dhlResult); } static int WriteDataOnFile(char *filename, unsigned char *ptr, int len) { FILE *fp; int n, total; fp = fopen(filename, "w+"); if ( !fp ) return -1; total = 0; do { n = fwrite( &ptr[total], sizeof(unsigned char), ((total+4096)<=len)?4096:(len-total), fp); if ( n <0 ) return -1; total += n; } while(totalnumPrograms; ++i) { returnPmt = NULL; printf("\r\nGet PMT : program #%d: program_map_PID = %d = 0x%04X\n", returnPat->programs[i].program_number, returnPat->programs[i].program_map_PID, returnPat->programs[i].program_map_PID); dhlResult = DHL_PSI_GetPMT(gPsiHandle, returnPat->programs[i].program_map_PID, returnPat->programs[i].program_number, &returnPmt, timeOut ); if (dhlResult != DHL_OK) { printf("%s| Cannot retrieve PMT.\n", __FUNCTION__); continue; } dhlResult = DHL_PSI_GetDsmccPIDs( returnPmt, dsmccPidList, &PidListLen ); if (dhlResult != DHL_OK) { printf("%s| Cannot find any DSMCC in this PMT-%d.\n", __FUNCTION__, i); continue; } // // 3. Search for any PID which match modelId // for(j=0; jnumSections; n++ ) { if ( DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.descCount > 0 && DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.compatblDescInfo.bValid ) { if ( DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.compatblDescInfo.specifierType == 1 && DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.compatblDescInfo.specifierData != 0x1E1B ) { printf("DSMCC message is found, but the IEEE_OUT is not our vendor. (0x%06lX)\n", DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.compatblDescInfo.specifierData); continue; } if ( DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.compatblDescInfo.model == modelId ) { found = 1; break; } else { printf("PID[0x%04lX] modelId=0x%04X (%d) is different from requested 0x%04X (%d).\n", dsmccPidList[j], DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.compatblDescInfo.model, DsmccDIIMsg->ptrDIIMsgSections[n].compatblDesc.compatblDescInfo.model, modelId, modelId); } } } if (found) { dsmccPID = dsmccPidList[j]; break; } } if ( jptrDIIMsgSections[n].ptrDIIModuleInfo->moduleId; moduleSize = DsmccDIIMsg->ptrDIIMsgSections[n].ptrDIIModuleInfo->moduleSize; moduleVersion = DsmccDIIMsg->ptrDIIMsgSections[n].ptrDIIModuleInfo->moduleVersion; downloadId = DsmccDIIMsg->downloadId; blockSize = DsmccDIIMsg->blockSize; printf("::: DII Table::::\n\t[ modelId = 0x%04X ]\n\t[ moduleId = %u ]\n\t[ moduleSize = %ld ]\n\t[ moduleVersion = %d ]\n\t[ downloadId = 0x%08lX ]\n\t[ blockSize = %d ]\n", modelId, moduleId, moduleSize, moduleVersion, downloadId, blockSize ); dhlResult = DHL_PSI_MonitorDsmccDDB( gPsiHandle, dsmccPID, downloadId, moduleId, moduleVersion, moduleSize, blockSize, DdbCallback, DdbStatus, &ddbHandle ); if ( dhlResult != DHL_OK ) { printf("%s| ERROR, LINE=%d (0x%X)\n", __FUNCTION__, __LINE__, dhlResult); goto done; } /* Wait until all DDB is receiving... */ do { if ( DHL_PSI_GetDsmccDDBProgress(ddbHandle) == 100 ) break; if (dsmccDdbErr) { printf("%s| error occurred during receiving DDB.\n", __FUNCTION__); break; } if ( OS_GetTickCount() > (startTick+timeout) ) { printf("Timeout.\n"); goto done; } OS_mDelay(100); } while(1); bufferPtr = (DS_U32 *)DHL_PSI_GetDsmccDDBBuffer(ddbHandle); DHL_PSI_CancelDDB(ddbHandle); /* Burning it! */ printf("Buffer pointer is 0x%08lX, size=%ld\n", (DS_U32)bufferPtr, moduleSize); startTick = OS_GetTickCount(); //DHL_UTIL_FirmwareUpdate( (unsigned char *)bufferPtr, testCBFunc ); printf("Elapsed Time: %ld.%ld sec\n", (OS_GetTickCount()-startTick)/100, (OS_GetTickCount()-startTick)%100); if ( DsmccDIIMsg->ptrDIIMsgSections[n].ptrDIIModuleInfo->bCrcFieldValid == DS_FALSE ) { printf("DII doesn't includes CRC32_descriptor. Ignore CRC.\n"); } else { crcCalculated = (DS_U32)crc32( 0, (unsigned char *)bufferPtr, moduleSize ); //crcCalculated = (DS_U32)DD_PSI_CalculateCRC( (unsigned char *)bufferPtr, moduleSize ); if ( crcCalculated == DsmccDIIMsg->ptrDIIMsgSections[n].ptrDIIModuleInfo->Crc32_descriptor ) printf("CRC32 is exact matched.\n"); else printf("ERROR: CRC32 is not matched!!! (calculated: 0x%08lX, read: 0x%08lX)\n", crcCalculated, DsmccDIIMsg->ptrDIIMsgSections[n].ptrDIIModuleInfo->Crc32_descriptor ); } WriteDataOnFile("./rx.dat", (unsigned char *)bufferPtr, moduleSize); } else { printf("%s| ERROR, couldn't find any DSMCC\n", __FUNCTION__); } done: if (dsmccPidList) free(dsmccPidList); if (ddbHandle) DHL_PSI_CancelDDB(ddbHandle); }