/*********************************************************************
Copyright (c) 2005 Embedded Internet Solutions, Inc
All rights reserved. You are not allowed to copy or distribute
the code without permission.
This is the demo implenment of the Demux Porting APIs needed by iPanel MiddleWare.
Maybe you should modify it accorrding to Platform.
Note: the "int" in the file is 32bits
Modified Records
$ver0.0.0.2
add batch interface. $author zouxianyun 2005/07/29
Modifed Records
add version control, add received full control, add received eit, 2005/06/08
// 2005/07/13 Xianyun Zou Modified defined
// 1) version number bit 0 1 2 3 4 5 6 7
// | | | | |
// | +-----+-----+ | |
// | | | |
// 保留 ver value 批量 监控
// bit 0 --- 保留位,以后扩展用
// bit 1 2 3 4 5 ---- 版本号
// bit 6 --- 等于0时,批量接收模式,1时,普通接收模式
// bit 7 --- 等于0时,版本的非模式,1时,忽略版本value模式
// 2005/08/30 xianyun Zou 增加一种新的接收方式
// 用上bit0
// bit 0 --- 0时 股票接收监控方式
//
// 统计如下:
// bit 7 6 5 4 3 2 1 0 -- value & comment
// 0 1 x x x x x 1 非模式普通接收模式
// 1 1 x x x x x 1 忽略版本value普通接收模式
// 0 0 x x x x x 1 保留
// 1 0 x x x x x 1 忽略版本value批量接收模式
// 0 0 x x x x x 0 股票模式接收
// x x x x x x x 0 保留
$ver0.0.0.1 $author Zouxianyun 2005/04/28
$ver0.0.0.1 $author Zouxianyun 2005/04/28
*********************************************************************/
#include <sys_define.h>
#include <sys_types.h>
#include <mdl/libc/stdio.h>
#include <mdl/libc/string.h>
#include <osal/osal.h>
#include <mdl/algo/link_list.h>
#include <mdl/algo/rbtree.h>
#include <hld/hld_dev.h>
#include <bus/sci/sci.h>
#include <hld/dmx/dmx.h>
#include <hal/hal_atomic.h>
#include <mdl/libc/stdio.h>
#include <mdl/si/asi_tstat.h>
#include <mdl/si/si_section.h>
#include <mdl/algo/fast_crc.h>
#include <mwal/kvdb/kvdb_event.h>
#include<mwal/kvdb/kvdb_demux.h>
#define IDI_DEBUG_LEVEL 1
#if (IDI_DEBUG_LEVEL>0)
#define IDI_PRINTF LOG_PRINTF
#elif defined(__GNUC__)
#define IDI_PRINTF(...) do{}while(0)
#else
#define IDI_PRINTF
#endif
enum {
IDI_FILTER_MASK = 0xC1,
IDI_FILTER_MON = 0x00,
IDI_FILTER_RECV = 0x01,
IDI_FILTER_NEGRECV = 0x41,
IDI_FILTER_BNV = 0x81,
IDI_FILTER_NV = 0xC1,
IDI_FILTER_PER_CHANNEL = 2//8,
};
enum {
IDI_SECTION_MAX_LEN = 4096,
IDI_CHANNEL_BUF_SIZE = 256*4096,//256*1024,
IDI_VCHANNEL_NUMBER = 2,
IDI_FILTER_MAX_NUM = 8,
IDI_STI_MAX_NUM = 4096,
IDI_SD_MAX_NUM = 384,
};
struct section_data {
struct list_head list;
UINT16 pos;
UINT16 size;
UINT8 data[IDI_SECTION_MAX_LEN];
};
struct physical_channel {
UINT16 pid;
UINT8 *cbuf;
atomic_t reference;
atomic_t counter;
};
union channel_buffer {
UINT8 data[IDI_CHANNEL_BUF_SIZE];
union channel_buffer *next;
};
struct idi_filter {
rbtree root;
UINT16 mode;
INT16 cid;
atomic_t counter;
atomic_t notify;
struct list_head sd;
struct section_data *sdata;
};
struct kvdb_demux_info {
struct dmx_device *dmx;
INT32 pool;
struct list_head *sd_free; /* section data holder, visited by dmx callbacks only */
union channel_buffer *cb_free;
rbtree rb_free;
struct physical_channel pc[IDI_FILTER_MAX_NUM]; /* physical channel buffer, visited by open/close only */
struct idi_filter ifilter[IDI_FILTER_MAX_NUM];
INT8 vc[0x2000]; /* virtual channel information, visited by open/close only */
UINT8 stat_pool[0x8000];
};
static struct kvdb_demux_info *idi;
static UINT8 count=0;
UINT32 event[3];
UINT32 Firstinto = 0;
OSAL_MUTEX_ID kvdb_dmx_mutex;
static INT8 channelnum = 0;
static UINT8 *rb_alloc(struct mem_mgr *mem_mgr, UINT32 size, UINT32 *actual_size)
{
rbtree ret;
if (size != sizeof(rbtree_node)) {
return NULL;
}
osal_task_dispatch_off();
if (NULL != (ret = idi->rb_free)) {
idi->rb_free = idi->rb_free->parent;
} else {
IDI_PRINTF("catch!\n");
}
osal_task_dispatch_on();
if (actual_size) {
*actual_size = ret != NULL? sizeof(rbtree_node): 0;
}
return (UINT8 *)ret;
}
static RET_CODE rb_free(struct mem_mgr *mem_mgr, UINT8 *buffer, UINT32 size)
{
rbtree ptr = (rbtree)buffer;
if (size != sizeof(rbtree_node)||(buffer==NULL)) {
return ERR_FAILURE;
}
osal_task_dispatch_off();
ptr->parent = idi->rb_free;
idi->rb_free = ptr;
osal_task_dispatch_on();
return SUCCESS;
}
static struct mem_mgr rb_mem_mgr = {
rb_alloc,
rb_free,
NULL,
};
static int tab_id_comp(UINT32 key1, UINT32 key2)
{
return ((int)key1)-((int)key2);
}
static struct section_data *sd_alloc(UINT16 size)
{
struct section_data *sd;
osal_task_dispatch_off();
if (idi->sd_free) {
sd = list_get_entry(idi->sd_free, struct section_data, list);
idi->sd_free = idi->sd_free->next;
} else {
sd = NULL;
}
osal_task_dispatch_on();
return sd;
}
static void sd_free(struct section_data *sd)
{
osal_task_dispatch_off();
list_del(&sd->list);
sd->list.next = idi->sd_free;
idi->sd_free = &sd->list;
osal_task_dispatch_on();
}
static void filter_write(INT32 filter_id, INT32 level)
{
struct idi_filter *ifilter = &idi->ifilter[filter_id];
if (ifilter->sdata) {
osal_task_dispatch_off();
list_add_tail(&ifilter->sdata->list, &ifilter->sd);
osal_task_dispatch_on();
ifilter->sdata = NULL;
atomic_inc(&ifilter->counter);
if (level) {
atomic_inc(&ifilter->notify);
}
}
}
static INT32 dmx_callback(struct dmx_device *dev, INT32 filter_id, enum dmx_filter_status status,
struct dmx_filter_info *filter_info, UINT32 param)
{
INT32 ret;
UINT32 key;
UINT32 value;
UINT8 buffer[13];
UINT16 mode;
INT32 submit;
rbtree locate;
struct section_head *sh;
struct asi_tinfo ati;
struct idi_filter *ifilter;
UINT16 pid;
UINT16 setion_len;
UINT8* data;
ifilter = &idi->ifilter[filter_id];
pid = idi->pc[ifilter->cid].pid;
if (status != DMX_FILTER_STATUS_OK) {
if (pid != 0x0014) {
LOG_PRINTF("[%04x]status = %02x\n", idi->pc[ifilter->cid].pid, status);
}
return SUCCESS;
}
mode = ifilter->mode;
if (pid == 0x0014) { /* TDT or TOT, such a crazy thing is that it doesn't have any section head! */
if (mode == IDI_FILTER_NV) {
ret = ASI_TSTAT_SUCCESS;
goto stat_escape;
} else {
return SUCCESS;
}
}
if (filter_info->sec_linear>=13) {
sh = (struct section_head *)filter_info->sec_addr;
} else {
dmx_filter_copy(dev, filter_id, buffer, 13);
sh = (struct section_head *)buffer;
}
ati.last_sn = sh->last_section_num;
ati.ver = 0; //sh->version; /* to avoid version detection!! */
ati.sn = sh->section_num;
if(count != sh->section_num)
return SUCCESS;
if (idi->pc[ifilter->cid].pid == 0x0012) {
ati.last_seg = buffer[12];
} else {
ati.last_seg = ati.last_sn;
}
key = (sh->table_id<<16)|(sh->extension_id[0]<<8)|sh->extension_id[1];
locate = rbtree_find(idi->ifilter[filter_id].root, key, NULL);
if (locate == rbtree_nil(idi->ifilter[filter_id].root)) {
value = asi_tstat_alloc(idi->pool, &ati);
locate = rbtree_insert_unique(ifilter->root, key, value, tab_id_comp, &rb_mem_mgr, NULL);
if (locate == NULL) {
IDI_PRINTF("--insufficent memory!\n");
/* Insufficient memory */
return ERR_FAILURE;
}
} else {
value = rbtree_val(locate);
}
stat_control:
ret = asi_tstat_set(idi->pool, value, &ati);
stat_escape:
//PRINTF("dmx: %04x %08x %d/%d %c\n", idi->pc[ifilter->cid].pid, key, ati.sn, ati.last