/*************************************************************************** * Copyright (c) 2003-2006, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: * * Revision History: * * $brcm_Log: $ * ***************************************************************************/ #include "bstd.h" #include "ministd.h" #include "bsettop_smessage.h" #include "ch_map.h" #include "ts_psi.h" #include "ts_psi.h" #include "ts_pat.h" #include "ts_pmt.h" #include "psip_ett.h" #include "si.h" #include "si_nit.h" #include "si_ntt.h" #include "si_stt.h" #include "si_svct.h" BDBG_MODULE(ch_map); /* Register software module with debug interface */ #define CH_MAP_MUTEX_TIMEOUT 500 /* Summary: Initialize channel map mgmt internals (structure may already be initialized). Initialize mutex if it is 0. */ void ch_map_init(ch_map_t *p_ch_map,b_mutex_t *p_mutex) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_mutex); p_ch_map->p_mutex = p_mutex; } /* Summary: reset channel map mgmt internals. */ void ch_map_reset(ch_map_t *p_ch_map) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { p_ch_map->mms_map.num_mms = 0; p_ch_map->freq_map.num_freq = 0; p_ch_map->st_map.num_st = 0; p_ch_map->vch_map.num_vch = 0; bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } /* Summary: copy channel map. */ void ch_map_copy(ch_map_t *p_ch_map_to,ch_map_t *p_ch_map_from,unsigned int flags) { BDBG_ASSERT(p_ch_map_to); BDBG_ASSERT(p_ch_map_from); BDBG_ASSERT(p_ch_map_to->p_mutex); BDBG_ASSERT(p_ch_map_from->p_mutex); if (bos_acquire_mutex(p_ch_map_to->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if (bos_acquire_mutex(p_ch_map_from->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { p_ch_map_to->cur_ch = p_ch_map_from->cur_ch; /* current channel */ if (flags & 0x8) memcpy(&p_ch_map_to->mms_map,&p_ch_map_from->mms_map,sizeof(mms_map_t)); if (flags & 0x1) memcpy(&p_ch_map_to->freq_map,&p_ch_map_from->freq_map,sizeof(freq_map_t)); if (flags & 0x4) memcpy(&p_ch_map_to->st_map,&p_ch_map_from->st_map,sizeof(st_map_t)); if (flags & 0x2) memcpy(&p_ch_map_to->vch_map,&p_ch_map_from->vch_map,sizeof(vch_map_t)); bos_release_mutex(p_ch_map_from->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } bos_release_mutex(p_ch_map_to->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } /* Summary: compare mms maps. */ int ch_map_cmp_mms(mms_map_t *p_mms_map_to, mms_map_t *p_mms_map_from) { mms_t *p_mms_from; mms_t *p_mms_to; int i; if (p_mms_map_to->num_mms != p_mms_map_from->num_mms) { return -1; } for (i = 0; i < p_mms_map_to->num_mms; ++i) { p_mms_from = &(p_mms_map_from->mms[i]); p_mms_to = &(p_mms_map_to->mms[i]); if (p_mms_from->code_rate != p_mms_to->code_rate) return -1; if (p_mms_from->idx != p_mms_to->idx) return -1; if (p_mms_from->modulation != p_mms_to->modulation) return -1; if (p_mms_from->symbol_rate != p_mms_to->symbol_rate) return -1; } return 0; } /* Summary: compare freq maps. */ int ch_map_cmp_freq(freq_map_t *p_freq_map_to, freq_map_t *p_freq_map_from) { freq_t *p_from; freq_t *p_to; int i; if (p_freq_map_to->num_freq != p_freq_map_from->num_freq) { return -1; } for (i = 0; i < p_freq_map_to->num_freq; ++i) { p_from = &(p_freq_map_from->freq[i]); p_to = &(p_freq_map_to->freq[i]); if (p_from->freq_khz != p_to->freq_khz) return -1; if (p_from->idx != p_to->idx) return -1; } return 0; } /* Summary: compare st entry to entries in to map. */ int ch_map_cmp_st_entry(st_map_t *p_map_to, st_t *p_from) { st_t *p_to; int i; for (i = 0; i < p_map_to->num_st; ++i) { p_to = &(p_map_to->st[i]); if ((p_from->source_id == p_to->source_id) && (strcmp(p_from->name,p_to->name) == 0)) return 0; } return -1; } /* Summary: compare st maps. */ int ch_map_cmp_st(st_map_t *p_map_to, st_map_t *p_map_from) { st_t *p_from; int i; if (p_map_to->num_st != p_map_from->num_st) { return -1; } for (i = 0; i < p_map_from->num_st; ++i) { p_from = &(p_map_from->st[i]); if (ch_map_cmp_st_entry(p_map_to,p_from) != 0) return -1; } return 0; } /* Summary: compare vch maps. */ int ch_map_cmp_vch(vch_map_t *p_map_to, vch_map_t *p_map_from) { vch_t *p_from; vch_t *p_to; int i; if (p_map_to->num_vch != p_map_from->num_vch) { return -1; } for (i = 0; i < p_map_to->num_vch; ++i) { p_from = &(p_map_from->vch[i]); p_to = &(p_map_to->vch[i]); if (p_from->ch_num != p_to->ch_num) return -1; if (p_from->source_id != p_to->source_id) return -1; if (p_from->program_num != p_to->program_num) return -1; if (p_from->freq_idx != p_to->freq_idx) return -1; if (p_from->mms_idx != p_to->mms_idx) return -1; if (p_from->vchflags != p_to->vchflags) return -1; } return 0; } int ch_map_cmp_vch_with_pid(vch_map_t *p_map_to, vch_map_t *p_map_from) { int i; vch_t *p_from; vch_t *p_to; for (i=0; inum_vch; ++i) { p_from = &(p_map_from->vch[i]); p_to = &(p_map_to->vch[i]); if ((p_from->video_pid != 0) && (p_to->video_pid != p_from->video_pid)) { return -1; } if ((p_from->audio_pid[0] != 0) && (p_to->audio_pid[0] != p_from->audio_pid[0])) { return -1; } } return 0; } /* Summary: check channel map for changes. */ unsigned int ch_map_cmp(ch_map_t *p_ch_map_to,ch_map_t *p_ch_map_from) { int cmp_result = 0; BDBG_ASSERT(p_ch_map_to); BDBG_ASSERT(p_ch_map_from); BDBG_ASSERT(p_ch_map_to->p_mutex); BDBG_ASSERT(p_ch_map_from->p_mutex); if (bos_acquire_mutex(p_ch_map_to->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if (bos_acquire_mutex(p_ch_map_from->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if (p_ch_map_to->mms_map.num_mms != p_ch_map_from->mms_map.num_mms) cmp_result |= 0x8; if (p_ch_map_to->freq_map.num_freq != p_ch_map_from->freq_map.num_freq) cmp_result |= 0x1; if (p_ch_map_to->st_map.num_st != p_ch_map_from->st_map.num_st) cmp_result |= 0x4; if (p_ch_map_to->vch_map.num_vch != p_ch_map_from->vch_map.num_vch) cmp_result |= 0x2; if (ch_map_cmp_mms(&p_ch_map_to->mms_map,&p_ch_map_from->mms_map) != 0) cmp_result |= 0x8; if (ch_map_cmp_freq(&p_ch_map_to->freq_map,&p_ch_map_from->freq_map) != 0) cmp_result |= 0x1; if (ch_map_cmp_st(&p_ch_map_to->st_map,&p_ch_map_from->st_map) != 0) cmp_result |= 0x4; if (ch_map_cmp_vch(&p_ch_map_to->vch_map,&p_ch_map_from->vch_map) != 0) cmp_result |= 0x2; bos_release_mutex(p_ch_map_from->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } bos_release_mutex(p_ch_map_to->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return cmp_result; } /* Summary: Check for matching entry. */ static bool ch_map_check_mms(ch_map_t *p_ch_map, mms_t *p_mms) { int i; for (i = 0; i < p_ch_map->mms_map.num_mms; ++i) { if (p_ch_map->mms_map.mms[i].idx == p_mms->idx) return true; } BDBG_MSG(("%s:%d no entry exists\n", __FUNCTION__,__LINE__)); return false; } /* Summary: Add an mms entry. */ void ch_map_add_mms(ch_map_t *p_ch_map, mms_t *p_mms) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if (p_ch_map->mms_map.num_mms == MAX_FREQ_MAP) { bos_release_mutex(p_ch_map->p_mutex); BDBG_WRN(("%s:%d ENTRY LIMIT %d of %d\n", __FUNCTION__,__LINE__,p_ch_map->mms_map.num_mms,MAX_FREQ_MAP)); return; } if (!ch_map_check_mms(p_ch_map,p_mms)) { p_ch_map->mms_map.mms[p_ch_map->mms_map.num_mms] = *p_mms; p_ch_map->mms_map.num_mms++; } bos_release_mutex(p_ch_map->p_mutex); BDBG_MSG(("%s:%d num_mms = %d\n", __FUNCTION__,__LINE__,p_ch_map->mms_map.num_mms)); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } /* Summary: Get mms for frequency idx. */ bool ch_map_get_mms(ch_map_t *p_ch_map, unsigned char mms_idx, mms_t *p_mms ) { int idx; bool result = false; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { for (idx = 0; idx < p_ch_map->mms_map.num_mms; ++idx) { if (mms_idx == p_ch_map->mms_map.mms[idx].idx) { *p_mms = p_ch_map->mms_map.mms[idx]; result = true; break; } } bos_release_mutex(p_ch_map->p_mutex); } else return false; return result; } /* Summary: Check for matching entry. */ static bool ch_map_check_freq(ch_map_t *p_ch_map, freq_t *p_freq) { int i; for (i = 0; i < p_ch_map->freq_map.num_freq; ++i) { if (p_ch_map->freq_map.freq[i].idx == p_freq->idx) return true; } BDBG_MSG(("%s:%d no entry exists\n", __FUNCTION__,__LINE__)); return false; } /* Summary: Add a frequency entry. */ void ch_map_add_freq(ch_map_t *p_ch_map, freq_t *p_freq) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if (p_ch_map->freq_map.num_freq == MAX_FREQ_MAP) { bos_release_mutex(p_ch_map->p_mutex); BDBG_WRN(("%s:%d ENTRY LIMIT %d of %d\n", __FUNCTION__,__LINE__,p_ch_map->freq_map.num_freq,MAX_FREQ_MAP)); return; } if (!ch_map_check_freq(p_ch_map,p_freq)) { p_ch_map->freq_map.freq[p_ch_map->freq_map.num_freq] = *p_freq; p_ch_map->freq_map.num_freq++; } bos_release_mutex(p_ch_map->p_mutex); BDBG_MSG(("%s:%d num_freq = %d\n", __FUNCTION__,__LINE__,p_ch_map->freq_map.num_freq)); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } /* Summary: Check for matching entry. */ static bool ch_map_check_vch(ch_map_t *p_ch_map, vch_t *p_vch) { int i; for (i = 0; i < p_ch_map->vch_map.num_vch; ++i) { if (p_ch_map->vch_map.vch[i].ch_num == p_vch->ch_num) return true; } BDBG_MSG(("%s:%d no entry exists(%d,%d)\n", __FUNCTION__,__LINE__,p_vch->ch_num,p_vch->program_num)); return false; } /* Summary: Add a virtual channel entry. */ void ch_map_add_vch(ch_map_t *p_ch_map, vch_t *p_vch) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { int idx,idx2, found_slot; found_slot = 0; if (p_ch_map->vch_map.num_vch == MAX_VCH) { bos_release_mutex(p_ch_map->p_mutex); BDBG_WRN(("%s:%d ENTRY LIMIT, %d of %d\n", __FUNCTION__,__LINE__,p_ch_map->vch_map.num_vch,MAX_VCH)); return; } if (ch_map_check_vch(p_ch_map,p_vch)) { bos_release_mutex(p_ch_map->p_mutex); BDBG_MSG(("%s:%d entry exists(%d,%d)\n", __FUNCTION__,__LINE__,p_vch->ch_num,p_vch->program_num)); return; } for (idx = 0; idx < p_ch_map->vch_map.num_vch; idx++) { if (p_vch->ch_num < p_ch_map->vch_map.vch[idx].ch_num) { for (idx2 = p_ch_map->vch_map.num_vch - 1; idx2 >= idx; idx2--) { BDBG_MSG(("move %d from %d to %d\n",p_ch_map->vch_map.vch[idx2].ch_num, idx2, idx2 + 1)); memcpy(&p_ch_map->vch_map.vch[idx2 + 1],&p_ch_map->vch_map.vch[idx2], sizeof(vch_t)); } memcpy(&p_ch_map->vch_map.vch[idx],p_vch, sizeof(vch_t)); BDBG_MSG(("Add %d at %d\n",p_vch->ch_num, idx)); found_slot = 1; break; } } if (!found_slot) { memcpy(&p_ch_map->vch_map.vch[p_ch_map->vch_map.num_vch],p_vch, sizeof(vch_t)); BDBG_MSG(("Append %d at %d\n",p_vch->ch_num, p_ch_map->vch_map.num_vch)); } p_ch_map->vch_map.num_vch++; bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } /* Summary: Check for matching entry. */ static bool ch_map_check_st(ch_map_t *p_ch_map, st_t *p_st) { int i; for (i = 0; i < p_ch_map->st_map.num_st; ++i) { if (p_ch_map->st_map.st[i].source_id == p_st->source_id) return true; } BDBG_MSG(("%s:%d no entry exists\n", __FUNCTION__,__LINE__)); return false; } /* Summary: Add a source text entry. */ void ch_map_add_st(ch_map_t *p_ch_map, st_t *p_st) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if (p_ch_map->st_map.num_st == MAX_VCH) { bos_release_mutex(p_ch_map->p_mutex); BDBG_WRN(("%s:%d ENTRY LIMIT\n", __FUNCTION__,__LINE__)); return; } if (!ch_map_check_st(p_ch_map,p_st)) { p_ch_map->st_map.st[p_ch_map->st_map.num_st] = *p_st; p_ch_map->st_map.num_st++; } bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } #ifdef CONFIG_DVB /* * Summary: * Add source text entry if it's new entry, or update the existing entry */ void ch_map_add_update_st(ch_map_t *p_ch_map, st_t *p_st) { int i; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex, CH_MAP_MUTEX_TIMEOUT) == b_ok) { for (i=0; ist_map.num_st; ++i) { if (p_ch_map->st_map.st[i].source_id == p_st->source_id) { break; } } if (i == p_ch_map->st_map.num_st) { if (p_ch_map->st_map.num_st == MAX_VCH) { bos_release_mutex(p_ch_map->p_mutex); BDBG_WRN(("%s:%d ENTRY LIMIT", __FUNCTION__, __LINE__)); return; } p_ch_map->st_map.st[p_ch_map->st_map.num_st] = *p_st; p_ch_map->st_map.num_st++; } else { p_ch_map->st_map.st[i] = *p_st; } bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout", __FUNCTION__,__LINE__)); } } bool ch_map_is_new_vch(ch_map_t *p_ch_map, vch_t *p_vch) { int i; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex, CH_MAP_MUTEX_TIMEOUT) == b_ok) { for (i = 0; i < p_ch_map->vch_map.num_vch; ++i) { if (p_ch_map->vch_map.vch[i].program_num == p_vch->program_num) { bos_release_mutex(p_ch_map->p_mutex); return false; } } bos_release_mutex(p_ch_map->p_mutex); return true; } else { BDBG_WRN(("%s:%d mutex timeout", __FUNCTION__,__LINE__)); } return true; } #endif /* Summary: Get number of map entries. */ void ch_map_get_counts(ch_map_t *p_ch_map, unsigned short *num_vch, unsigned short *num_st, unsigned char *num_freq ) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { *num_vch = p_ch_map->vch_map.num_vch; *num_st = p_ch_map->st_map.num_st; *num_freq = p_ch_map->freq_map.num_freq; bos_release_mutex(p_ch_map->p_mutex); } else { *num_vch = 0; *num_st = 0; *num_freq = 0; BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } /* Summary: Get number of map entries. */ void ch_map_get_vch_num(ch_map_t *p_ch_map, unsigned short *num_vch ) { BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { *num_vch = p_ch_map->vch_map.num_vch; bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } } /* Summary: Find the matching freqency info for the given the vch reference. */ bool ch_map_find_freq(ch_map_t *p_ch_map, vch_t *p_vch, freq_t *p_freq) { int idx; for (idx = 0; idx < p_ch_map->freq_map.num_freq; ++idx) { if (p_vch->freq_idx == p_ch_map->freq_map.freq[idx].idx) { *p_freq = p_ch_map->freq_map.freq[idx]; return true; } } BDBG_MSG(("%s:%d frequncy %d not found\n", __FUNCTION__,__LINE__,p_vch->freq_idx)); return false; } /* Summary: Find the matching source text for the given the vch reference. */ static bool ch_map_find_st(ch_map_t *p_ch_map, vch_t *p_vch, st_t *p_st) { int idx; for (idx = 0; idx < p_ch_map->st_map.num_st; ++idx) { if (p_vch->source_id == p_ch_map->st_map.st[idx].source_id) { *p_st = p_ch_map->st_map.st[idx]; return true; } } return false; } /* Summary: Get current channel information. */ bool ch_map_get_current(ch_map_t *p_ch_map, vch_t *p_vch, st_t *p_st, freq_t *p_freq) { bool result = false; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); BDBG_MSG(("%s:%d channel map empty(%d,%d)\n", __FUNCTION__,__LINE__,p_ch_map->freq_map.num_freq,p_ch_map->vch_map.num_vch)); return result; } *p_vch = p_ch_map->vch_map.vch[p_ch_map->cur_ch]; if (ch_map_find_freq(p_ch_map,p_vch,p_freq)) { result = true; } if (!ch_map_find_st(p_ch_map,p_vch,p_st)) { p_st->name[0] = '\0'; p_st->source_id = 0; } bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /* Summary: Update current channel information. */ bool ch_map_vch_update(ch_map_t *p_ch_map, vch_t *p_vch) { bool result = false; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); BDBG_MSG(("%s:%d channel map empty(%d,%d)\n", __FUNCTION__,__LINE__,p_ch_map->freq_map.num_freq,p_ch_map->vch_map.num_vch)); return result; } /* only update if this vch matches current vch */ if ((p_ch_map->vch_map.vch[p_ch_map->cur_ch].freq_idx != p_vch->freq_idx) || (p_ch_map->vch_map.vch[p_ch_map->cur_ch].source_id != p_vch->source_id) || (p_ch_map->vch_map.vch[p_ch_map->cur_ch].ch_num != p_vch->ch_num) || (p_ch_map->vch_map.vch[p_ch_map->cur_ch].program_num != p_vch->program_num)) { bos_release_mutex(p_ch_map->p_mutex); BDBG_WRN(("%s:%d current vch changed, abort update(%d,0x%04x,%d,%d) != (%d,0x%04x,%d,%d)\n", __FUNCTION__,__LINE__, p_ch_map->vch_map.vch[p_ch_map->cur_ch].freq_idx, p_ch_map->vch_map.vch[p_ch_map->cur_ch].source_id, p_ch_map->vch_map.vch[p_ch_map->cur_ch].ch_num, p_ch_map->vch_map.vch[p_ch_map->cur_ch].program_num, p_vch->freq_idx,p_vch->source_id,p_vch->ch_num,p_vch->program_num )); return result; } p_ch_map->vch_map.vch[p_ch_map->cur_ch] = *p_vch; result = true; bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /* Summary: Set next channel information. */ bool ch_map_set_next(ch_map_t *p_ch_map) { bool result = false; int idx = 0; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); return result; } do { p_ch_map->cur_ch++; if (p_ch_map->cur_ch >= p_ch_map->vch_map.num_vch) p_ch_map->cur_ch = 0; result = ((p_ch_map->vch_map.vch[p_ch_map->cur_ch].vchflags == 0) && !(p_ch_map->vch_map.vch[p_ch_map->cur_ch].hd_flag&0x5)) ? true : false; } while (!result && (idx++ < p_ch_map->vch_map.num_vch)); bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /* Summary: Set prev channel information. */ bool ch_map_set_prev(ch_map_t *p_ch_map) { bool result = false; int idx = 0; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); return result; } do { if (p_ch_map->cur_ch == 0) p_ch_map->cur_ch = p_ch_map->vch_map.num_vch - 1; else p_ch_map->cur_ch--; result = ((p_ch_map->vch_map.vch[p_ch_map->cur_ch].vchflags == 0) && !(p_ch_map->vch_map.vch[p_ch_map->cur_ch].hd_flag&0x5)) ? true : false; } while (!result && (idx++ < p_ch_map->vch_map.num_vch)); bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /*Summary: determine if a given channel is visible (not hidden) in the channel map. */ bool ch_map_is_channel_visible(ch_map_t *p_ch_map, unsigned short ch_num) { bool result = false; int idx; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); return result; } for (idx = 0; idx < p_ch_map->vch_map.num_vch; ++idx) { if (p_ch_map->vch_map.vch[idx].ch_num == ch_num) { if (p_ch_map->vch_map.vch[idx].vchflags == 0 && !(p_ch_map->vch_map.vch[idx].hd_flag&0x5)) { result = true; } bos_release_mutex(p_ch_map->p_mutex); return result;//we are done looking, get out } } bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /* Summary: Set channel information by number. */ bool ch_map_set_ch(ch_map_t *p_ch_map, unsigned short ch_num) { bool result = false; int idx; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); return result; } for (idx = 0; idx < p_ch_map->vch_map.num_vch; ++idx) { if (p_ch_map->vch_map.vch[idx].ch_num == ch_num) { p_ch_map->cur_ch = idx; result = true; break; } } bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /* Summary: Set current channel given source ID. */ bool ch_map_set(ch_map_t *p_ch_map,unsigned short source_id) { bool result = false; int idx; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); return result; } for (idx = 0; idx < p_ch_map->vch_map.num_vch; ++idx) { if (p_ch_map->vch_map.vch[idx].source_id == source_id) { p_ch_map->cur_ch = idx; result = true; break; } } bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /* Summary: try to find a source ID from the frequency vector and program number (for EAS major/minor ch#). */ bool ch_map_find_soure_id(ch_map_t *p_ch_map, unsigned char freq_vec, unsigned short prog_num, unsigned short *p_source_id ) { bool result = false; int idx; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { if ((p_ch_map->freq_map.num_freq <= 0) || (p_ch_map->vch_map.num_vch <= 0)) { bos_release_mutex(p_ch_map->p_mutex); return result; } for (idx = 0; idx < p_ch_map->vch_map.num_vch; ++idx) { if ((p_ch_map->vch_map.vch[idx].freq_idx == freq_vec) && (p_ch_map->vch_map.vch[idx].program_num == prog_num)) { *p_source_id = p_ch_map->vch_map.vch[idx].source_id; result = true; break; } } bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return result; } /* Summary: Output details to console. */ void ch_map_print_vch(vch_t *p_vch) { int i; printf("\t\t{ %d,0x%04x,%d,%d,%d,0x%02x,%d,%d,0x%04x,0x%04x,0x%04x,0x%02x,0x%04x,{", p_vch->ch_num, p_vch->source_id, p_vch->program_num, p_vch->freq_idx, p_vch->mms_idx, p_vch->vchflags, p_vch->num_audio, p_vch->cur_audio, p_vch->pcr_pid, p_vch->scte127_pid, p_vch->video_pid, p_vch->video_type, p_vch->ca_pid); for (i = 0; i < MAX_AUDIO_PIDS; i++) { if (i >= p_vch->num_audio) printf("0x0000,"); else printf("0x%04x,",p_vch->audio_pid[i]); } printf("},{"); for (i = 0; i < MAX_AUDIO_PIDS; i++) { if (i >= p_vch->num_audio) printf("0x00,"); else printf("0x%02x,",p_vch->audio_type[i]); } printf("},{"); for (i = 0; i < MAX_AUDIO_PIDS; i++) { if (i >= p_vch->num_audio) printf("\' \',\' \',\' \',"); else printf("%c,%c,%c,",p_vch->audio_lang[i][0], p_vch->audio_lang[i][1],p_vch->audio_lang[i][2]); } printf("} },\n"); } /* Summary: Output details to console. */ void ch_output(ch_map_t *p_ch_map) { int idx; BDBG_ASSERT(p_ch_map); BDBG_ASSERT(p_ch_map->p_mutex); if (bos_acquire_mutex(p_ch_map->p_mutex,CH_MAP_MUTEX_TIMEOUT) == b_ok) { printf("const ch_map_t s_ch_map = \n{\n"); printf("\t0x%08x,\n",0); printf("\t%d,\n",p_ch_map->cur_ch); printf("\t{ %d,\n",p_ch_map->mms_map.num_mms); for (idx = 0; idx < p_ch_map->mms_map.num_mms; ++idx) { printf("\t\t%c{ %d,%d,%d,%d }%c,\n",(idx == 0) ? '{' : ' ', p_ch_map->mms_map.mms[idx].idx, p_ch_map->mms_map.mms[idx].code_rate,p_ch_map->mms_map.mms[idx].modulation,p_ch_map->mms_map.mms[idx].symbol_rate, (idx == (p_ch_map->mms_map.num_mms - 1)) ? '}' : ' '); } printf("\t},\n"); printf("\t{ %d,\n",p_ch_map->freq_map.num_freq); for (idx = 0; idx < p_ch_map->freq_map.num_freq; ++idx) { printf("\t\t%c{ %d,%d }%c,\n",(idx == 0) ? '{' : ' ', p_ch_map->freq_map.freq[idx].idx, p_ch_map->freq_map.freq[idx].freq_khz, (idx == (p_ch_map->freq_map.num_freq - 1)) ? '}' : ' '); } printf("\t},\n"); printf("\t{ %d,\n",p_ch_map->st_map.num_st); for (idx = 0; idx < p_ch_map->st_map.num_st; ++idx) { printf("\t\t%c{ 0x%04x,\"%s\" }%c,\n",(idx == 0) ? '{' : ' ', p_ch_map->st_map.st[idx].source_id, p_ch_map->st_map.st[idx].name, (idx == (p_ch_map->st_map.num_st - 1)) ? '}' : ' '); } printf("\t},\n"); printf("\t{ %d,\n",p_ch_map->vch_map.num_vch); printf("\t\t{"); for (idx = 0; idx < p_ch_map->vch_map.num_vch; ++idx) { bos_sleep(50); ch_map_print_vch(&(p_ch_map->vch_map.vch[idx])); } printf("\n\t\t}\n"); printf("\t},\n"); printf("};\n"); bos_release_mutex(p_ch_map->p_mutex); } else { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__,__LINE__)); } return; }