summaryrefslogtreecommitdiffstats
path: root/sys/dvb/camconditionalaccess.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dvb/camconditionalaccess.c')
-rw-r--r--sys/dvb/camconditionalaccess.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/sys/dvb/camconditionalaccess.c b/sys/dvb/camconditionalaccess.c
new file mode 100644
index 00000000..985ce293
--- /dev/null
+++ b/sys/dvb/camconditionalaccess.c
@@ -0,0 +1,208 @@
+/*
+ * camconditionalaccess.c - CAM (EN50221) Conditional Access resource
+ * Copyright (C) 2007 Alessandro Decina
+ *
+ * Authors:
+ * Alessandro Decina <alessandro@nnva.org>
+ *
+ * This program 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include "camutils.h"
+#include "camconditionalaccess.h"
+
+#define GST_CAT_DEFAULT cam_debug_cat
+#define TAG_CONDITIONAL_ACCESS_INFO_ENQUIRY 0x9F8030
+#define TAG_CONDITIONAL_ACCESS_INFO_REPLY 0x9F8031
+#define TAG_CONDITIONAL_ACCESS_PMT 0x9F8032
+
+static CamReturn session_request_impl (CamALApplication * application,
+ CamSLSession * session, CamSLResourceStatus * status);
+static CamReturn open_impl (CamALApplication * application,
+ CamSLSession * session);
+static CamReturn close_impl (CamALApplication * application,
+ CamSLSession * session);
+static CamReturn data_impl (CamALApplication * application,
+ CamSLSession * session, guint tag, guint8 * buffer, guint length);
+
+CamConditionalAccess *
+cam_conditional_access_new ()
+{
+ CamConditionalAccess *cas;
+ CamALApplication *application;
+
+ cas = g_new0 (CamConditionalAccess, 1);
+
+ application = CAM_AL_APPLICATION (cas);
+ _cam_al_application_init (application);
+ application->resource_id = CAM_AL_CONDITIONAL_ACCESS_ID;
+ application->session_request = session_request_impl;
+ application->open = open_impl;
+ application->close = close_impl;
+ application->data = data_impl;
+
+ cas->ready = FALSE;
+
+ return cas;
+}
+
+void
+cam_conditional_access_destroy (CamConditionalAccess * cas)
+{
+ _cam_al_application_destroy (CAM_AL_APPLICATION (cas));
+ g_free (cas);
+}
+
+static CamReturn
+send_ca_pmt (CamConditionalAccess * cas, GObject * pmt,
+ guint8 list_management, guint8 cmd_id)
+{
+ CamReturn ret;
+ guint8 *buffer;
+ guint buffer_size;
+ guint offset;
+ guint8 *ca_pmt;
+ guint ca_pmt_size;
+ GList *walk;
+
+ ca_pmt = cam_build_ca_pmt (pmt, list_management, cmd_id, &ca_pmt_size);
+ cam_al_calc_buffer_size (CAM_AL_APPLICATION (cas)->al,
+ ca_pmt_size, &buffer_size, &offset);
+
+ buffer = g_malloc0 (buffer_size);
+ memcpy (buffer + offset, ca_pmt, ca_pmt_size);
+
+ for (walk = CAM_AL_APPLICATION (cas)->sessions; walk; walk = walk->next) {
+ CamSLSession *session = CAM_SL_SESSION (walk->data);
+
+ ret = cam_al_application_write (CAM_AL_APPLICATION (cas), session,
+ TAG_CONDITIONAL_ACCESS_PMT, buffer, buffer_size, ca_pmt_size);
+ if (CAM_FAILED (ret)) {
+ GST_ERROR ("error sending ca_pmt to slot %d, error: %d",
+ session->connection->slot, ret);
+ continue;
+ }
+ }
+
+ g_free (ca_pmt);
+ g_free (buffer);
+
+ return CAM_RETURN_OK;
+}
+
+CamReturn
+cam_conditional_access_set_pmt (CamConditionalAccess * cas,
+ GObject * pmt, CamConditionalAccessPmtFlag flag)
+{
+ return send_ca_pmt (cas, pmt, flag, 0x01 /* ok_descrambling */ );
+}
+
+static CamReturn
+send_simple (CamConditionalAccess * cas, CamSLSession * session, guint tag)
+{
+ guint8 *buffer;
+ guint offset;
+ guint buffer_size;
+ CamReturn ret;
+
+ cam_al_calc_buffer_size (CAM_AL_APPLICATION (cas)->al, 0, &buffer_size,
+ &offset);
+ buffer = g_malloc (buffer_size);
+
+ ret = cam_al_application_write (CAM_AL_APPLICATION (cas), session,
+ tag, buffer, buffer_size, 0);
+
+ g_free (buffer);
+
+ return ret;
+}
+
+static CamReturn
+send_conditional_access_enquiry (CamConditionalAccess * cas,
+ CamSLSession * session)
+{
+ GST_DEBUG ("sending application cas enquiry");
+ return send_simple (cas, session, TAG_CONDITIONAL_ACCESS_INFO_ENQUIRY);
+}
+
+static CamReturn
+session_request_impl (CamALApplication * application,
+ CamSLSession * session, CamSLResourceStatus * status)
+{
+ *status = CAM_SL_RESOURCE_STATUS_OPEN;
+
+ return CAM_RETURN_OK;
+}
+
+static CamReturn
+open_impl (CamALApplication * application, CamSLSession * session)
+{
+ CamConditionalAccess *cas = CAM_CONDITIONAL_ACCESS (application);
+
+ GST_INFO ("opening conditional access session %d", session->session_nb);
+
+ return send_conditional_access_enquiry (cas, session);
+}
+
+static CamReturn
+close_impl (CamALApplication * application, CamSLSession * session)
+{
+ GST_INFO ("closing conditional access session %d", session->session_nb);
+
+ return CAM_RETURN_OK;
+}
+
+static CamReturn
+handle_conditional_access_info_reply (CamConditionalAccess * cas,
+ CamSLSession * session, guint8 * buffer, guint length)
+{
+ int i;
+ guint16 cas_id;
+
+ GST_INFO ("conditional access info enquiry reply");
+
+ for (i = 0; i < length / 2; ++i) {
+ cas_id = GST_READ_UINT16_BE (buffer);
+
+ GST_INFO ("slot %d, cas_id 0x%x", session->connection->slot, cas_id);
+
+ buffer += 2;
+ }
+
+ cas->ready = TRUE;
+
+ return CAM_RETURN_OK;
+}
+
+static CamReturn
+data_impl (CamALApplication * application, CamSLSession * session,
+ guint tag, guint8 * buffer, guint length)
+{
+ CamReturn ret;
+ CamConditionalAccess *cas = CAM_CONDITIONAL_ACCESS (application);
+
+ switch (tag) {
+ case TAG_CONDITIONAL_ACCESS_INFO_REPLY:
+ ret = handle_conditional_access_info_reply (cas, session, buffer, length);
+ break;
+ default:
+ g_return_val_if_reached (CAM_RETURN_ERROR);
+ }
+
+ return ret;
+}