+ switch( p_sys->i_ca_type )
+ {
+ case CA_CI_LINK:
+ i_ret = en50221_Poll( p_access );
+ break;
+ case CA_CI:
+ i_ret = VLC_SUCCESS;
+ break;
+ default:
+ msg_Err( p_access, "CAMPoll: This should not happen" );
+ break;
+ }
+
+ return i_ret;
+}
+
+#ifdef ENABLE_HTTPD
+/*****************************************************************************
+ * CAMStatus :
+ *****************************************************************************/
+void CAMStatus( access_t * p_access )
+{
+ access_sys_t *p_sys = p_access->p_sys;
+ char *p;
+ ca_caps_t caps;
+ int i_slot, i;
+
+ if ( p_sys->psz_request != NULL && *p_sys->psz_request )
+ {
+ /* Check if we have an undisplayed MMI message : in that case we ignore
+ * the user input to avoid confusing the CAM. */
+ for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ )
+ {
+ if ( p_sys->pb_slot_mmi_undisplayed[i_slot] == true )
+ {
+ p_sys->psz_request = NULL;
+ msg_Dbg( p_access,
+ "ignoring user request because of a new MMI object" );
+ break;
+ }
+ }
+ }
+
+ if ( p_sys->psz_request != NULL && *p_sys->psz_request )
+ {
+ /* We have a mission to accomplish. */
+ en50221_mmi_object_t mmi_object;
+ char *psz_request = p_sys->psz_request;
+ char psz_value[255];
+ int i_slot;
+ bool b_ok = false;
+
+ p_sys->psz_request = NULL;
+
+ if ( HTTPExtractValue( psz_request, "slot", psz_value,
+ sizeof(psz_value) ) == NULL )
+ {
+ p_sys->psz_mmi_info = strdup( "invalid request parameter\n" );
+ goto out;
+ }
+ i_slot = atoi(psz_value);
+
+ if ( HTTPExtractValue( psz_request, "open", psz_value,
+ sizeof(psz_value) ) != NULL )
+ {
+ en50221_OpenMMI( p_access, i_slot );
+ return;
+ }
+
+ if ( HTTPExtractValue( psz_request, "close", psz_value,
+ sizeof(psz_value) ) != NULL )
+ {
+ en50221_CloseMMI( p_access, i_slot );
+ return;
+ }
+
+ if ( HTTPExtractValue( psz_request, "cancel", psz_value,
+ sizeof(psz_value) ) == NULL )
+ {
+ b_ok = true;
+ }
+
+ if ( HTTPExtractValue( psz_request, "type", psz_value,
+ sizeof(psz_value) ) == NULL )
+ {
+ p_sys->psz_mmi_info = strdup( "invalid request parameter\n" );
+ goto out;
+ }
+
+ if ( !strcmp( psz_value, "enq" ) )
+ {
+ mmi_object.i_object_type = EN50221_MMI_ANSW;
+ mmi_object.u.answ.b_ok = b_ok;
+ if ( b_ok == false )
+ {
+ mmi_object.u.answ.psz_answ = strdup("");
+ }
+ else
+ {
+ if ( HTTPExtractValue( psz_request, "answ", psz_value,
+ sizeof(psz_value) ) == NULL )
+ {
+ p_sys->psz_mmi_info = strdup( "invalid request parameter\n" );
+ goto out;
+ }
+
+ mmi_object.u.answ.psz_answ = strdup(psz_value);
+ }
+ }
+ else
+ {
+ mmi_object.i_object_type = EN50221_MMI_MENU_ANSW;
+ if ( b_ok == false )
+ {
+ mmi_object.u.menu_answ.i_choice = 0;
+ }
+ else
+ {
+ if ( HTTPExtractValue( psz_request, "choice", psz_value,
+ sizeof(psz_value) ) == NULL )
+ mmi_object.u.menu_answ.i_choice = 0;
+ else
+ mmi_object.u.menu_answ.i_choice = atoi(psz_value);
+ }
+ }
+
+ en50221_SendMMIObject( p_access, i_slot, &mmi_object );
+ return;
+ }
+
+ /* Check that we have all necessary MMI information. */
+ for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ )
+ {
+ if ( p_sys->pb_slot_mmi_expected[i_slot] == true )
+ return;
+ }
+
+ p = p_sys->psz_mmi_info = malloc( 10000 );
+
+ if ( ioctl( p_sys->i_ca_handle, CA_GET_CAP, &caps ) != 0 )
+ {
+ char buf[1000];
+ strerror_r( errno, buf, sizeof( buf ) );
+ p += sprintf( p, "ioctl CA_GET_CAP failed (%s)\n", buf );
+ goto out;
+ }
+
+ /* Output CA capabilities */
+ p += sprintf( p, "CA interface with %d %s, type:\n<table>", caps.slot_num,
+ caps.slot_num == 1 ? "slot" : "slots" );
+#define CHECK_CAPS( x, s ) \
+ if ( caps.slot_type & (CA_##x) ) \
+ p += sprintf( p, "<tr><td>" s "</td></tr>\n" );
+
+ CHECK_CAPS( CI, "CI high level interface" );
+ CHECK_CAPS( CI_LINK, "CI link layer level interface" );
+ CHECK_CAPS( CI_PHYS, "CI physical layer level interface (not supported)" );
+ CHECK_CAPS( DESCR, "built-in descrambler" );
+ CHECK_CAPS( SC, "simple smartcard interface" );
+#undef CHECK_CAPS
+
+ p += sprintf( p, "</table>%d available %s\n<table>", caps.descr_num,
+ caps.descr_num == 1 ? "descrambler (key)" : "descramblers (keys)" );
+#define CHECK_DESC( x ) \
+ if ( caps.descr_type & (CA_##x) ) \
+ p += sprintf( p, "<tr><td>" STRINGIFY(x) "</td></tr>\n" );
+
+ CHECK_DESC( ECD );
+ CHECK_DESC( NDS );
+ CHECK_DESC( DSS );
+#undef CHECK_DESC
+
+ p += sprintf( p, "</table>" );
+
+ for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ )
+ {
+ ca_slot_info_t sinfo;
+
+ p_sys->pb_slot_mmi_undisplayed[i_slot] = false;
+ p += sprintf( p, "<p>CA slot #%d: ", i_slot );
+
+ sinfo.num = i_slot;
+ if ( ioctl( p_sys->i_ca_handle, CA_GET_SLOT_INFO, &sinfo ) != 0 )
+ {
+ char buf[1000];
+ strerror_r( errno, buf, sizeof( buf ) );
+ p += sprintf( p, "ioctl CA_GET_SLOT_INFO failed (%s)<br>\n", buf );
+ continue;
+ }
+
+#define CHECK_TYPE( x, s ) \
+ if ( sinfo.type & (CA_##x) ) \
+ p += sprintf( p, "%s", s );
+
+ CHECK_TYPE( CI, "high level, " );
+ CHECK_TYPE( CI_LINK, "link layer level, " );
+ CHECK_TYPE( CI_PHYS, "physical layer level, " );
+#undef CHECK_TYPE
+
+ if ( sinfo.flags & CA_CI_MODULE_READY )
+ {
+ en50221_mmi_object_t *p_object = en50221_GetMMIObject( p_access,
+ i_slot );
+
+ p += sprintf( p, "module present and ready<p>\n" );
+ p += sprintf( p, "<form action=index.html method=get>\n" );
+ p += sprintf( p, "<input type=hidden name=slot value=\"%d\">\n",
+ i_slot );
+
+ if ( p_object == NULL )
+ {
+ p += sprintf( p, "<input type=submit name=open value=\"Open session\">\n" );
+ }
+ else
+ {
+ switch ( p_object->i_object_type )
+ {
+ case EN50221_MMI_ENQ:
+ p += sprintf( p, "<input type=hidden name=type value=enq>\n" );
+ p += sprintf( p, "<table border=1><tr><th>%s</th></tr>\n",
+ p_object->u.enq.psz_text );
+ if ( p_object->u.enq.b_blind == false )
+ p += sprintf( p, "<tr><td><input type=text name=answ></td></tr>\n" );
+ else
+ p += sprintf( p, "<tr><td><input type=password name=answ></td></tr>\n" );
+ break;
+
+ case EN50221_MMI_MENU:
+ p += sprintf( p, "<input type=hidden name=type value=menu>\n" );
+ p += sprintf( p, "<table border=1><tr><th>%s</th></tr>\n",
+ p_object->u.menu.psz_title );
+ p += sprintf( p, "<tr><td>%s</td></tr><tr><td>\n",
+ p_object->u.menu.psz_subtitle );
+ for ( i = 0; i < p_object->u.menu.i_choices; i++ )
+ p += sprintf( p, "<input type=radio name=choice value=\"%d\">%s<br>\n", i + 1, p_object->u.menu.ppsz_choices[i] );
+ p += sprintf( p, "</td></tr><tr><td>%s</td></tr>\n",
+ p_object->u.menu.psz_bottom );
+ break;
+
+ case EN50221_MMI_LIST:
+ p += sprintf( p, "<input type=hidden name=type value=menu>\n" );
+ p += sprintf( p, "<input type=hidden name=choice value=0>\n" );
+ p += sprintf( p, "<table border=1><tr><th>%s</th></tr>\n",
+ p_object->u.menu.psz_title );
+ p += sprintf( p, "<tr><td>%s</td></tr><tr><td>\n",
+ p_object->u.menu.psz_subtitle );
+ for ( i = 0; i < p_object->u.menu.i_choices; i++ )
+ p += sprintf( p, "%s<br>\n",
+ p_object->u.menu.ppsz_choices[i] );
+ p += sprintf( p, "</td></tr><tr><td>%s</td></tr>\n",
+ p_object->u.menu.psz_bottom );
+ break;
+
+ default:
+ p += sprintf( p, "<table><tr><th>Unknown MMI object type</th></tr>\n" );
+ }
+
+ p += sprintf( p, "</table><p><input type=submit name=ok value=\"OK\">\n" );
+ p += sprintf( p, "<input type=submit name=cancel value=\"Cancel\">\n" );
+ p += sprintf( p, "<input type=submit name=close value=\"Close Session\">\n" );
+ }
+ p += sprintf( p, "</form>\n" );
+ }
+ else if ( sinfo.flags & CA_CI_MODULE_PRESENT )
+ p += sprintf( p, "module present, not ready<br>\n" );
+ else
+ p += sprintf( p, "module not present<br>\n" );
+ }
+
+out:
+ vlc_mutex_lock( &p_sys->httpd_mutex );
+ p_sys->b_request_mmi_info = false;
+ vlc_cond_signal( &p_sys->httpd_cond );
+ vlc_mutex_unlock( &p_sys->httpd_mutex );