📄 en50221.c
字号:
/***************************************************************************** * MMIHandleMenu *****************************************************************************/static void MMIHandleMenu( access_t *p_access, int i_session_id, int i_tag, 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 = (i_tag == AOT_MENU_LAST) ? EN50221_MMI_MENU : EN50221_MMI_LIST; p_mmi->last_object.u.menu.i_choices = 0; p_mmi->last_object.u.menu.ppsz_choices = NULL; if ( l > 0 ) { l--; d++; /* choice_nb */#define GET_FIELD( x ) \ if ( l > 0 ) \ { \ p_mmi->last_object.u.menu.psz_##x \ = MMIGetText( p_access, &d, &l ); \ msg_Dbg( p_access, "MMI " STRINGIFY( x ) ": %s", \ p_mmi->last_object.u.menu.psz_##x ); \ } GET_FIELD( title ); GET_FIELD( subtitle ); GET_FIELD( bottom );#undef GET_FIELD while ( l > 0 ) { char *psz_text = MMIGetText( p_access, &d, &l ); TAB_APPEND( p_mmi->last_object.u.menu.i_choices, p_mmi->last_object.u.menu.ppsz_choices, psz_text ); msg_Dbg( p_access, "MMI choice: %s", psz_text ); } } p_sys->pb_slot_mmi_expected[i_slot] = false; p_sys->pb_slot_mmi_undisplayed[i_slot] = true;}/***************************************************************************** * MMIHandle *****************************************************************************/static void MMIHandle( access_t *p_access, int i_session_id, uint8_t *p_apdu, int i_size ){ int i_tag = APDUGetTag( p_apdu, i_size ); switch ( i_tag ) { case AOT_DISPLAY_CONTROL: { int l; uint8_t *d = APDUGetLength( p_apdu, &l ); if ( l > 0 ) { switch ( *d ) { case DCC_SET_MMI_MODE: if ( l == 2 && d[1] == MM_HIGH_LEVEL ) MMIDisplayReply( p_access, i_session_id ); else msg_Err( p_access, "unsupported MMI mode %02x", d[1] ); break; default: msg_Err( p_access, "unsupported display control command %02x", *d ); break; } } break; } case AOT_ENQ: MMIHandleEnq( p_access, i_session_id, p_apdu, i_size ); break; case AOT_LIST_LAST: case AOT_MENU_LAST: MMIHandleMenu( p_access, i_session_id, i_tag, p_apdu, i_size ); break; case AOT_CLOSE_MMI: SessionSendClose( p_access, i_session_id ); break; default: msg_Err( p_access, "unexpected tag in MMIHandle (0x%x)", i_tag ); }}/***************************************************************************** * MMIClose *****************************************************************************/static void MMIClose( 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; mmi_t *p_mmi = (mmi_t *)p_sys->p_sessions[i_session_id - 1].p_sys; en50221_MMIFree( &p_mmi->last_object ); free( p_sys->p_sessions[i_session_id - 1].p_sys ); msg_Dbg( p_access, "closing MMI session (%d)", i_session_id ); p_sys->pb_slot_mmi_expected[i_slot] = false; p_sys->pb_slot_mmi_undisplayed[i_slot] = true;}/***************************************************************************** * MMIOpen *****************************************************************************/static void MMIOpen( access_t *p_access, int i_session_id ){ access_sys_t *p_sys = p_access->p_sys; mmi_t *p_mmi; msg_Dbg( p_access, "opening MMI session (%d)", i_session_id ); p_sys->p_sessions[i_session_id - 1].pf_handle = MMIHandle; p_sys->p_sessions[i_session_id - 1].pf_close = MMIClose; p_sys->p_sessions[i_session_id - 1].p_sys = malloc(sizeof(mmi_t)); p_mmi = (mmi_t *)p_sys->p_sessions[i_session_id - 1].p_sys; p_mmi->last_object.i_object_type = EN50221_MMI_NONE;}/* * Hardware handling *//***************************************************************************** * InitSlot: Open the transport layer *****************************************************************************/#define MAX_TC_RETRIES 20static int InitSlot( access_t * p_access, int i_slot ){ access_sys_t *p_sys = p_access->p_sys; int i; if ( TPDUSend( p_access, i_slot, T_CREATE_TC, NULL, 0 ) != VLC_SUCCESS ) { msg_Err( p_access, "en50221_Init: couldn't send TPDU on slot %d", i_slot ); return VLC_EGENERIC; } /* This is out of the spec */ for ( i = 0; i < MAX_TC_RETRIES; i++ ) { uint8_t i_tag; if ( TPDURecv( p_access, i_slot, &i_tag, NULL, NULL ) == VLC_SUCCESS && i_tag == T_CTC_REPLY ) { p_sys->pb_active_slot[i_slot] = true; break; } if ( TPDUSend( p_access, i_slot, T_CREATE_TC, NULL, NULL ) != VLC_SUCCESS ) { msg_Err( p_access, "en50221_Init: couldn't send TPDU on slot %d", i_slot ); continue; } } if ( p_sys->pb_active_slot[i_slot] ) { p_sys->i_ca_timeout = 100000; return VLC_SUCCESS; } return VLC_EGENERIC;}/* * External entry points *//***************************************************************************** * en50221_Init : Initialize the CAM for en50221 *****************************************************************************/int en50221_Init( access_t * p_access ){ access_sys_t *p_sys = p_access->p_sys; if( p_sys->i_ca_type & CA_CI_LINK ) { int i_slot; for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ ) { if ( ioctl( p_sys->i_ca_handle, CA_RESET, 1 << i_slot) != 0 ) { msg_Err( p_access, "en50221_Init: couldn't reset slot %d", i_slot ); } } p_sys->i_ca_timeout = 100000; /* Wait a bit otherwise it doesn't initialize properly... */ msleep( 1000000 ); return VLC_SUCCESS; } else { struct ca_slot_info info; info.num = 0; /* We don't reset the CAM in that case because it's done by the * ASIC. */ if ( ioctl( p_sys->i_ca_handle, CA_GET_SLOT_INFO, &info ) < 0 ) { msg_Err( p_access, "en50221_Init: couldn't get slot info" ); close( p_sys->i_ca_handle ); p_sys->i_ca_handle = 0; return VLC_EGENERIC; } if( info.flags == 0 ) { msg_Err( p_access, "en50221_Init: no CAM inserted" ); close( p_sys->i_ca_handle ); p_sys->i_ca_handle = 0; return VLC_EGENERIC; } /* Allocate a dummy sessions */ p_sys->p_sessions[ 0 ].i_resource_id = RI_CONDITIONAL_ACCESS_SUPPORT; /* Get application info to find out which cam we are using and make sure everything is ready to play */ ca_msg_t ca_msg; ca_msg.length=3; ca_msg.msg[0] = ( AOT_APPLICATION_INFO & 0xFF0000 ) >> 16; ca_msg.msg[1] = ( AOT_APPLICATION_INFO & 0x00FF00 ) >> 8; ca_msg.msg[2] = ( AOT_APPLICATION_INFO & 0x0000FF ) >> 0; memset( &ca_msg.msg[3], 0, 253 ); APDUSend( p_access, 1, AOT_APPLICATION_INFO_ENQ, NULL, 0 ); if ( ioctl( p_sys->i_ca_handle, CA_GET_MSG, &ca_msg ) < 0 ) { msg_Err( p_access, "en50221_Init: failed getting message" ); return VLC_EGENERIC; }#if HLCI_WAIT_CAM_READY while( ca_msg.msg[8] == 0xff && ca_msg.msg[9] == 0xff ) { if( !vlc_object_alive (p_access) ) return VLC_EGENERIC; msleep(1); msg_Dbg( p_access, "CAM: please wait" ); APDUSend( p_access, 1, AOT_APPLICATION_INFO_ENQ, NULL, 0 ); ca_msg.length=3; ca_msg.msg[0] = ( AOT_APPLICATION_INFO & 0xFF0000 ) >> 16; ca_msg.msg[1] = ( AOT_APPLICATION_INFO & 0x00FF00 ) >> 8; ca_msg.msg[2] = ( AOT_APPLICATION_INFO & 0x0000FF ) >> 0; memset( &ca_msg.msg[3], 0, 253 ); if ( ioctl( p_sys->i_ca_handle, CA_GET_MSG, &ca_msg ) < 0 ) { msg_Err( p_access, "en50221_Init: failed getting message" ); return VLC_EGENERIC; } msg_Dbg( p_access, "en50221_Init: Got length: %d, tag: 0x%x", ca_msg.length, APDUGetTag( ca_msg.msg, ca_msg.length ) ); }#else if( ca_msg.msg[8] == 0xff && ca_msg.msg[9] == 0xff ) { msg_Err( p_access, "CAM returns garbage as application info!" ); return VLC_EGENERIC; }#endif msg_Dbg( p_access, "found CAM %s using id 0x%x", &ca_msg.msg[12], (ca_msg.msg[8]<<8)|ca_msg.msg[9] ); return VLC_SUCCESS; }}/***************************************************************************** * en50221_Poll : Poll the CAM for TPDUs *****************************************************************************/int en50221_Poll( access_t * p_access ){ access_sys_t *p_sys = p_access->p_sys; int i_slot; int i_session_id; for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ ) { uint8_t i_tag; ca_slot_info_t sinfo; sinfo.num = i_slot; if ( ioctl( p_sys->i_ca_handle, CA_GET_SLOT_INFO, &sinfo ) != 0 ) { msg_Err( p_access, "en50221_Poll: couldn't get info on slot %d", i_slot ); continue; } if ( !(sinfo.flags & CA_CI_MODULE_READY) ) { if ( p_sys->pb_active_slot[i_slot] ) { msg_Dbg( p_access, "en50221_Poll: slot %d has been removed", i_slot ); p_sys->pb_active_slot[i_slot] = false; p_sys->pb_slot_mmi_expected[i_slot] = false; p_sys->pb_slot_mmi_undisplayed[i_slot] = false; /* Close all sessions for this slot. */ for ( i_session_id = 1; i_session_id <= MAX_SESSIONS; i_session_id++ ) { if ( p_sys->p_sessions[i_session_id - 1].i_resource_id && p_sys->p_sessions[i_session_id - 1].i_slot == i_slot ) { if ( p_sys->p_sessions[i_session_id - 1].pf_close != NULL ) { p_sys->p_sessions[i_session_id - 1].pf_close( p_access, i_session_id ); } p_sys->p_sessions[i_session_id - 1].i_resource_id = 0; } } } continue; } else if ( !p_sys->pb_active_slot[i_slot] ) { InitSlot( p_access, i_slot ); if ( !p_sys->pb_active_slot[i_slot] ) { msg_Dbg( p_access, "en50221_Poll: resetting slot %d", i_slot ); if ( ioctl( p_sys->i_ca_handle, CA_RESET, 1 << i_slot) != 0 ) { msg_Err( p_access, "en50221_Poll: couldn't reset slot %d", i_slot ); } continue; } msg_Dbg( p_access, "en50221_Poll: slot %d is active", i_slot ); } if ( !p_sys->pb_tc_has_data[i_slot] ) { if ( TPDUSend( p_access, i_slot, T_DATA_LAST, NULL, NULL ) != VLC_SUCCESS ) { msg_Err( p_access, "en50221_Poll: couldn't send TPDU on slot %d", i_slot ); continue; } if ( TPDURecv( p_access, i_slot, &i_tag, NULL, NULL ) != VLC_SUCCESS ) { msg_Err( p_access, "en50221_Poll: couldn't recv TPDU on slot %d", i_slot ); continue; } } while ( p_sys->pb_tc_has_data[i_slot] ) { uint8_t p_tpdu[MAX_TPDU_SIZE]; int i_size, i_session_size; uint8_t *p_session; if ( TPDUSend( p_access, i_slot, T_RCV, NULL, 0 ) != VLC_SUCCESS ) { msg_Err( p_access, "en50221_Poll: couldn't send TPDU on slot %d", i_slot ); continue; } if ( TPDURecv( p_access, i_slot, &i_tag, p_tpdu, &i_size ) != VLC_SUCCESS ) { msg_Err( p_access, "en50221_Poll: couldn't recv TPDU on slot %d", i_slot ); continue; } p_session = GetLength( &p_tpdu[3], &i_session_size ); if ( i_session_size <= 1 ) continue; p_session++; i_session_size--; if ( i_tag != T_DATA_LAST ) { msg_Err( p_ac
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -