/******************************************************************** * * DMW_Xds.c * * * Copyright 2002-2004 Digital STREAM Technology, Inc. * All Rights Reserved * * DMW_Xds.c, v 1.0 2004/12/22 cafrii * *******************************************************************/ #include "Zoran.h" #include #include "DHL_OSAL.h" #include "DMW_Status.h" #include "DMW_Config.h" #include "DMW_DebugUtil.h" #include "DMW_Mutex.h" #include "DMW_ChannelAPI.h" #include "DMW_EpgInterface.h" #include "DMW_Xds.h" DHL_MODULE("$xds", 1); //=========================================================================== // // Design Notes // // #if 0 XDS data processingÀº Å©°Ô µÎ ºÎºÐÀ¸·Î ³ª´²Áø´Ù. FrontEnd ½ÇÁ¦·Î µ¥ÀÌÅ͸¦ ¹Þ¾ÆµéÀÌ´Â ºÎºÐ XDS µ¥ÀÌÅÍ´Â VBI µ¥ÀÌÅÍ ¾È¿¡ Æ÷ÇԵǾî Àֱ⠶§¹®¿¡ NTSC Decoder µå¶óÀ̹ö ¸ðµâ¿¡¼­ VBI µ¥ÀÌÅ͸¦ ÃßÃâ ¹× ºÐ¼®ÇÏ¿© XDS µ¥ÀÌÅ͸¸À» »Ì¾Æ³»°Ô µÈ´Ù. ÀÌ ÄÚµå´Â NTSC CC ÄÚµå ¿¡ °°ÀÌ Æ÷ÇԵǾî ÀÖ´Â °æ¿ì°¡ ¸¹À¸¸ç, ±×·² °æ¿ì CC ¸ðµâÀÇ VBI ó¸® ¸ðµâÀÌ FrontEnd°¡ µÈ´Ù. CC Á¤º¸°¡ ¾Æ´Ñ XDS µ¥ÀÌÅÍÀÎ °æ¿ì¿¡¸¸ BackEnd·Î ³Ñ°ÜÁÖ¸é µÈ´Ù. FrontEnd°¡ DTV Module ÀÌ ¾Æ´Ñ ¿ÜºÎ ÀåÄ¡¿¡ ÀÖÀ» ¼öµµ Àִµ¥ (¿¹: TV Host) ±×·² °æ¿ì¿¡´Â TV Host°¡ FrontEnd À̸ç, Åë½Å Interface¸¦ ÅëÇØ¼­ DTV Module BackEnd·Î µ¥ÀÌÅͰ¡ ³Ñ°ÜÁø´Ù. À̶§ ³Ñ°ÜÁö´Â µ¥ÀÌÅÍÀÇ Çü½ÄÀº °¢ Host ±Ô°Ý¿¡ µû¶ó ´Þ¶óÁú ¼ö ÀÖ´Ù. BackEnd FrontEnd ºÎºÐ¿¡¼­ ¹ÞÀº XDS raw data (¶Ç´Â ÀϺΠparsing µÈ µ¥ÀÌÅÍ)¸¦ ºÐ¼®Çϰí À̸¦ DB È­ ÇÏ¿© ÀúÀåÇÑ´Ù. Interface 1. FrontEnd - BackEnd Interface - VBI Raw µ¥ÀÌÅ͸¦ BackEnd ¿¡ ³Ñ°ÜÁÖ´Â ÀÎÅÍÆäÀ̽º Raw µ¥ÀÌÅÍÀÇ Çü½ÄÀº ¾ÆÁ÷ ¹ÌÁ¤.. OnReceiveXDS... - ¿ÜºÎ NTSC Decoder ÀåÄ¡ (¿¹: TV Host)°¡ ¼ö½ÅÇÑ XDS µ¥ÀÌÅ͸¦ ¾î´ÀÁ¤µµ Á¤¸®ÇÏ¿© ³Ñ°ÜÁÖ´Â ÀÎÅÍÆäÀ̽º DMW_XDS_UpdateXdsXXX API 2. Application Control Interface - XDS DB control DB ÃʱâÈ­, ÀúÀå µî.. - RF change notification FrontEnd¿¡¼­ Raw XDS packetÀ» ³Ñ°ÜÁÙ °æ¿ì¶ó¸é ÇöÀç ¾î´À RF ¿¡¼­ ¼ö½Å ÁßÀÎÁö BackEnd°¡ ¾Ë°í ÀÖ¾î¾ß¸¸ DB ±¸¼ºÀ» ÇÒ ¼ö ÀÖÀ½. - XDS time setting?? 3. Application Query Interface - DB ·Î ÀúÀåµÈ XDS µ¥ÀÌÅÍ Áß¿¡¼­ Application ¿¡¼­ EPG ¿ëµµ·Î »ç¿ëÇÒ µ¥ÀÌÅ͸¦ query ÇÏ´Â API DMW_XDS_GetXXXXInfo DMW_XDS_FreeXXXInfo.. 4. Application Notification Interface - ÀÌ ¸ðµâ ³»ºÎ¿¡¼­ ¹ß»ýµÇ´Â ¿©·¯°¡Áö Á¤º¸¸¦ Application¿¡°Ô ¾Ë·ÁÁÖ´Â notification callback #endif //=========================================================================== // // Configuration parameters // // °¢Á¾ ¿É¼Ç ±â´ÉÀÇ On/Off ¼³Á¤, ÄÄÆÄÀÏ·¯ ¿É¼Ç ¼³Á¤, // µå¶óÀ̹ö °ü·Ã ȯ°æ ¼³Á¤ µî.. // //=========================================================================== // // Constants, Variables, Function declarations // XdsChannelInfo *g_XdsChannel; enum { XDS_EVENT_CH_DB_UPDATED = 1000, // // XDS data°¡ ¼ö½ÅµÇ¾î¼­ Channel DB (ÁÖ·Î CSD) Ç׸ñÀÌ º¯°æµÇ¾úÀ½. // NvRam ¿¡ DB update¸¦ ÇØ¾ß ÇÒ Çʿ䰡 ÀÖ´Ù. // // param : none // XDS_EVENT_EPG_DB_UPDATED, // // XDS data°¡ ¼ö½ÅµÇ¾î¼­ Program DB Ç׸ñÀÌ º¯°æµÇ¾úÀ½. }; typedef STATUS (*XdsEventCallback)(int event, UINT32 param); // // user callback function pointer // user¿¡°Ô ¾Ë·ÁÁÙ Á¤º¸°¡ ÀÖÀ¸¸é ÀÌ callbackÀ» ÅëÇØ¼­ ¾Ë·ÁÁØ´Ù. // XdsEventCallback g_fnXdsEventCallback; //=========================================================================== // // Implementations // #if COMMENT ____Mutex______(){} #endif // Mutex = { SemID, Owner, lockCnt, FailCnt, UseOsMutex, Name, flag, traceLvl } // DMW_MUTEX g_MutexXdsInfo = { 0, 0, 0, 0, FALSE, "XdsInfo", OS_SEM_PRIO, FALSE, }; void LockXdsInfoMutex(BOOL bLock) { if (bLock) DMW_LockMutex(&g_MutexXdsInfo); else DMW_UnlockMutex(&g_MutexXdsInfo); } void DeleteXdsInfoMutex() { DMW_DeleteMutex(&g_MutexXdsInfo); } #if COMMENT ____XdsInfo_______(){} #endif //------------------------------------------ // FindXdsChannelInfoByRf // // rf ¿¡ ÇØ´çÇÏ´Â Channel Info¸¦ ã¾Æ¼­ Æ÷ÀÎÅ͸¦ ¸®ÅÏ. // ¾øÀ¸¸é NULLÀ» ¸®ÅÏÇÑ´Ù. // // Unlock »óÅ¿¡¼­ ÀÛ¾÷Çϱ⠶§¹®¿¡ caller°¡ LockÀ» ÇØ¾ß ÇÑ´Ù. // XdsChannelInfo *FindXdsChannelInfoByRf(int rf) { XdsChannelInfo *chInfo = g_XdsChannel; while (chInfo) { if (chInfo->rf == rf) return chInfo; chInfo = chInfo->pNext; } return NULL; } //------------------------------------------ // AllocateNewXdsChannelInfo // // »õ·Ó°Ô XdsChannelInfo ¸Þ¸ð¸®¸¦ ÇÒ´çÇϰí, DB¿¡ Ãß°¡ÇÑ ÈÄ¿¡ // Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. // ÁöÁ¤ÇÑ rfÀÇ channel info´Â ±âÁ¸ DB¿¡ ¾ø¾î¾ß ÇÑ´Ù. (¾È±×·¯¸é µ¿ÀÏÇÑ rf·Î µÎ°³ ÀÌ»óÀÇ info Á¸Àç) // XdsChannelInfo *AllocateNewXdsChannelInfo(int rf) { XdsChannelInfo *newChInfo, *chInfo, *chInfoPrev; newChInfo = OS_Calloc(1, sizeof(XdsChannelInfo)); if (newChInfo == NULL) { //dprint(0, "!! out of memory for XdsChannelInfo\n"); return NULL; } newChInfo->rf = rf; // traverse channel info chain until proper position found in linked-list // chInfo = g_XdsChannel; chInfoPrev = NULL; while (chInfo) { // check so that sort state is not broken.. if (rf <= chInfo->rf) { if (rf == chInfo->rf) dprint(0, "!! same rf %d channel exist in allocate\n", rf); break; } chInfoPrev = chInfo; chInfo = chInfo->pNext; } // we have to insert newChInfo between chInfoPrev and chInfo if (chInfoPrev == NULL) { // head of whole list dprint(2, " new chInfo inserted head of list\n"); g_XdsChannel = newChInfo; newChInfo->pNext = chInfo; } else { chInfoPrev->pNext = newChInfo; newChInfo->pNext = chInfo; // chInfo may be NULL, but that's ok. } return newChInfo; } //------------------------------------------ // FindXdsProgramInfoByProgramID // // ÇØ´ç channel info Á¤º¸¿¡¼­ programID¿Í ÀÏÄ¡ÇÏ´Â program info¸¦ °Ë»öÇÑ´Ù. // ¾øÀ¸¸é NULLÀ» ¸®ÅÏ. // XdsProgramInfo *FindXdsProgramInfoByProgramID(XdsChannelInfo *chInfo, UINT32 startTime) { XdsProgramInfo *programInfo; if (chInfo == NULL || chInfo->programs == NULL) return NULL; programInfo = chInfo->programs; while (programInfo) { if (programInfo->startTime == startTime) { return programInfo; } programInfo = programInfo->pNext; } return NULL; } //------------------------------------------ // AllocateNewXdsProgramInfo // // »õ·Ó°Ô XdsProgramInfo ¸Þ¸ð¸®¸¦ ÇÒ´çÇϰí, DB¿¡ Ãß°¡ÇÑ ÈÄ¿¡ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. // // ÁöÁ¤ÇÑ startTime ÀÇ program info´Â ±âÁ¸ DB¿¡ ¾ø¾î¾ß ÇÑ´Ù. // Ãß°¡ µÉ ¶§´Â startTime ±âÁØÀ¸·Î Á¤·ÄµÇ¾î¼­ list¿¡ µé¾î°£´Ù. // // XdsProgramInfo *AllocateNewXdsProgramInfo(XdsChannelInfo *chInfo, UINT32 startTime) { //»ç¿ëÇÏÁö ¾Ê´Â º¯¼ö Á¦°Å : programID, newProgramID probability // UINT32 programID, newProgramID; XdsProgramInfo *newProgramInfo, *programInfo, *programInfoPrev; newProgramInfo = OS_Calloc(1, sizeof(XdsProgramInfo)); if (newProgramInfo == NULL) { //dprint(0, "!! out of memory for XdsChannelInfo\n"); return NULL; } newProgramInfo->rf = chInfo->rf; newProgramInfo->startTime = startTime; // traverse channel info chain until proper position found in linked-list // programInfo = chInfo->programs; programInfoPrev = NULL; while (programInfo) { // check so that sort state is not broken.. if (startTime <= programInfo->startTime) { if (startTime == programInfo->startTime) dprint(0, "!! same progID 0x%x exist in allocate\n", startTime); break; } programInfoPrev = programInfo; programInfo = programInfo->pNext; } // we have to insert 'newProgramInfo' between 'programInfoPrev' and 'programInfo' if (programInfoPrev == NULL) { // head of whole list dprint(2, " new program info inserted head of list\n"); chInfo->programs = newProgramInfo; newProgramInfo->pNext = programInfo; } else { programInfoPrev->pNext = newProgramInfo; newProgramInfo->pNext = programInfo; // programInfo may be NULL, but that's ok. } return newProgramInfo; } //------------------------------------------ // DeleteXdsProgramInfoItems // // ÇØ´ç program info ¾ÈÀÇ °¢Á¾ item µéÀ» »èÁ¦ÇÑ´Ù. // ¿¬°áµÇ¾î ÀÖ´Â ¸ðµç pointer µéµµ ±ú²ýÀÌ »èÁ¦ÇÑ´Ù. // // ÁÖÀÇ! // ÀÌ program info´Â DBÀÇ ÀϺκРÀϼöµµ ÀÖ°í, Query API¸¦ ÀÌ¿ëÇØ¼­ // Application ¿¡ ³Ñ°ÜÁø »çº» Àϼöµµ ÀÖ´Ù. // // void DeleteXdsProgramInfoItems(XdsProgramInfo *programInfo) { if (programInfo == NULL) return; if (programInfo->ratingInfo) { dprint(3, " free rating info\n"); OS_Free(&programInfo->ratingInfo); } if (programInfo->audioInfo) { dprint(3, " free audio info\n"); OS_Free(&programInfo->audioInfo); } if (programInfo->captionInfo) { dprint(3, " free caption info\n"); OS_Free(&programInfo->captionInfo); } if (programInfo->cgmsaInfo) { dprint(3, " free cgmsa info\n"); OS_Free(&programInfo->cgmsaInfo); } if (programInfo->aspectRatioInfo) { dprint(3, " free aspect ratio info\n"); OS_Free(&programInfo->aspectRatioInfo); } if (programInfo->programDescription) { dprint(3, " free prog desc info\n"); OS_Free(&programInfo->programDescription); } } //------------------------------------------ // DeleteXdsProgramInfoList // // ƯÁ¤ channelÀÇ ¸ðµç program info¸¦ »èÁ¦. // local time ±âÁØÀ¸·Î program info°¡ ÀÛ¼ºµÇ¾ú±â ¶§¹®¿¡ // time Á¤º¸°¡ º¯°æµÇ¸é ¸ðµç program info ÀÚü°¡ ¹«ÀǹÌÇØÁø´Ù. // // ÀÌ ChannelInfo, ProgramInfo´Â ¸ðµÎ DBÀÇ ÀϺκÐÀ̾î¾ß ÇÑ´Ù. // void DeleteXdsProgramInfoList(XdsChannelInfo *chInfo) { XdsProgramInfo *programInfo, *programInfoPrev; if (chInfo == NULL || chInfo->programs == NULL) return; programInfo = chInfo->programs; programInfoPrev = NULL; while (programInfo) { programInfoPrev = programInfo; programInfo = programInfo->pNext; // delete programInfoPrev.. // DeleteXdsProgramInfoItems(programInfoPrev); OS_Free(&programInfoPrev); } chInfo->programs = NULL; } //------------------------------------------ // CopyXdsProgramInfo // // XdsProgramInfo ÀÇ °¢ field link±îÁö ¸ðµÎ º¹»ç¸¦ ÇÑ´Ù. // Query API ³»ºÎ¿¡¼­ program infoÀÇ »çº»À» ¸¸µé¶§ »ç¿ëµÈ´Ù. // // STATUS CopyXdsProgramInfo(XdsProgramInfo *pDst, XdsProgramInfo *pSrc) { int err = statusOutOfMemory; memcpy(pDst, pSrc, sizeof(XdsProgramInfo)); if (pSrc->ratingInfo) { pDst->ratingInfo = OS_Calloc(1, sizeof(XdsRatingInfo)); if (pDst->ratingInfo == NULL) goto label_err_exit; memcpy(pDst->ratingInfo, pSrc->ratingInfo, sizeof(XdsRatingInfo)); } if (pSrc->audioInfo) { pDst->audioInfo = OS_Calloc(1, sizeof(XdsAudioInfo)); if (pDst->ratingInfo == NULL) goto label_err_exit; memcpy(pDst->audioInfo, pSrc->audioInfo, sizeof(XdsAudioInfo)); } if (pSrc->captionInfo) { pDst->captionInfo = OS_Calloc(1, sizeof(XdsCaptionInfo)); if (pDst->captionInfo == NULL) goto label_err_exit; memcpy(pDst->captionInfo, pSrc->captionInfo, sizeof(XdsCaptionInfo)); } if (pSrc->cgmsaInfo) { pDst->cgmsaInfo = OS_Calloc(1, sizeof(XdsCGMSA)); if (pDst->cgmsaInfo == NULL) goto label_err_exit; memcpy(pDst->cgmsaInfo, pSrc->cgmsaInfo, sizeof(XdsCGMSA)); } if (pSrc->aspectRatioInfo) { pDst->aspectRatioInfo = OS_Calloc(1, sizeof(XdsAspectRatioInfo)); if (pDst->aspectRatioInfo == NULL) goto label_err_exit; memcpy(pDst->aspectRatioInfo, pSrc->aspectRatioInfo, sizeof(XdsAspectRatioInfo)); } if (pSrc->programDescription) { pDst->programDescription = OS_Calloc(1, sizeof(XdsProgramDescription)); if (pDst->programDescription == NULL) goto label_err_exit; memcpy(pDst->programDescription, pSrc->programDescription, sizeof(XdsProgramDescription)); } pDst->pNext = NULL; return statusOK; label_err_exit: if (pDst->ratingInfo) OS_Free(&pDst->ratingInfo); if (pDst->audioInfo) OS_Free(&pDst->audioInfo); if (pDst->captionInfo) OS_Free(&pDst->captionInfo); if (pDst->cgmsaInfo) OS_Free(&pDst->cgmsaInfo); if (pDst->aspectRatioInfo) OS_Free(&pDst->aspectRatioInfo); if (pDst->programDescription) OS_Free(&pDst->programDescription); return err; } #if COMMENT ____VBI_IF_______(){} #endif #if 0 void GoToControlCodeRoutine( XDSControlClass_t xdsClass , UINT8 controlType , UINT8 *xdsDataBuffer , UINT8 xdsDataSize ) { if(xdsClass == CurrentClass) { switch(controlType) { case 0x01: /*Program Identification Number*/ #if XDS_DEBUG OS_DbgPrintf("Current :: ProgramIdentificationNumber\n"); #endif ProgramIdentificationNumber(xdsDataBuffer , xdsDataSize); break; case 0x02: /*Length/Time-in-Show*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Length/Time-in-Show\n"); #endif LengthTimeInShow(xdsDataBuffer , xdsDataSize); break; case 0x03: /*Program Name(title)*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Program Name(title)\n"); #endif ProgramName(xdsDataBuffer , xdsDataSize); break; case 0x04: /*Program Type*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Program Type\n"); #endif ProgramType(xdsDataBuffer , xdsDataSize); break; case 0x05: /*Content Advisory*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Content Advisory\n"); #endif ContentAdvisory(xdsDataBuffer , xdsDataSize); break; case 0x06: /*Audio Services*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Audio Services\n"); #endif AudioServices(xdsDataBuffer , xdsDataSize); break; case 0x07: /*Caption Services*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Caption Services\n"); #endif CaptionServices(xdsDataBuffer , xdsDataSize); break; case 0x08: /*Copy Generation Management System(Analog)*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Copy Generation Management System(Analog)\n"); #endif CopyGenerationManagementSystemA(xdsDataBuffer , xdsDataSize); break; case 0x09: /*Aspect Ration Information*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Aspect Ration Information\n"); #endif AspectRatioInformation(xdsDataBuffer , xdsDataSize); break; case 0x0C: /*Composite Packet1*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Composite Packet1\n"); #endif CompositePacket1(xdsDataBuffer , xdsDataSize); break; case 0x0D: /*Composite Packet2*/ #if XDS_DEBUG OS_DbgPrintf("Current :: Composite Packet2\n"); #endif CompositePacket2(xdsDataBuffer , xdsDataSize); break; case 0x10: /*Program Description Row 1 to Row 8*/ case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: #if XDS_DEBUG OS_DbgPrintf("Current :: Program Description\n"); #endif ProgramDescription( xdsDataBuffer , xdsDataSize , controlType-0x10 ); break; } /*switch(controlType)*/ }/*ÇöÀç program¸¸ À¯È¿ÇÑ °É·Î Ãë±ÞÇÏ´Â mode°¡ ¾Æ´Ï °æ¿ì¿¡¸¸ futureclass¸¦ parsingÇÏÀÚ.*/ else if ( (xdsClass == FutureClass) && (DMW_608B_IsCurrentOnlyMode() == false)) { switch(controlType) { case 0x01: /*Program Identification Number*/ #if XDS_DEBUG OS_DbgPrintf("Future :: ProgramIdentificationNumber\n"); #endif ProgramIdentificationNumber(xdsDataBuffer , xdsDataSize); break; case 0x02: /*Length/Time-in-Show*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Length/Time-in-Show\n"); #endif LengthTimeInShow(xdsDataBuffer , xdsDataSize); break; case 0x03: /*Program Name(title)*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Program Name(title)\n"); #endif ProgramName(xdsDataBuffer , xdsDataSize); break; case 0x04: /*Program Type*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Program Type\n"); #endif ProgramType(xdsDataBuffer , xdsDataSize); break; case 0x05: /*Content Advisory*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Content Advisory\n"); #endif ContentAdvisory(xdsDataBuffer , xdsDataSize); break; case 0x06: /*Audio Services*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Audio Services\n"); #endif AudioServices(xdsDataBuffer , xdsDataSize); break; case 0x07: /*Caption Services*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Caption Services\n"); #endif CaptionServices(xdsDataBuffer , xdsDataSize); break; case 0x08: /*Copy Generation Management System(Analog)*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Copy Generation Management System(Analog)\n"); #endif CopyGenerationManagementSystemA(xdsDataBuffer , xdsDataSize); break; case 0x09: /*Aspect Ration Information*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Aspect Ration Information\n"); #endif AspectRatioInformation(xdsDataBuffer , xdsDataSize); break; case 0x0C: /*Composite Packet1*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Composite Packet1\n"); #endif CompositePacket1(xdsDataBuffer , xdsDataSize); break; case 0x0D: /*Composite Packet2*/ #if XDS_DEBUG OS_DbgPrintf("Future :: Composite Packet2\n"); #endif CompositePacket2(xdsDataBuffer , xdsDataSize); break; case 0x10: /*Program Description Row 1 to Row 8*/ case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: #if XDS_DEBUG OS_DbgPrintf("Future :: Program Description\n"); #endif break; } /*switch(controlType)*/ } else if (xdsClass == ChannelClass) { switch(controlType) { case 0x01: /*Network Name*/ #if XDS_DEBUG OS_DbgPrintf("Network Name\n"); #endif NetworkName(xdsDataBuffer , xdsDataSize); break; case 0x02: /*Call Letters(StatonID) and Native Channel*/ #if XDS_DEBUG OS_DbgPrintf("Call Letters(StatonID) and Native Channel\n"); #endif CallLetters(xdsDataBuffer , xdsDataSize); break; case 0x03: /*Tape Delay*/ #if XDS_DEBUG OS_DbgPrintf("Tape Delay\n"); #endif TapeDelay(xdsDataBuffer , xdsDataSize); break; case 0x04: /*Transmission Signal Identifier(TSID)*/ #if XDS_DEBUG OS_DbgPrintf("Transmission Signal Identifier(TSID)\n"); #endif TransmissionSignalIdentifier(xdsDataBuffer , xdsDataSize); break; } /*switch(conrolType)*/ } else if (xdsClass == MiscellaneousClass) { switch(controlType) { case 0x01: /*Time of Day*/ #if XDS_DEBUG OS_DbgPrintf("Time of Day\n"); #endif TimeOfDay(xdsDataBuffer , xdsDataSize); break; case 0x02: /*Impulse Capture ID*/ #if XDS_DEBUG OS_DbgPrintf("Impulse Capture ID\n"); #endif ImpulseCaptureID(xdsDataBuffer , xdsDataSize); break; case 0x03: /*Supplemental Data Location*/ #if XDS_DEBUG OS_DbgPrintf("Supplemental Data Location\n"); #endif SupplementDataLocation(xdsDataBuffer , xdsDataSize); break; case 0x04: /*Local Time Zone & DST Use*/ #if XDS_DEBUG OS_DbgPrintf("Local Time Zone & DST Use\n"); #endif LocalTimeZone_DSTUse (xdsDataBuffer , xdsDataSize); break; case 0x40: /*Out-of-Band Channel Number*/ #if XDS_DEBUG OS_DbgPrintf("Out-of-Band Channel Number\n"); #endif OutOfBandChannelNumber(xdsDataBuffer , xdsDataSize); break; case 0x41: /*Channel Map Pointer*/ #if XDS_DEBUG OS_DbgPrintf("Channel Map Pointer\n"); #endif ChannelMapPointer(xdsDataBuffer , xdsDataSize); break; case 0x42: /*Channel Map Header Packet*/ #if XDS_DEBUG OS_DbgPrintf("Channel Map Header Packet\n"); #endif ChannelMapHeaderPacket(xdsDataBuffer , xdsDataSize); break; case 0x43: /*Channel Map Packet*/ #if XDS_DEBUG OS_DbgPrintf("Channel Map Packet\n"); #endif ChannelMapPacket(xdsDataBuffer , xdsDataSize); break; } /*switch(controlType)*/ } else if (xdsClass == PublicServiceClass) { switch(controlType) { case 0x01: /*National Weather Service Code(WRSAME)*/ #if XDS_DEBUG OS_DbgPrintf("National Weather Service Code(WRSAME)\n"); #endif NationalWeatherServiceCode(xdsDataBuffer , xdsDataSize); break; case 0x02: /*National Weather Service Message*/ #if XDS_DEBUG OS_DbgPrintf("National Weather Service Message\n"); #endif break; } } else if(xdsClass == PrivateClass) { /*nothing*/ } } void OnReceiveXDSData( UINT8 *VBIData ) { static UINT8 xdsDataBuffer[32]; /*The maximum size of XDS Data field is 32 bytes.*/ static XDSControlClass_t xdsClass = CurrentClass; /*class type : current ,future , channel , miscellaneous , public service , private , all*/ static UINT8 controlType = 0; /*it is specific to the class*/ static UINT8 bufferPos = 0; static UINT16 checkSum = 0; static UINT16 checkSum2=0; int i=0; switch ( VBIData[0] ) { case 0x01: /*Control Code : Current class Start Function.*/ case 0x03: /*Control Code : Future class Start Function.*/ case 0x05: /*Control Code : Channel class Start Function.*/ #if DMW_XDS_TIMEOFDAY_BUG_FIX_1 case 0x07: /*Control Code: Miscellaneous */ case 0x09: /*Control Code: PublicServiceClass */ case 0x0B: /*reserved*/ case 0x0D: /*Control Code: PrivaeClass*/ #endif /*clear a data buffer*/ memset( xdsDataBuffer , 0 , 32 ); bufferPos = 0; checkSum = 0; checkSum += VBIData[0]+VBIData[1]; #if _XDS_CHECKSUM_DEBUG OS_DbgPrintf("_XDS_CHECKSUM_DEBUG_ (%d)START checksum=%d, [%d,%d]\n ",VBIData[0],checkSum, VBIData[0],VBIData[1]); #endif /*decide the what is a real control code.*/ controlType = VBIData[1]; if( VBIData[0] == 0x01 ) { xdsClass = CurrentClass; } else if (VBIData[0] == 0x03) { xdsClass = FutureClass; } else if (VBIData[0] == 0x05) { xdsClass = ChannelClass; } else if (VBIData[0] == 0x07) { xdsClass = MiscellaneousClass; } else if (VBIData[0] == 0x09) { xdsClass = PublicServiceClass; } else if (VBIData[0] == 0x0B) { //reserved; } else if (VBIData[0] == 0x0D) { xdsClass = PrivateClass; } break; case 0x02: /*Control Code : Current class Continue Function.*/ case 0x04: /*Control Code : Future class Continue Function.*/ case 0x06: /*Control Code : Channel class Continue Function.*/ case 0x08: /*Control Code : Miscellaneous Continue Function.*/ case 0x0A: /*Control Code : PublicService Continue Function.*/ case 0x0C: /*reserved.*/ case 0x0E: /*Control Code : Private Continue Functioin.*/ if( controlType != VBIData[1]) return; /*if continue Fuction code¶ó¸é ÀÌÀü¿¡ ¿Ô´ø controlÀÇ ¿¬ÀåÀ̾î¾ß ÇϹǷΠcontrolTypeÀÌ ÀÏÄ¡ÇÑ °æ¿ì¸¸ À¯È¿ÇÏ´Ù.*/ // checkSum += (VBIData[0]+VBIData[1]); break; case 0x0F: /*Control Code : All class End Function.*/ /* checksumÀ» °è»êÇϰí, checksum error°¡ ¾ø´Ù¸é ÇØ´ç·çƾÀ» call.*/ checkSum += VBIData[0]; #if DMW_XDS_WORKAROUND_CHECKSUM checkSum2=checkSum; for(i=0;i0x20) checkSum2=checkSum+0x20;//leon for test } } checkSum2 = (((~checkSum2)&0x7F)+1)&0x7F; // make 2's complement. #endif checkSum = (((~checkSum)&0x7F)+1)&0x7F; // make 2's complement. #if _XDS_CHECKSUM_DEBUG OS_DbgPrintf("_XDS_CHECKSUM_DEBUG_ (%d) END (cal_checksum,checksum)=(%d, %d)%d\n ",VBIData[0],checkSum, VBIData[1],checkSum2); #endif #if DMW_XDS_WORKAROUND_CHECKSUM if(checkSum==VBIData[1] ||checkSum2==VBIData[1]) #else if(checkSum==VBIData[1]) // this XDS packet is valid. //test #endif //if(1) { #if XDS_DEBUG dprint(2, "Received Valid XDS packet\n"); #endif GoToControlCodeRoutine( xdsClass , controlType , xdsDataBuffer , bufferPos); } #if XDS_DEBUG else{ dprint(2, "CheckSum Error\n"); } #endif break; default : /*condtorl code¸¦ Á¦¿ÜÇßÀ¸´Ï ¸ðµÎ data·Á´Ï...*/ if(bufferPos > 32 ) /*data size°¡ 32º¸´Ù Å©¸é ¹º°¡ À߸ø ³¯¾Æ ¿Â °Å´Ù.*/ return; checkSum += VBIData[0]+VBIData[1]; #if _XDS_CHECKSUM_DEBUG if(VBIData[0]<0x20 ||VBIData[0]>0x7F){ OS_DbgPrintf("_XDS_CHECKSUM_DEBUG_ Data0 Error [0x%x]\n",VBIData[0]); } if(VBIData[1]<0x20 ||VBIData[1]>0x7F){ OS_DbgPrintf("_XDS_CHECKSUM_DEBUG_ Data1 Error [0x%x]\n",VBIData[1]); } OS_DbgPrintf("_XDS_CHECKSUM_DEBUG_ (%d) ... (cal_checksum=%d),(%d, %d) (0x%x,0x%x) cnt=%d\n ",VBIData[0],checkSum, VBIData[0],VBIData[1],VBIData[0],VBIData[1],bufferPos); OS_DbgPrintf("_XDS_CHECKSUM_DEBUG_ (%d) ... (cal_checksum=%d),(%c, %c) cnt=%d\n ",VBIData[0],checkSum, VBIData[0],VBIData[1],bufferPos); #endif xdsDataBuffer[bufferPos++] = VBIData[0]; xdsDataBuffer[bufferPos++] = VBIData[1]; break; } /* if(VBIData[0]!=0x0F) // ÀÏ¹Ý XDS char. { checkSum += (VBIData[0]+VBIData[1]); } else // XDS End. check the checksum. { checkSum += VBIData[0]; } */ } #endif #if COMMENT ____COM_IF_________(){} #endif //------------------------------------------------------- // DMW_XDS_UpdateXdsChannelInfo // // XDS ä³Î Á¤º¸¸¦ DB¿¡ µî·ÏÇÑ´Ù. // // ÀÎÀÚ·Î ³Ñ¾î¿À´Â newChannelInfo °¡ DB¿¡ Á÷Á¢ insertµÇ´Â °ÍÀÌ ¾Æ´Ï°í º°µµÀÇ ¸Þ¸ð¸®°¡ ÇÒ´çµÈ´Ù. // µû¶ó¼­ caller´Â local area¿¡ newChannelInfo¸¦ Àӽ÷ΠÇÒ´çÇØµµ µÈ´Ù. // // newChannelInfoÀÇ rf °ªÀº ¹Ýµå½Ã valid ÇØ¾ß ÇÑ´Ù. (º°µµÀÇ valid mask °ªÀº ¾øÀ½) // // CallLetter, NetworkName µîÀº NULL·Î Á¾·áµÇ´Â ASCIIZ ÇüÅÂÀ̾î¾ß ÇÑ´Ù. // STATUS DMW_XDS_UpdateXdsChannelInfo(XdsChannelInfo *newChannelInfo, UINT32 validMask) { XdsChannelInfo *chInfo; STATUS err, returnStatus = statusError; BOOL bChannelNameUpdated; if (newChannelInfo == NULL || newChannelInfo->rf <= 0) return statusInvalidArgument; // ´Ü¼øÈ÷ ¸Þ¸ð¸® ÇÒ´ç ¸¸ÀÇ ¿ëµµ¶ó¸é validMask´Â 0ÀÏ ¼ö ÀÖÀ½. //if (validMask == 0) // return statusInvalidArgument; LockXdsInfoMutex(TRUE); //<----- Lock // rf ¿¡ ÇØ´çÇÏ´Â ±âÁ¸ XdsChInfo¸¦ °Ë»ö... chInfo = FindXdsChannelInfoByRf(newChannelInfo->rf); if (chInfo == NULL) { // make new one // chInfo = AllocateNewXdsChannelInfo(newChannelInfo->rf); if (chInfo == NULL) { dprint(0, "!! cannot allocate new xds channel info\n"); returnStatus = statusOutOfMemory; goto label_end; } } // channelInfo <-- newChannelInfo ¿¡ update.. // validMask ¿¡ set µÈ bit¿¡ ÇØ´çµÇ´Â field ¸¸ À¯È¿ÇÏ´Ù. bChannelNameUpdated = FALSE; if (validMask & XVM_NETWORK_NAME) { //compile warming Á¦°Å¸¦ À§ÇÑ Çüº¯È¯ : (char *) probability strncpy((char *)chInfo->networkName, (char *)newChannelInfo->networkName, 32); chInfo->networkName[32] = 0; dprint(3, " network name '%s' updated\n", chInfo->networkName); // update to CSD // // source_id 0 is reserved for PSIP specification. // we use value '0' as an indication of analog channel. // //compile warming Á¦°Å¸¦ À§ÇÑ Çüº¯È¯ : (char *) probability err = DMW_CDB_UpdateUcmCsdEntry(chInfo->rf, 0, CSD_TAG_XDS_NETWORK_NAME, strlen((char *)chInfo->networkName) + 1, chInfo->networkName); if (err == statusNotChanged) { dprint(2, " same network name\n"); } else if (err) { dprint(1, " !! update xds network name to csd err %d, %s (rf %d)\n", err, DMW_CDB_ErrString(err), chInfo->rf); } else { bChannelNameUpdated = TRUE; } } if (validMask & XVM_CALL_LETTER) { memcpy(chInfo->stationId, newChannelInfo->stationId, 7); // including NULL terminator dprint(3, " call letter '%s' updated\n", chInfo->stationId); err = DMW_CDB_UpdateUcmCsdEntry(chInfo->rf, 0, CSD_TAG_XDS_CALL_LETTER, 7, chInfo->stationId); if (err == statusNotChanged) { dprint(2, " same call-letter\n"); } else if (err) { dprint(1, " !! update xds call letter to csd err %d, %s (rf %d)\n", err, DMW_CDB_ErrString(err), chInfo->rf); } else { bChannelNameUpdated = TRUE; } } if (validMask & XVM_TSID) { chInfo->tsid = newChannelInfo->tsid; } if (validMask & XVM_TAPE_DELAY) { chInfo->tapeMinute = newChannelInfo->tapeMinute; chInfo->tapeHour = newChannelInfo->tapeHour; } // notify to user if something in CSD changed.. // if (bChannelNameUpdated) { // // Caller ¶Ç´Â User¿¡°Ô ÀÌ »ç½ÇÀ» ¾Ë·Á¼­ // UCM update¸¦ Çϵµ·Ï ÇØ¾ß ÇÑ´Ù. // if (g_fnXdsEventCallback) g_fnXdsEventCallback(XDS_EVENT_CH_DB_UPDATED, 0); } returnStatus = statusOK; label_end: LockXdsInfoMutex(FALSE); //-----> Unlock return returnStatus; } //------------------------------------------------------- // DMW_XDS_UpdateXdsProgramInfo // // XDS ProgramInfo¸¦ DB¿¡ µî·ÏÇÑ´Ù. // // ½ÇÁ¦·Î Àû¿ëµÉ fieldÀÇ bit¸¦ validMask¿¡ setÇØ¾ß ÇÑ´Ù. // STATUS DMW_XDS_UpdateXdsProgramInfo(XdsProgramInfo *newProgramInfo, UINT32 validMask) { STATUS err, returnStatus = statusError; XdsChannelInfo *chInfo; XdsProgramInfo *programInfo; //»ç¿ëµÇÁö ¾Ê´Â º¯¼ö Á¦°Å : programID[5] probability // UINT8 programID[5]; if (newProgramInfo == NULL || newProgramInfo->rf <= 0) return statusInvalidArgument; // ¹Ýµå½Ã Program ID Çʵå´Â À¯È¿ÇØ¾ß ÇÑ´Ù. ±×·¡¾ß ÇØ´ç ProgramInfo¸¦ °Ë»öÇÒ ¼ö ÀÖÀ¸´Ï±î // if ((validMask & XVM_PROGRAM_ID) == 0) return statusInvalidArgument; LockXdsInfoMutex(TRUE); //<----- Lock // rf ¿¡ ÇØ´çÇÏ´Â ±âÁ¸ XdsChInfo¸¦ °Ë»ö... chInfo = FindXdsChannelInfoByRf(newProgramInfo->rf); if (chInfo == NULL) { // channel 'rf' not exist. make new one.. XdsChannelInfo newChInfo; memset(&newChInfo, 0, sizeof(newChInfo)); newChInfo.rf = newProgramInfo->rf; err = DMW_XDS_UpdateXdsChannelInfo(&newChInfo, 0); // no valid mask.. if (err == statusOK) chInfo = FindXdsChannelInfoByRf(newProgramInfo->rf); if (chInfo == NULL) { dprint(0, "!! cannot allocate new xds ch info\n"); returnStatus = statusOutOfMemory; goto label_end; } } // chInfo ¿¡¼­ program info¸¦ °Ë»ö.. // programInfo = FindXdsProgramInfoByProgramID(chInfo, newProgramInfo->startTime); if (programInfo == NULL) { // »õ·Ó°Ô program info¸¦ ÇÒ´ç ÇÏ¿©, chInfo->programs list ¿¡ Ãß°¡ÇÑ´Ù. //programInfo = AllocateNewXdsProgramInfo(chInfo, programID); programInfo = AllocateNewXdsProgramInfo(chInfo, newProgramInfo->startTime); if (programInfo == NULL) { dprint(0, "!! cannot allocate new xds program info\n"); returnStatus = statusOutOfMemory; goto label_end; } } // programInfo ¿¡ update.. // validMask ¿¡ set µÈ bit¿¡ ÇØ´çµÇ´Â field ¸¸ À¯È¿ÇÏ´Ù. if (validMask & XVM_PROGRAM_ID) { programInfo->startTime = newProgramInfo->startTime; dprint(3, " program id 0x%08x updated\n", programInfo->startTime); } if (validMask & XVM_PROGRAM_LENGTH) { programInfo->minLength = min(newProgramInfo->minLength, 59); programInfo->hourLength = min(newProgramInfo->hourLength, 63); programInfo->minElapsed = newProgramInfo->minElapsed; programInfo->hourElapsed = newProgramInfo->hourElapsed; programInfo->secElapsed = newProgramInfo->secElapsed; dprint(3, " program length %d:%02d min updated\n", programInfo->hourLength, programInfo->minLength); } if (validMask & XVM_PROGRAM_NAME) { //compile warming Á¦°Å¸¦ À§ÇÑ Çüº¯È¯ : (char *) probability strncpy((char *)programInfo->programName, (char *)newProgramInfo->programName, 32); programInfo->programName[32] = 0; dprint(3, " program name '%s' updated\n", programInfo->programName); } if (validMask & XVM_PROGRAM_TYPE) { memcpy(programInfo->programType, newProgramInfo->programType, 32); } if (validMask & XVM_CONTENT_ADVISORY) { if (newProgramInfo->ratingInfo) { if (programInfo->ratingInfo) OS_Free(&programInfo->ratingInfo); programInfo->ratingInfo = OS_Calloc(1, sizeof(XdsRatingInfo)); if (programInfo->ratingInfo) *(programInfo->ratingInfo) = *(newProgramInfo->ratingInfo); else dprint(0, "!! out of memory for xds rating info\n"); } else dprint(0, "!! source xds rating info NULL\n"); } if (validMask & XVM_AUDIO_SERVICES) { if (newProgramInfo->audioInfo) { if (programInfo->audioInfo) OS_Free(&programInfo->audioInfo); programInfo->audioInfo = OS_Calloc(1, sizeof(XdsAudioInfo)); if (programInfo->audioInfo) *(programInfo->audioInfo) = *(newProgramInfo->audioInfo); else dprint(0, "!! out of memory for xds audio info\n"); } else dprint(0, "!! source xds audio info NULL\n"); } if (validMask & XVM_CAPTION_SERVICES) { if (newProgramInfo->captionInfo) { if (programInfo->captionInfo) OS_Free(&programInfo->captionInfo); programInfo->captionInfo = OS_Calloc(1, sizeof(XdsCaptionInfo)); if (programInfo->captionInfo) *(programInfo->captionInfo) = *(newProgramInfo->captionInfo); else dprint(0, "!! out of memory for xds caption info\n"); } else dprint(0, "!! source xds caption info NULL\n"); } if (validMask & XVM_CGMSA) { if (newProgramInfo->cgmsaInfo) { if (programInfo->cgmsaInfo) OS_Free(&programInfo->cgmsaInfo); programInfo->cgmsaInfo = OS_Calloc(1, sizeof(XdsCGMSA)); if (programInfo->cgmsaInfo) *(programInfo->cgmsaInfo) = *(newProgramInfo->cgmsaInfo); else dprint(0, "!! out of memory for xds cgmsa info\n"); } else dprint(0, "!! source xds cgmsa info NULL\n"); } if (validMask & XVM_ASPECT_RATIO) { if (newProgramInfo->aspectRatioInfo) { if (programInfo->aspectRatioInfo) OS_Free(&programInfo->aspectRatioInfo); programInfo->aspectRatioInfo = OS_Calloc(1, sizeof(XdsAspectRatioInfo)); if (programInfo->aspectRatioInfo) *(programInfo->aspectRatioInfo) = *(newProgramInfo->aspectRatioInfo); else dprint(0, "!! out of memory for xds aspect ratio info\n"); } else dprint(0, "!! source xds aspect ratio info NULL\n"); } if (validMask & XVM_PROGRAM_DESCRIPTION) { if (newProgramInfo->programDescription) { if (programInfo->programDescription) OS_Free(&programInfo->programDescription); programInfo->programDescription = OS_Calloc(1, sizeof(XdsProgramDescription)); if (programInfo->programDescription) *(programInfo->programDescription) = *(newProgramInfo->programDescription); else dprint(0, "!! out of memory for xds prog desc \n"); } else dprint(0, "!! source xds prog desc NULL\n"); } returnStatus = statusOK; label_end: LockXdsInfoMutex(FALSE); //-----> Unlock return returnStatus; } #if COMMENT ______API______(){} #endif //------------------------------------------ // DMW_XDS_DeleteAllXdsProgramInfo // // ¸ðµç ä³ÎÀÇ ¸ðµç Program Info Á¤º¸¸¦ »èÁ¦ÇÑ´Ù. // Channel Info´Â »èÁ¦ÇÏÁö ¾Ê´Â´Ù. // // ÀÌ APIÀÇ ÁÖµÈ ¿ëµµ´Â, System ¿¡¼­ SysTime Á¤º¸¸¦ º¯°æÇßÀ»¶§ // (TimeZone °ªÀÌ º¯°æ) // Local time ±â¹ÝÀÎ XDS program Á¤º¸°¡ ÀÇ¹Ì ¾ø¾îÁö±â ¶§¹®ÀÌ´Ù. // STATUS DMW_XDS_DeleteAllXdsProgramInfo() { XdsChannelInfo *chInfo; dprint(1, "DeleteAllXdsProgramInfo\n"); LockXdsInfoMutex(TRUE); chInfo = g_XdsChannel; while (chInfo) { dprint(2, " delete xds channel rf %d\n", chInfo->rf); DeleteXdsProgramInfoList(chInfo); // ÁÖÀÇ! // chInfo ÀÚü´Â »èÁ¦ÇÏ¸é ¾ÈµÈ´Ù... chInfo = chInfo->pNext; } LockXdsInfoMutex(FALSE); //Á¤»ó Á¾·á ÇßÀ» °æ¿ì return 0 probability return 0; } //------------------------------------------ // // // // STATUS DMW_XDS_RegisterEventCallback(XdsEventCallback cb) { dprint(2, "RegisterUserCallback 0x%x\n", cb); g_fnXdsEventCallback = cb; //Á¤»ó Á¾·á ÇßÀ» °æ¿ì return 0 probability return 0; } #if COMMENT ______QueryAPI______(){} #endif //------------------------------------------ // DMW_XDS_FreeChannelInfo // // DMW_XDS_GetChannelInfo ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© ¾òÀº channel »çº»À» »ç¿ë ÈÄ »èÁ¦ÇÑ´Ù. // // STATUS DMW_XDS_FreeChannelInfo(XdsChannelInfo *channel) { if (channel == NULL) return statusInvalidArgument; OS_Free(&channel); return statusOK; } //------------------------------------------ // DMW_XDS_FreeProgramInfoArray // // DMW_XDS_GetProgramInfo ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© ¾òÀº program Á¤º¸ »çº»À» »ç¿ë ÈÄ »èÁ¦ÇÑ´Ù. // programÀº array ÇüÅ·ΠµÇ¾î Àֱ⠶§¹®¿¡ ¸î°³ÀÇ program element°¡ ÀÖ´ÂÁö¸¦ // nProgramÀ» ÅëÇØ ¾Ë·ÁÁà¾ß ÇÑ´Ù. // // STATUS DMW_XDS_FreeProgramInfoArray(XdsProgramInfo *programs, int nProgram) { int i; for (i=0; iprograms = NULL; // program Á¤º¸±îÁö »õ·Ó°Ô duplicate¸¦ ÇÏÁö´Â ¾Ê´Â´Ù. // ³ªÁß¿¡ Free ½Ãų¶§ ÀÌ program Á¤º¸±îÁö °°ÀÌ Áö¿ö¹ö¸±Áö ¸ð¸£¹Ç·Î // program Á¤º¸´Â link¸¦ ¾ø¾Ø´Ù. (*ppChanInfo)->pNext = NULL; return statusOK; } //------------------------------------------ // DMW_XDS_GetProgramInfo // // nStartTime ºÎÅÍ nDuration ±â°£ À̳»¿¡ µé¾îÀÖ´Â ¸ðµç ÇÁ·Î±×·¥ Á¤º¸¸¦ ¸®ÅÏÇÑ´Ù. // ÇÁ·Î±×·¥ÀÇ ÀϺθ¸ °ãÄ¡´õ¶óµµ ¸®ÅϵȴÙ. // // ÇÊ¿äÇÑ ¸Þ¸ð¸® aFoundProgram Àº ³»ºÎ¿¡¼­ µ¿ÀûÀ¸·Î ÇÒ´çµÇ¹Ç·Î // caller´Â »ç¿ë ÈÄ¿¡ FreeProgram API·Î »èÁ¦ÇØ¾ß ÇÑ´Ù. // // nStartTimeÀº GPS ½Ã°£, nDurationÀº ÃÊ ´ÜÀ§.. // // STATUS DMW_XDS_GetProgramInfo(int rf, UINT32 nStartTime, UINT32 nDuration, XdsProgramInfo **aFoundProgram, int *pnPrograms) { XdsChannelInfo *chInfo; XdsProgramInfo *progInfo; int nLengthInSec; int nProgram; int err; UINT32 max_start_time, min_end_time; chInfo = FindXdsChannelInfoByRf(rf); if (chInfo == NULL) return statusNotFound; progInfo = chInfo->programs; nProgram = 0; // ¸ÕÀú °¹¼ö¸¦ ¼¼¾î¼­ ÇÊ¿äÇÑ ¸Þ¸ð¸® Å©±â¸¦ °è»ê.. // while (progInfo) { nLengthInSec = progInfo->minLength * 60 + progInfo->hourLength * 3600; max_start_time = max(nStartTime, progInfo->startTime); min_end_time = min(nStartTime + nDuration-1, progInfo->startTime + nLengthInSec-1); if (max_start_time <= min_end_time) nProgram++; progInfo = progInfo->pNext; } dprint(2, " %d programs are in range\n", nProgram); *aFoundProgram = OS_Calloc(nProgram, sizeof(XdsProgramInfo)); if (*aFoundProgram == NULL) return statusOutOfMemory; *pnPrograms = 0; progInfo = chInfo->programs; while (progInfo) { nLengthInSec = progInfo->minLength * 60 + progInfo->hourLength * 3600; max_start_time = max(nStartTime, progInfo->startTime); min_end_time = min(nStartTime + nDuration-1, progInfo->startTime + nLengthInSec-1); if (max_start_time <= min_end_time) { dprint(2, " copy %dth program..\n", *pnPrograms); err = CopyXdsProgramInfo(&(*aFoundProgram)[*pnPrograms], progInfo); if (err) break; (*pnPrograms)++; } if (*pnPrograms >= nProgram) break; progInfo = progInfo->pNext; } return statusOK; } //------------------------------------------------------------- #if COMMENT ______TEST______(){} #endif extern char *GpsTimeString(UINT32 gps, char *buf); // defined in EpgDebug.c // // XDS program ÇϳªÀÇ Á¤º¸¸¦ Ãâ·Â // void TestPrintXdsProgram(int index, XdsProgramInfo *program) { char buf[50]; if (program == NULL) return; program->programName[32] = 0; // for safety DMW_DBG_SimplePrint(" (%d) %s (0x%x), %d minutes, '%s'\n", index, GpsTimeString(program->startTime, buf), program->startTime, program->hourLength * 60 + program->minLength, program->programName); } // // Query µÈ program »çº» Á¤º¸¸¦ Ç¥½Ã // void TestPrintXdsProgramArray(XdsProgramInfo *program, int nProgram) { int i; for (i=0; inetworkName[32] = 0; // for safety.. numPrograms = 0; program = chInfo->programs; while (program) { numPrograms++; program = program->pNext; } DMW_DBG_SimplePrint(" (%d) RF %d, '%s', '%s', TSID 0x%x, TD %d:%02d, %d programs\n", index, chInfo->rf, chInfo->networkName, chInfo->stationId, chInfo->tsid, chInfo->tapeHour, chInfo->tapeMinute, numPrograms); if (bPrintProgramInfo && chInfo->programs) { numPrograms = 0; program = chInfo->programs; while (program) { TestPrintXdsProgram(numPrograms, program); numPrograms++; program = program->pNext; } DMW_DBG_SimplePrint("\n"); } } // // ÇØ´ç rfÀÇ Ã¤³Î Á¤º¸¸¦ Ç¥½Ã. // // rf °¡ 0ÀÌ¸é ¸ðµç ä³Î Á¤º¸ Ç¥½Ã. // bPrintProgramAlso °¡ TRUE À̸é ä³Î ¾ÈÀÇ ÇÁ·Î±×·¥ Á¤º¸µµ °°ÀÌ Ç¥½Ã. // void TestPrintXdsChannelList(int rf, BOOL bPrintProgramAlso) { XdsChannelInfo *chInfo; int nChannel = 0; LockXdsInfoMutex(TRUE); if (rf) { chInfo = FindXdsChannelInfoByRf(rf); if (chInfo == NULL) { dprint(0, "!! xds channel info rf %d not found\n", rf); goto label_print_all; } DMW_DBG_SimplePrint("------ XdsChannel RF %d ------\n", rf); TestPrintXdsChannel(0, chInfo, bPrintProgramAlso); LockXdsInfoMutex(FALSE); return; } label_print_all: DMW_DBG_SimplePrint("------ XdsChannelList ------\n"); chInfo = g_XdsChannel; while (chInfo) { TestPrintXdsChannel(nChannel, chInfo, bPrintProgramAlso); chInfo = chInfo->pNext; nChannel++; } DMW_DBG_SimplePrint("\n"); LockXdsInfoMutex(FALSE); } //--------------------------------------------------------------------- // // XDS ä³Î Á¤º¸ update ¿¹Á¦ // // void TestUpdateXdsChannel(int rf, char *call_letter, char *network_name) { XdsChannelInfo chInfo; int err; if (rf == 0) { dprint(0, "Usage: TestUpdateXdsChannel rf, \"call_letter\", \"name\"\n"); return; } memset(&chInfo, 0, sizeof(XdsChannelInfo)); chInfo.rf = rf; //compile warming Á¦°Å¸¦ À§ÇÑ Çüº¯È¯ : (char *) probability strncpy((char *)chInfo.networkName, network_name, 32); strncpy((char *)chInfo.stationId, call_letter, 6); dprint(1, "UpdateXdsChannel: rf %d, call letter '%s', network name '%s'\n", chInfo.rf, call_letter, network_name); err = DMW_XDS_UpdateXdsChannelInfo(&chInfo, XVM_NETWORK_NAME | XVM_CALL_LETTER); if (err) dprint(0, "!! err update xds channel info\n"); else dprint(2, " update channel ok\n"); } // // XDS ÇÁ·Î±×·¥ Á¤º¸ update ¿¹Á¦ // // void TestUpdateXdsProgram(int rf, UINT32 start_gps_time, int length_in_minute, char *title, BOOL bCCExist) { XdsProgramInfo progInfo; char buf[50]; int err; if (rf == 0) { dprint(0, "Usage: TestUpdateXdsProgram rf, gps_time, length_in_min, \"title\"\n"); return; } memset(&progInfo, 0, sizeof(XdsProgramInfo)); progInfo.rf = rf; progInfo.startTime = start_gps_time; progInfo.minLength = length_in_minute % 60; progInfo.hourLength = length_in_minute / 60; //compile warming Á¦°Å¸¦ À§ÇÑ Çüº¯È¯ : (char *) probability strncpy((char *)progInfo.programName, title, 32); if (bCCExist) { progInfo.captionInfo = OS_Calloc(1, sizeof(XdsCaptionInfo)); if (progInfo.captionInfo == NULL) dprint(0, "!! out of memory for caption info\n"); else progInfo.captionInfo->iCapService = 1; // ´Ù¸¥ CC °ü·Ã Á¤º¸´Â ÇöÀç not-available Çϸç, ´ÜÁö CC°¡ Á¸ÀçÇÑ´Ù ¾ÈÇÑ´Ù¸¸ ¾Ë¼ö ÀÖ´Ù. // µû¶ó¼­ Caption service °¹¼ö¸¸ 1·Î µî·Ï½ÃÄÑ ³õ°í ³ª¸ÓÁö µ¥ÀÌÅÍ´Â ±×³É empty.. // application¿¡¼­´Â ÀÌ·± Á¡À» ¿°µÎÇØ µÎ°í µ¥ÀÌÅ͸¦ ÀÌ¿ëÇØ¾ß ÇÒ °ÍÀÓ. } dprint(1, "UpdateXdsProgram: rf %d, time %s, len %d:%d, '%s'\n", progInfo.rf, GpsTimeString(progInfo.startTime, buf), progInfo.hourLength, progInfo.minLength, progInfo.programName); err = DMW_XDS_UpdateXdsProgramInfo(&progInfo, XVM_PROGRAM_ID | XVM_PROGRAM_LENGTH | XVM_PROGRAM_NAME); if (err) dprint(0, "!! err update xds program info\n"); else dprint(2, " update program ok\n"); } #if COMMENT ______Script______(){} #endif #if 0 test script.. ## ÀÓÀÇ·Î Á¤º¸¸¦ ¸¸µé¾î ³Ö´Â´Ù. UCM¿¡ RF 24, 25°¡ ÀÖÀ¸¸é UpdateCSD¿¡¼­ ¿¡·¯°¡ ³ªÁö ¾Ê´Â´Ù. ## CSD update ½Ã¿¡´Â ¿¡·¯°¡ ³ªµµ »ó°ü ¾ø´Ù. TestUpdateXdsChannel 24, "WBCD", "MBC Analog" TestUpdateXdsProgram 24, 780000000, 60, "Man in black" TestUpdateXdsProgram 24, 780001000, 5, "CF" TestUpdateXdsProgram 24, 780002000, 25, "News 9", 1 TestUpdateXdsProgram 24, 780003000, 60, "MBC Drama" TestUpdateXdsProgram 24, 780004000, 120, "MBC Movie" TestUpdateXdsChannel 25, "WXSA", "HOME CGV" TestUpdateXdsProgram 25, 780001000, 60, "Send & Chihiro", 1 TestUpdateXdsProgram 25, 780002000, 5, "Ad" TestUpdateXdsProgram 25, 780003000, 25, "Movie World" ## update µÈ Á¤º¸¸¦ Ãâ·ÂÇØº¸ÀÚ. TestPrintXdsChannelList TestPrintXdsChannelList 24, 1 TestPrintXdsChannelList 25, 1 ## Query, Free µîÀÇ API Å×½ºÆ®. ¸Þ¸ð¸® ´©¼ö°¡ ÀÖ´ÂÁöµµ °°ÀÌ Å×½ºÆ®.. memShow chInfo = 0 DMW_XDS_GetChannelInfo 24, &chInfo TestPrintXdsChannel 0, chInfo DMW_XDS_FreeChannelInfo chInfo memShow progInfo = 0 nProg = 0 DMW_XDS_GetProgramInfo 24, 780000000, 10000, &progInfo, &nProg TestPrintXdsProgramArray progInfo, nProg DMW_XDS_FreeProgramInfoArray progInfo, nProg memShow #endif /******************************************************************* Update: 1.00 2004/12/20 first design *******************************************************************/