/******************************************************************** DMW_EpgRating.c EPG Middleware RRT management Copyright 2006 Digital STREAM Technology, Inc. All Rights Reserved $Id: DMW_EpgRating.c cafrii ********************************************************************/ /*_____ I N C L U D E __________________________________________*/ #include "DHL_UTL.h" #include "DMW_Platform.h" //#include "DHL_PsiAPI.h" #include "DLIB_PSIP_Monitor.h" #include "DLIB_PSIP_Parser.h" #include "DLIB_PSI_Monitor.h" #include "DLIB_PSI_Parser.h" //#include "DHL_Memchain.h" //#include DHL_MODULE("$epr", 0); #define RRT_FLATTEN_MAP_VERSION 0x81 /* RRT section flattened map version 0x81 00 ID 01 VER 02 LEN_HI 03 LEN_LO, from ID to end of CRC32 04 region 05 rrt version .. payload .. CRC32 (32 bits) from ID to just before CRC32 */ STATUS Dmc_FlattenRrtSection(const rrtSectionPtr_t rrt, UINT32 *pFlattenSize, UINT8 *pSectionBuf) { /* reverse of ParseRrtSection input: caller should prepare necessary memory buffer (pSectionBuf) for flattened rrt . pFlattenSize is the maximum buffer size of pSectionBuf. output: pFlattenSize is actual byte size flattened. */ int i, t; int total_len; UINT8 *p; /* running pointer */ UINT8 *buf_start; int max_size; UINT32 crc; dprint(1, "Dmc_FlattenRrtSection\n"); if (!rrt) { dprint(0, "!! NULL rrt section\n"); return statusInvalidArgument; } if (pSectionBuf == NULL || pFlattenSize == NULL) { dprint(0, "!! invalid buf or bufsize ptr\n"); return statusInvalidArgument; } p = buf_start = pSectionBuf; max_size = (int) *pFlattenSize; #define RSET1(val) \ if ((UINT8 *)p+1 - (UINT8 *)buf_start > max_size) goto label_overflow; \ *p++ = (val)&0xff; #define RSETN(buf,n) \ if ((UINT8 *)p+(n) - (UINT8 *)buf_start > max_size) goto label_overflow; \ memcpy(p, (buf), (n)); \ p += (n); /* fill in PMT header info (except length) */ RSET1(tid_rating_region_table); /* 0xCA */ RSET1(RRT_FLATTEN_MAP_VERSION); /* flatten map length filled later, after it's known */ /* buf[1], buf[2].. */ RSET1(0); RSET1(0); RSET1(rrt->rating_region); RSET1(rrt->version_number & 0x1F); /* now, payload starts.. */ RSET1(rrt->rating_region_name_length); RSETN(rrt->rating_region_name, rrt->rating_region_name_length); RSET1(rrt->dimensions_defined); for (i=0; idimensions_defined; i++) { rrtDimensionPtr_t dim = &rrt->dimension[i]; RSET1(dim->dimension_name_length); RSETN(dim->dimension_name, dim->dimension_name_length); RSET1(dim->graduated_scale); RSET1(dim->first_value_empty); RSET1(dim->values_defined); for (t=0; tvalues_defined; t++) { rrtValuePtr_t value = &dim->value[t]; RSET1(value->block_on); RSET1(value->abbrev_rating_value_length); RSETN(value->abbrev_rating_value, value->abbrev_rating_value_length); RSET1(value->rating_value_length); RSETN(value->rating_value, value->rating_value_length); } } RSET1(rrt->descriptor_length); RSETN(rrt->descriptors, rrt->descriptor_length); total_len = (int)(p - buf_start) + 4; /* CRC¸¦ Æ÷ÇÔÇÑ Àüü Å©±â. */ /* update total length */ buf_start[2] = (total_len >> 8) & 0xff; buf_start[3] = (total_len & 0xff); crc = DHL_UTL_CalcCRC32(0xffffffff, buf_start, total_len-4); /* crc °è»ê¿¡´Â CRCÀÚü´Â »©°í °è»ê. ¹öÆÛ óÀ½ºÎÅÍ CRC ¹Ù·Î ¾Õ±îÁö. */ RSET1((crc >> 24) & 0xFF); RSET1((crc >> 16) & 0xFF); RSET1((crc >> 8) & 0xFF); RSET1((crc & 0xFF)); #undef RSET1 #undef RSETN if (pFlattenSize) *pFlattenSize = total_len; return statusOK; label_overflow: dprint(0, "!! flatten buf overflow, maxsize %d\n", max_size); return statusOverflow; } /* ParseRrtSection(UINT8 * section, rrtSectionPtr_t * rrtSectionPtr) */ STATUS Dmc_RestoreRrtSection(rrtSectionPtr_t *prrt, UINT8 *pSectionBuf) { #define RRT_MEM_LIMIT 0x1000 /* 4K */ #define RatingCheckMemoryError(p) \ if (p == NULL) {status = statusOutOfMemory; goto label_exit;} STATUS status = statusOK; DHL_RESULT err; rrtSectionPtr_t rrt = NULL; memChainSetup_t memSetup = {RRT_MEM_LIMIT,NULL,NULL}; memId_t memId = NULL; int i, t, total_len; UINT8 *p; UINT32 crc1, crc2; if (pSectionBuf == NULL || prrt == NULL) { dprint(0, "!! NULL flat rrt ptr or NULL section buf\n"); status = statusInvalidArgument; goto label_exit; } p = pSectionBuf; if (p[0] != tid_rating_region_table) { dprint(0, "!! flat rrt map id 0x%x err\n", p[0]); status = statusError; goto label_exit; } if (p[1] != RRT_FLATTEN_MAP_VERSION) { dprint(0, "!! RRT flatten map version 0x%x err\n", p[1]); status = statusError; goto label_exit; } total_len = ((p[2] << 8UL) | p[3]); /* total length including CRC */ crc1 = (p[total_len-4]<<24UL) | (p[total_len-3]<<16UL) | (p[total_len-2]<<8UL) | p[total_len-1]; crc2 = DHL_UTL_CalcCRC32(0xffffffff, p, total_len-4); if (crc1 != crc2) { dprint(0, "!! crc mismatch (flat: %08x, calc: %08x)\n", crc1, crc2); status = statusError; goto label_exit; } p = pSectionBuf + 4; /* start of payload.. */ err = memChainCreate(&memId,&memSetup); if (err) { status = statusOutOfMemory; goto label_exit; } rrt = (rrtSectionPtr_t)((memId_t *)(memChainAlloc(memId,sizeof(rrtSection_t)+sizeof(memId_t))) + 1); RatingCheckMemoryError(rrt); #define RGET1(val) if ((UINT8 *)p+1 - (UINT8 *)pSectionBuf > total_len) goto label_overflow; \ (val) = *p++; #define RGET1X(val, type) if ((UINT8 *)p+1 - (UINT8 *)pSectionBuf > total_len) goto label_overflow; \ (val) = (type)*p++; #define RGETN(buf,n) if ((UINT8 *)p+(n) - (UINT8 *)pSectionBuf > total_len) goto label_overflow; \ memcpy((buf), p, (n)); p += (n); RGET1X(rrt->rating_region, rating_region_k); RGET1(rrt->version_number); RGET1(rrt->rating_region_name_length); if (rrt->rating_region_name_length) { rrt->rating_region_name = (UINT8 *)memChainAlloc(memId, rrt->rating_region_name_length*sizeof(UINT8)); RatingCheckMemoryError(rrt->rating_region_name); RGETN(rrt->rating_region_name, rrt->rating_region_name_length); } else rrt->rating_region_name = NULL; RGET1(rrt->dimensions_defined); if (rrt->dimensions_defined) { rrt->dimension = (rrtDimensionPtr_t)memChainAlloc(memId, rrt->dimensions_defined*sizeof(rrtDimension_t)); RatingCheckMemoryError(rrt->dimension); } else rrt->dimension = NULL; for (i=0; idimensions_defined; i++) { rrtDimensionPtr_t dim = &rrt->dimension[i]; RGET1(dim->dimension_name_length); if (dim->dimension_name_length) { dim->dimension_name = (UINT8 *)memChainAlloc(memId, dim->dimension_name_length*sizeof(UINT8)); RatingCheckMemoryError(dim->dimension_name); RGETN(dim->dimension_name, dim->dimension_name_length); } else dim->dimension_name = NULL; RGET1(dim->graduated_scale); RGET1(dim->first_value_empty); RGET1(dim->values_defined); if (dim->values_defined) { dim->value = (rrtValuePtr_t)memChainAlloc(memId, dim->values_defined*sizeof(rrtValue_t)); RatingCheckMemoryError(dim->value); } else dim->value = NULL; for (t=0; tvalues_defined; t++) { rrtValuePtr_t value = &dim->value[t]; RGET1(value->block_on); RGET1(value->abbrev_rating_value_length); if (value->abbrev_rating_value_length) { value->abbrev_rating_value = (UINT8 *)memChainAlloc(memId, value->abbrev_rating_value_length*sizeof(UINT8)); RatingCheckMemoryError(value->abbrev_rating_value); RGETN(value->abbrev_rating_value, value->abbrev_rating_value_length); } else value->abbrev_rating_value = NULL; RGET1(value->rating_value_length); if (value->rating_value_length) { value->rating_value = (UINT8 *)memChainAlloc(memId, value->rating_value_length*sizeof(UINT8)); RatingCheckMemoryError(value->rating_value); RGETN(value->rating_value, value->rating_value_length); } else value->rating_value = NULL; } } RGET1(rrt->descriptor_length); rrt->descriptors = (UINT8 *)memChainAlloc(memId, rrt->descriptor_length*sizeof(UINT8)); RatingCheckMemoryError(rrt->descriptors); RGETN(rrt->descriptors, rrt->descriptor_length); /* parsing complete */ *(((memId_t *)rrt)-1) = memId; memId = NULL; /* so memChain not deleted */ goto label_exit; label_overflow: dprint(0, "!! %s: overflow\n", __FUNCTION__); status = statusOverflow; label_exit: if (memId) { /* delete the rrtSection memory */ memChainDestroy(memId); } if (status == statusOK) *prrt = rrt; return status; } /* end of file */