📄 en50221.c
字号:
* CAPMTUpdate *****************************************************************************/static void CAPMTUpdate( access_t * p_access, int i_session_id, dvbpsi_pmt_t *p_pmt ){ uint8_t *p_capmt; int i_capmt_size; msg_Dbg( p_access, "updating CAPMT for SID %d on session %d", p_pmt->i_program_number, i_session_id ); p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt, 0x5 /* update */, 0x1 /* ok_descrambling */, &i_capmt_size ); if ( i_capmt_size ) APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );}/***************************************************************************** * CAPMTDelete *****************************************************************************/static void CAPMTDelete( access_t * p_access, int i_session_id, dvbpsi_pmt_t *p_pmt ){ uint8_t *p_capmt; int i_capmt_size; p_access->p_sys->i_selected_programs--; msg_Dbg( p_access, "deleting CAPMT for SID %d on session %d", p_pmt->i_program_number, i_session_id ); p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt, 0x5 /* update */, 0x4 /* not selected */, &i_capmt_size ); if ( i_capmt_size ) APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );}/***************************************************************************** * ConditionalAccessHandle *****************************************************************************/static void ConditionalAccessHandle( access_t * p_access, int i_session_id, uint8_t *p_apdu, int i_size ){ access_sys_t *p_sys = p_access->p_sys; system_ids_t *p_ids = (system_ids_t *)p_sys->p_sessions[i_session_id - 1].p_sys; int i_tag = APDUGetTag( p_apdu, i_size ); switch ( i_tag ) { case AOT_CA_INFO: { int i; int l = 0; uint8_t *d = APDUGetLength( p_apdu, &l ); msg_Dbg( p_access, "CA system IDs supported by the application :" ); for ( i = 0; i < l / 2; i++ ) { p_ids->pi_system_ids[i] = ((uint16_t)d[0] << 8) | d[1]; d += 2; msg_Dbg( p_access, "- 0x%x", p_ids->pi_system_ids[i] ); } p_ids->pi_system_ids[i] = 0; for ( i = 0; i < MAX_PROGRAMS; i++ ) { if ( p_sys->pp_selected_programs[i] != NULL ) { CAPMTAdd( p_access, i_session_id, p_sys->pp_selected_programs[i] ); } } break; } default: msg_Err( p_access, "unexpected tag in ConditionalAccessHandle (0x%x)", i_tag ); }}/***************************************************************************** * ConditionalAccessClose *****************************************************************************/static void ConditionalAccessClose( access_t * p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; msg_Dbg( p_access, "closing ConditionalAccess session (%d)", i_session_id ); free( p_sys->p_sessions[i_session_id - 1].p_sys );}/***************************************************************************** * ConditionalAccessOpen *****************************************************************************/static void ConditionalAccessOpen( access_t * p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; msg_Dbg( p_access, "opening ConditionalAccess session (%d)", i_session_id ); p_sys->p_sessions[i_session_id - 1].pf_handle = ConditionalAccessHandle; p_sys->p_sessions[i_session_id - 1].pf_close = ConditionalAccessClose; p_sys->p_sessions[i_session_id - 1].p_sys = malloc(sizeof(system_ids_t)); memset( p_sys->p_sessions[i_session_id - 1].p_sys, 0, sizeof(system_ids_t) ); APDUSend( p_access, i_session_id, AOT_CA_INFO_ENQ, NULL, 0 );}/* * Date Time */typedef struct{ int i_interval; mtime_t i_last;} date_time_t;/***************************************************************************** * DateTimeSend *****************************************************************************/static void DateTimeSend( access_t * p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; date_time_t *p_date = (date_time_t *)p_sys->p_sessions[i_session_id - 1].p_sys; time_t t = time(NULL); struct tm tm_gmt; struct tm tm_loc; if ( gmtime_r(&t, &tm_gmt) && localtime_r(&t, &tm_loc) ) { int Y = tm_gmt.tm_year; int M = tm_gmt.tm_mon + 1; int D = tm_gmt.tm_mday; int L = (M == 1 || M == 2) ? 1 : 0; int MJD = 14956 + D + (int)((Y - L) * 365.25) + (int)((M + 1 + L * 12) * 30.6001); uint8_t p_response[7];#define DEC2BCD(d) (((d / 10) << 4) + (d % 10)) p_response[0] = htons(MJD) >> 8; p_response[1] = htons(MJD) & 0xff; p_response[2] = DEC2BCD(tm_gmt.tm_hour); p_response[3] = DEC2BCD(tm_gmt.tm_min); p_response[4] = DEC2BCD(tm_gmt.tm_sec); p_response[5] = htons(tm_loc.tm_gmtoff / 60) >> 8; p_response[6] = htons(tm_loc.tm_gmtoff / 60) & 0xff; APDUSend( p_access, i_session_id, AOT_DATE_TIME, p_response, 7 ); p_date->i_last = mdate(); }}/***************************************************************************** * DateTimeHandle *****************************************************************************/static void DateTimeHandle( access_t * p_access, int i_session_id, uint8_t *p_apdu, int i_size ){ access_sys_t *p_sys = p_access->p_sys; date_time_t *p_date = (date_time_t *)p_sys->p_sessions[i_session_id - 1].p_sys; int i_tag = APDUGetTag( p_apdu, i_size ); switch ( i_tag ) { case AOT_DATE_TIME_ENQ: { int l; const uint8_t *d = APDUGetLength( p_apdu, &l ); if ( l > 0 ) { p_date->i_interval = *d; msg_Dbg( p_access, "DateTimeHandle : interval set to %d", p_date->i_interval ); } else p_date->i_interval = 0; DateTimeSend( p_access, i_session_id ); break; } default: msg_Err( p_access, "unexpected tag in DateTimeHandle (0x%x)", i_tag ); }}/***************************************************************************** * DateTimeManage *****************************************************************************/static void DateTimeManage( access_t * p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; date_time_t *p_date = (date_time_t *)p_sys->p_sessions[i_session_id - 1].p_sys; if ( p_date->i_interval && mdate() > p_date->i_last + (mtime_t)p_date->i_interval * 1000000 ) { DateTimeSend( p_access, i_session_id ); }}/***************************************************************************** * DateTimeClose *****************************************************************************/static void DateTimeClose( access_t * p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; msg_Dbg( p_access, "closing DateTime session (%d)", i_session_id ); free( p_sys->p_sessions[i_session_id - 1].p_sys );}/***************************************************************************** * DateTimeOpen *****************************************************************************/static void DateTimeOpen( access_t * p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; msg_Dbg( p_access, "opening DateTime session (%d)", i_session_id ); p_sys->p_sessions[i_session_id - 1].pf_handle = DateTimeHandle; p_sys->p_sessions[i_session_id - 1].pf_manage = DateTimeManage; p_sys->p_sessions[i_session_id - 1].pf_close = DateTimeClose; p_sys->p_sessions[i_session_id - 1].p_sys = malloc(sizeof(date_time_t)); memset( p_sys->p_sessions[i_session_id - 1].p_sys, 0, sizeof(date_time_t) ); DateTimeSend( p_access, i_session_id );}/* * MMI *//* Display Control Commands */#define DCC_SET_MMI_MODE 0x01#define DCC_DISPLAY_CHARACTER_TABLE_LIST 0x02#define DCC_INPUT_CHARACTER_TABLE_LIST 0x03#define DCC_OVERLAY_GRAPHICS_CHARACTERISTICS 0x04#define DCC_FULL_SCREEN_GRAPHICS_CHARACTERISTICS 0x05/* MMI Modes */#define MM_HIGH_LEVEL 0x01#define MM_LOW_LEVEL_OVERLAY_GRAPHICS 0x02#define MM_LOW_LEVEL_FULL_SCREEN_GRAPHICS 0x03/* Display Reply IDs */#define DRI_MMI_MODE_ACK 0x01#define DRI_LIST_DISPLAY_CHARACTER_TABLES 0x02#define DRI_LIST_INPUT_CHARACTER_TABLES 0x03#define DRI_LIST_GRAPHIC_OVERLAY_CHARACTERISTICS 0x04#define DRI_LIST_FULL_SCREEN_GRAPHIC_CHARACTERISTICS 0x05#define DRI_UNKNOWN_DISPLAY_CONTROL_CMD 0xF0#define DRI_UNKNOWN_MMI_MODE 0xF1#define DRI_UNKNOWN_CHARACTER_TABLE 0xF2/* Enquiry Flags */#define EF_BLIND 0x01/* Answer IDs */#define AI_CANCEL 0x00#define AI_ANSWER 0x01typedef struct{ en50221_mmi_object_t last_object;} mmi_t;/***************************************************************************** * MMISendObject *****************************************************************************/static void MMISendObject( access_t *p_access, int i_session_id, en50221_mmi_object_t *p_object ){ access_sys_t *p_sys = p_access->p_sys; int i_slot = p_sys->p_sessions[i_session_id - 1].i_slot; uint8_t *p_data; int i_size, i_tag; switch ( p_object->i_object_type ) { case EN50221_MMI_ANSW: i_tag = AOT_ANSW; i_size = 1 + strlen( p_object->u.answ.psz_answ ); p_data = malloc( i_size ); p_data[0] = (p_object->u.answ.b_ok == VLC_TRUE) ? 0x1 : 0x0; strncpy( (char *)&p_data[1], p_object->u.answ.psz_answ, i_size - 1 ); break; case EN50221_MMI_MENU_ANSW: i_tag = AOT_MENU_ANSW; i_size = 1; p_data = malloc( i_size ); p_data[0] = p_object->u.menu_answ.i_choice; break; default: msg_Err( p_access, "unknown MMI object %d", p_object->i_object_type ); return; } APDUSend( p_access, i_session_id, i_tag, p_data, i_size ); free( p_data ); p_sys->pb_slot_mmi_expected[i_slot] = VLC_TRUE;}/***************************************************************************** * MMISendClose *****************************************************************************/static void MMISendClose( access_t *p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; int i_slot = p_sys->p_sessions[i_session_id - 1].i_slot; APDUSend( p_access, i_session_id, AOT_CLOSE_MMI, NULL, 0 ); p_sys->pb_slot_mmi_expected[i_slot] = VLC_TRUE;}/***************************************************************************** * MMIDisplayReply *****************************************************************************/static void MMIDisplayReply( access_t *p_access, int i_session_id ){ uint8_t p_response[2]; p_response[0] = DRI_MMI_MODE_ACK; p_response[1] = MM_HIGH_LEVEL; APDUSend( p_access, i_session_id, AOT_DISPLAY_REPLY, p_response, 2 ); msg_Dbg( p_access, "sending DisplayReply on session (%d)", i_session_id );}/***************************************************************************** * MMIGetText *****************************************************************************/static char *MMIGetText( access_t *p_access, uint8_t **pp_apdu, int *pi_size ){ int i_tag = APDUGetTag( *pp_apdu, *pi_size ); int l; uint8_t *d; if ( i_tag != AOT_TEXT_LAST ) { msg_Err( p_access, "unexpected text tag: %06x", i_tag ); *pi_size = 0; return strdup( "" ); } d = APDUGetLength( *pp_apdu, &l ); *pp_apdu += l + 4; *pi_size -= l + 4; return dvbsi_to_utf8((char*)d,l);}/***************************************************************************** * MMIHandleEnq *****************************************************************************/static void MMIHandleEnq( access_t *p_access, int i_session_id, uint8_t *p_apdu, int i_size ){ access_sys_t *p_sys = p_access->p_sys; mmi_t *p_mmi = (mmi_t *)p_sys->p_sessions[i_session_id - 1].p_sys; int i_slot = p_sys->p_sessions[i_session_id - 1].i_slot; int l; uint8_t *d = APDUGetLength( p_apdu, &l ); en50221_MMIFree( &p_mmi->last_object ); p_mmi->last_object.i_object_type = EN50221_MMI_ENQ; p_mmi->last_object.u.enq.b_blind = (*d & 0x1) ? VLC_TRUE : VLC_FALSE; d += 2; /* skip answer_text_length because it is not mandatory */ l -= 2; p_mmi->last_object.u.enq.psz_text = malloc( l + 1 ); strncpy( p_mmi->last_object.u.enq.psz_text, (char *)d, l ); p_mmi->last_object.u.enq.psz_text[l] = '\0'; msg_Dbg( p_access, "MMI enq: %s%s", p_mmi->last_object.u.enq.psz_text, p_mmi->last_object.u.enq.b_blind == VLC_TRUE ? " (blind)" : "" ); p_sys->pb_slot_mmi_expected[i_slot] = VLC_FALSE; p_sys->pb_slot_mmi_undisplayed[i_slot] = VLC_TRUE;}/***************************************************************************** * MMIHandleMenu *****************************************************************************/static void MMIHandleMenu( access_t *p_access, int i_session_id, int i_tag, uint8_t *p_apdu, int i_size )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -