From 37334ac8a52a23ba2a41d26d0e4ee2f21464e5b2 Mon Sep 17 00:00:00 2001 From: harlequin Date: Fri, 8 Jul 2016 07:54:30 +0200 Subject: [PATCH] Add F-MST model, resolve issue #17 Create call for DMX_STOP, resolve issue #22 --- Makefile | 6 + dvbapi.c | 12 +- models.h | 1 + models/serie_d_mst.c | 10 ++ models/serie_f_mst.c | 364 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 386 insertions(+), 7 deletions(-) create mode 100644 models/serie_f_mst.c diff --git a/Makefile b/Makefile index 4cb0d00..98ab6ad 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,12 @@ ifeq ($(PLATFORM), F) CFLAGS += endif +ifeq ($(PLATFORM), F-MST) + LIB_TV_MODEL=${PLATFORM} + APP_OBJ += models/serie_f.o + CFLAGS += +endif + OBJS = $(APP_OBJ) LIB:=libdvbapi-${PLATFORM}-${TAG}.so diff --git a/dvbapi.c b/dvbapi.c index edfac86..1b07dbb 100644 --- a/dvbapi.c +++ b/dvbapi.c @@ -255,13 +255,11 @@ static void *socket_handler(void *ptr){ } else if (*request == DVBAPI_DMX_STOP) { - log("<< DVBAPI_DMX_STOP request ...\n"); -// stopMonitors(); -// unsigned char demux_index = buf[4]; -// unsigned char filter_num = buf[5]; -// u16 *pid_ptr = (u16 *) &buf[6]; -// u16 pid = ntohs(*pid_ptr); -// log("<< DMX_STOP request, adapter_index=%d, pid=%X, demux_idx=%d, filter_num=%d\n", __FUNCTION__, adapter_index, pid, demux_index, filter_num); + u8 demux_index = buf[4]; + u8 filter_num = buf[5]; + u16 *pid_ptr = (u16 *) &buf[6]; + u16 pid = ntohs(*pid_ptr); + dvbapi_dmx_stop(demux_index, filter_num, pid); } diff --git a/models.h b/models.h index f8ea58b..ea2fbe7 100644 --- a/models.h +++ b/models.h @@ -26,5 +26,6 @@ int dvbapi_server_info(void); int dvbapi_set_descriptor(ca_descr_t ca_descr); int dvbapi_start_filter(u8 demux_index, u8 filter_num, struct dmx_sct_filter_params params); +void dvbapi_dmx_stop(u8 demux_index, u8 filter_num, u16 pid); #endif /* MODELS_H_ */ diff --git a/models/serie_d_mst.c b/models/serie_d_mst.c index 79b3cfa..38c88fd 100644 --- a/models/serie_d_mst.c +++ b/models/serie_d_mst.c @@ -311,6 +311,16 @@ int dvbapi_set_descriptor(ca_descr_t ca_descr) { return g_fltDscmb; } +void dvbapi_dmx_stop(u8 demux_index, u8 filter_num, u16 pid) { + demux_filter_t *filter; + log("DVBAPI_DMX_STOP request, pid=%X, demux_idx=%d, filter_num=%d\n", pid, demux_index, filter_num); + LL_SEARCH_SCALAR(g_demux_filter, filter, filterId, filter_num); + if(filter) { + u32 res = api_callbacks.SdTSData_StopMonitor( g_dmxHandle, filter->monHandle & 0x7FFFFFFF ); + log("Monitor stopped, idx=0x%02X, flt=0x%02X, dmxHandle=0x%08X, monHandle=0x%08X, ret=0x%08X\n", demux_index, filter_num, g_dmxHandle, filter->monHandle & 0x7FFFFFFF, res); + } +} + int dvbapi_start_filter(u8 demux_index, u8 filter_num, struct dmx_sct_filter_params params){ /* This pid zero still occurs because the pmt is not send correctly */ if ( ntohs(params.pid) != 0x00 ) { diff --git a/models/serie_f_mst.c b/models/serie_f_mst.c new file mode 100644 index 0000000..73f9c30 --- /dev/null +++ b/models/serie_f_mst.c @@ -0,0 +1,364 @@ +/** + * Copyright (c) 2016 harlequin + * https://github.com/harlequin/samygo-plugin-dvbapi + * + * This file is part of samygo-plugin-dvbapi. + * + * samygo-plugin-dvbapi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include /*ntohs*/ +#include "../dvbapi.h" +#include "../utlist.h" +#include "../hook.h" +#include "../models.h" +#include "../log.h" +#include "../version.h" + +#define FILTER_MASK_SIZE 16 + +typedef struct DEMUX_FILTER { + u16 tableId; + s32 monHandle; + u8 demuxId; + u8 filterId; + struct DEMUX_FILTER *next; +} demux_filter_t; + +static int g_send_PMT_required = 0; +static int g_SID = 0; +static unsigned int g_dmxHandle = 0; +static demux_filter_t *g_demux_filter = NULL; +static SdTSData_Settings2_t g_emmParams; + +typedef union { + const void *procs[14]; + struct { + const int (*SdTSData_StartMonitor)(u32 dmx_handle, SdTSData_Settings2_t *a1, u32 eDataType, u32 SdMainChip_k); + const int (*SdTSData_StopMonitor)(u32 dmx_handle, u32 mon_handle, u32 SdMainChip_k); + + // libUTOPIA.so + uint32_t *gDSCMB_BUFF; + int (*NW_TZ_DSCMB_FUNC)(int TZ_DSCMB_CMD); + + void* (*TCAPI_GetWindow)(int arg1); + const int (*TCWindowImpl_GetSource)(void *window, int *source, int a2); + const int (*TCWindowImpl_GetTVChannel)(void *window, void *channel, int arg3); + const int (*TCWindowImpl_SetChannelQuiet)(void *window, void *channel, int arg3); + const int (*TCChannel_Create)(void *channel); + const int (*TCChannel_Destroy)(void *channel); + const int (*TCChannel_ProgramNumber)(void *channel); + const int (*TCChannel_SizeOfDescriptor)(void *channel); + const int (*TCChannel_Descriptor)(void *channel, int nine, int desc); + const int (*TPASource_Id)(void *this); + }; + +} api_callbacks_t; + +api_callbacks_t api_callbacks = { + (const void*)"_Z21SdTSData_StartMonitorjP19SdTSData_Settings_tj12SdMainChip_k", + (const void*)"_Z20SdTSData_StopMonitorjj12SdMainChip_k", + + (const void*)"gDSCMB_BUFF", + (const void*)"_Z16NW_TZ_DSCMB_FUNC12TZ_DSCMB_CMD", + + (const void*)"_ZN5TCAPI9GetWindowEN8TCWindow7EWindowE", + (const void*)"_ZN12TCWindowImpl9GetSourceEPii", + (const void*)"_ZN12TCWindowImpl12GetTVChannelEP9TCChanneli", + (const void*)"_ZN12TCWindowImpl15SetChannelQuietEPK9TCChannelb", + (const void*)"_ZN9TCChannelC2Ev", + (const void*)"_ZN9TCChannelD2Ev", + (const void*)"_ZNK9TCChannel13ProgramNumberEv", + (const void*)"_ZNK9TCChannel16SizeOfDescriptorEv", + (const void*)"_ZNK9TCChannel10DescriptorEii", + (const void*)"_ZN9TPASource2IdEv", +}; + +////////////////////////////////////////////////////////////////////////////// +// HELPER FUNCTIONS +////////////////////////////////////////////////////////////////////////////// +int NW_TZ_DSCMB_FUNC(int TZ_DSCMB_CMD) { + return api_callbacks.NW_TZ_DSCMB_FUNC(TZ_DSCMB_CMD); +} + +static uint32_t F_MDrv_DSCMB2_FltAlloc(int unused) { + NW_TZ_DSCMB_FUNC(2); + return (uint32_t)*api_callbacks.gDSCMB_BUFF; +} + +static uint32_t F_MDrv_DSCMB2_FltConnectFltId(int unused, uint32_t allocatedFilter, int filterNumber) { + api_callbacks.gDSCMB_BUFF[0]=allocatedFilter; + api_callbacks.gDSCMB_BUFF[1]=filterNumber; + return NW_TZ_DSCMB_FUNC(6); + //return *hCTX.gDSCMB_BUFF; +} + +static uint32_t F_MDrv_DSCMB2_FltTypeSet(int unused, uint32_t allocatedFilter, int pDscmbType) { + api_callbacks.gDSCMB_BUFF[0]=allocatedFilter; + api_callbacks.gDSCMB_BUFF[8]=pDscmbType; + return NW_TZ_DSCMB_FUNC(3); + //return *hCTX.gDSCMB_BUFF; +} + +static uint32_t F_MDrv_DSCMB2_FltKeySet(int unused, uint32_t allocatedFilter, int oddOrEven, uint32_t *keyTable) { + api_callbacks.gDSCMB_BUFF[0]=allocatedFilter; + api_callbacks.gDSCMB_BUFF[3]=keyTable[0]; + api_callbacks.gDSCMB_BUFF[4]=keyTable[1]; + api_callbacks.gDSCMB_BUFF[5]=keyTable[2]; + api_callbacks.gDSCMB_BUFF[6]=keyTable[3]; + api_callbacks.gDSCMB_BUFF[7]=oddOrEven; + return NW_TZ_DSCMB_FUNC(4); + //return *hCTX.gDSCMB_BUFF; +} +static uint32_t F_MDrv_DSCMB2_FltIVSet(int unused, uint32_t allocatedFilter, int oddOrEven, uint32_t *ivTable) { + api_callbacks.gDSCMB_BUFF[0]=allocatedFilter; + api_callbacks.gDSCMB_BUFF[3]=ivTable[0]; + api_callbacks.gDSCMB_BUFF[4]=ivTable[1]; + api_callbacks.gDSCMB_BUFF[5]=ivTable[2]; + api_callbacks.gDSCMB_BUFF[6]=ivTable[3]; + api_callbacks.gDSCMB_BUFF[7]=oddOrEven; + return NW_TZ_DSCMB_FUNC(5); + //return *hCTX.gDSCMB_BUFF; +} + +static uint32_t F_MDrv_DSCMB2_FltConnectPid(int unused, uint32_t allocatedFilter, uint32_t u32Pid) { + api_callbacks.gDSCMB_BUFF[0]=allocatedFilter; + api_callbacks.gDSCMB_BUFF[2]=u32Pid; + NW_TZ_DSCMB_FUNC(7); + //return *hCTX.gDSCMB_BUFF; + //it looks here not the first element of array is used... + return api_callbacks.gDSCMB_BUFF[9]; +} + +static uint32_t F_MDrv_DSCMB2_FltFree(int unused, int u32DscmbId) { + api_callbacks.gDSCMB_BUFF[0]=u32DscmbId; + return NW_TZ_DSCMB_FUNC(1); + //return (uint32_t)*hCTX.gDSCMB_BUFF; +} + +static uint32_t F_MDrv_DSCMB2_FltDisconnectPid(int unused, uint32_t u32DscmbId, uint32_t u32Pid) { + api_callbacks.gDSCMB_BUFF[0]=u32DscmbId; + api_callbacks.gDSCMB_BUFF[2]=u32Pid; + return NW_TZ_DSCMB_FUNC(8); + ///return (uint32_t)*hCTX.gDSCMB_BUFF; +} + +_HOOK_IMPL(int,SdAVDec_DemuxStop, unsigned int dmxHandle, int eDemuxOut) { + log("SdAVDec_DemuxStop, dmxHandle=0x%08X, eDemuxOut=0x%08X\n", dmxHandle, eDemuxOut); + _HOOK_DISPATCH(SdAVDec_DemuxStop, dmxHandle, eDemuxOut); + g_dmxHandle = dmxHandle; + log("g_dmxHandle=0x%08X\n", g_dmxHandle); + return (int)h_ret; +} + +_HOOK_IMPL(int,SdAVDec_DemuxStart, unsigned int dmxHandle, int eDemuxOut) { + log("SdDemux_Start, dmxHandle=0x%08X, eDemuxOut=0x%08X\n", dmxHandle, eDemuxOut); + g_dmxHandle = dmxHandle; + log("g_dmxHandle=0x%08X\n", g_dmxHandle); + _HOOK_DISPATCH(SdAVDec_DemuxStart, dmxHandle, eDemuxOut); + return (int)h_ret; +} + +_HOOK_IMPL(int,DemuxBase_m_Demux_SICallback, u32* data) { + _HOOK_DISPATCH(DemuxBase_m_Demux_SICallback, data); + + pmt_t *buf; + + u16 sid = 0x00; + + if ( data[3] > 0 ) { + + if ( be8((u8 *)data[2]) == 0x02 ) { + + sid = be16( ((u8*)data[2]) + 0x03 ); + + if ( sid == 0x00 ) { + return (int)h_ret; + } + + if ( sid == g_SID && g_send_PMT_required == 1 ) { + buf = malloc(sizeof(pmt_t)); + buf->sid = sid; + buf->lm = PMT_LIST_FIRST | PMT_LIST_LAST; + buf->len = data[2]; + buf->ptr = malloc(buf->len); + memcpy(buf->ptr, (u8*)data[2], buf->len); + socket_send_capmt(buf); + g_send_PMT_required = 0; + } + + } else { + demux_filter_t *filter; + LL_SEARCH_SCALAR(g_demux_filter, filter, monHandle, data[0]); + if ( filter ) { + log(">> EMM%02x ... hmon:0x%08x send data\n", be8((u8 *)data[2]), data[0]); + socket_send_filter_data( filter->demuxId, filter->filterId, ((u8*)data[2]) , data[3] ); + } + } + } + + return (int)h_ret; +} + +_HOOK_IMPL(int, TCCIMManagerBase_HostChannelChangeCompleted, u32 this, u32 TCChannel, u32 *TCSourceConf) { + u32 i; + _HOOK_DISPATCH(TCCIMManagerBase_HostChannelChangeCompleted, this, TCChannel, TCSourceConf); + + if ( TCChannel != 0x00 ) { + int sid = api_callbacks.TCChannel_ProgramNumber( (void *) TCChannel); + if ( g_SID != sid ) { + g_SID = sid; + + for(i = 0; i < 16; i++) { + F_MDrv_DSCMB2_FltFree(0, i); + } + + for(int i = 0; i < 16; i++) { + F_MDrv_DSCMB2_FltAlloc(0); + F_MDrv_DSCMB2_FltConnectFltId(0, i, 16 + i); + F_MDrv_DSCMB2_FltTypeSet(0, i, 0); + } + + g_send_PMT_required = 1; + log("Service id changes, new SID: 0x%04x\n", g_SID); + } + } + + return (int)h_ret; +} + +STATIC dyn_fn_t TCCIMManagerBase_func_table[] = { + { 0, "_ZN9DemuxBase18m_Demux_SICallbackEPN8CDiDemux20SICallBackSettings_tE" }, + { 0, "_ZN9TCCAMConf13ChannelChangeEPK9TCChannelP12TCSourceConf" }, + { 0, "_Z13SdDemux_Startj13SdDemux_Out_k12SdMainChip_k" }, + { 0, "_Z12SdDemux_Stopj13SdDemux_Out_k12SdMainChip_k" }, +}; + +STATIC hook_entry_t TCCIMManagerBase_hooks[] = +{ +#define _HOOK_ENTRY(F, I) \ + &hook_##F, &TCCIMManagerBase_func_table[I], &x_##F + { _HOOK_ENTRY(DemuxBase_m_Demux_SICallback, __COUNTER__) }, + { _HOOK_ENTRY(TCCIMManagerBase_HostChannelChangeCompleted, __COUNTER__) }, + { _HOOK_ENTRY(SdAVDec_DemuxStart, __COUNTER__) }, + { _HOOK_ENTRY(SdAVDec_DemuxStop, __COUNTER__) }, +#undef _HOOK_ENTRY +}; + + +////////////////////////////////////////////////////////////////////////////// + +int dvbapi_install(void *h) { + int res = 0; + + log("Install "LIB_TV_MODELS" lib"LIB_NAME" "LIB_VERSION" - "BUILD_GIT_TIME" (c) harlequin 2016\n"); + + samyGO_whacky_t_init(h, &api_callbacks, ARRAYSIZE(api_callbacks.procs)); + + if ( dyn_sym_tab_init(h, TCCIMManagerBase_func_table, ARRAYSIZE(TCCIMManagerBase_func_table)) >= 0 ) { + set_hooks(TCCIMManagerBase_hooks, ARRAYSIZE(TCCIMManagerBase_hooks)); + res = 1; + } + + return res; +} + +void dvbapi_dmx_stop(u8 demux_index, u8 filter_num, u16 pid) { + demux_filter_t *filter; + log("DVBAPI_DMX_STOP request, pid=%X, demux_idx=%d, filter_num=%d\n", pid, demux_index, filter_num); + LL_SEARCH_SCALAR(g_demux_filter, filter, filterId, filter_num); + if(filter) { + u32 res = api_callbacks.SdTSData_StopMonitor( g_dmxHandle, filter->monHandle & 0x7FFFFFFF ); + log("Monitor stopped, idx=0x%02X, flt=0x%02X, dmxHandle=0x%08X, monHandle=0x%08X, ret=0x%08X\n", demux_index, filter_num, g_dmxHandle, filter->monHandle & 0x7FFFFFFF, res); + } +} + +int dvbapi_server_info(void) { + int source = 0; + + api_callbacks.TCWindowImpl_GetSource(api_callbacks.TCAPI_GetWindow(0), &source, 1); + if(source == 0) { + u32 channel[32] = {0}; + + api_callbacks.TCChannel_Create(channel); + api_callbacks.TCWindowImpl_GetTVChannel(api_callbacks.TCAPI_GetWindow(0), channel, 1); + + for(int i = 0; i < api_callbacks.TCChannel_SizeOfDescriptor(channel); i++) { + if(api_callbacks.TCChannel_Descriptor(channel, 9, i)) { + api_callbacks.TCWindowImpl_SetChannelQuiet(api_callbacks.TCAPI_GetWindow(0), channel, 1); + break; + } + } + api_callbacks.TCChannel_Destroy(channel); + } +} + +int dvbapi_set_descriptor(ca_descr_t ca_descr) { + u32 i; + log("Got CA_SET_DESCR request, adapter=%d, idx=%d, cw parity=%d\n", 0, ca_descr.index, ca_descr.parity); + for(int i = 0; i < 16; i++) { + F_MDrv_DSCMB2_FltKeySet(0, i, ca_descr.parity + 1, (u32 *)ca_descr.cw); + } + return 0; +} + +int dvbapi_start_filter(u8 demux_index, u8 filter_num, struct dmx_sct_filter_params params){ + /* This pid zero still occurs because the pmt is not send correctly */ + if ( ntohs(params.pid) != 0x00 ) { + demux_filter_t *filter; + + LL_SEARCH_SCALAR(g_demux_filter, filter, filterId, filter_num ); + if(!filter) { + filter = malloc(sizeof(demux_filter_t)); + filter->tableId = -1; + filter->filterId = filter_num; + filter->demuxId = demux_index; + filter->monHandle = -1; + LL_APPEND(g_demux_filter, filter); + } + + if (filter->monHandle != -1) { + u32 ret = api_callbacks.SdTSData_StopMonitor(g_dmxHandle, filter->monHandle,0 ); + log("EMM%02X monitor stopped, dmxHandle=0x%08x, monHandle=0x%08x, ret=0x%08x\n",filter->tableId, g_dmxHandle, filter->monHandle, ret); + filter->monHandle = -1; + filter->tableId = -1; + } + + g_emmParams.pid = ntohs(params.pid); + + g_emmParams.data_type = 0; + g_emmParams.bCRC_check = 0; + g_emmParams.filter_type = 1; + g_emmParams.filter_data_len = DMX_FILTER_SIZE; + g_emmParams.filter = malloc(DMX_FILTER_SIZE); + g_emmParams.mask = malloc(DMX_FILTER_SIZE); + g_emmParams.mode = malloc(DMX_FILTER_SIZE); + + memset(g_emmParams.filter, 0, DMX_FILTER_SIZE); + memset(g_emmParams.mask, 0, DMX_FILTER_SIZE); + memset(g_emmParams.mode, 0, DMX_FILTER_SIZE); + + memcpy(g_emmParams.filter, params.filter.filter, DMX_FILTER_SIZE); + memcpy(g_emmParams.mask, params.filter.mask, DMX_FILTER_SIZE); + + filter->tableId = params.filter.filter[0]; + filter->demuxId = demux_index; + filter->filterId = filter_num; + filter->monHandle = api_callbacks.SdTSData_StartMonitor(g_dmxHandle, &g_emmParams,0 ,0); + log("EMM%02x monitor started, dmxHandle=0x%08x, monHandle=0x%08x\n",filter->tableId, g_dmxHandle, filter->monHandle); + } + return 0; +}