diff options
author | Alessandro Decina <alessandro@nnva.org> | 2007-10-16 17:38:05 +0000 |
---|---|---|
committer | Zaheer Abbas Merali <zaheerabbas@merali.org> | 2007-10-16 17:38:05 +0000 |
commit | c205b740d4e793354493c4a2663e45670255453c (patch) | |
tree | 3c5d8978e68cf860b69c279e14372ccc144a883c /sys/dvb/camapplication.c | |
parent | 389904f6248c65468175c072441747f51c5a5296 (diff) | |
download | gst-plugins-bad-c205b740d4e793354493c4a2663e45670255453c.tar.gz gst-plugins-bad-c205b740d4e793354493c4a2663e45670255453c.tar.bz2 gst-plugins-bad-c205b740d4e793354493c4a2663e45670255453c.zip |
sys/dvb/: Integrate SoC work done by Alessandro for the Freevo project.
Original commit message from CVS:
patch by: Alessandro Decina
* sys/dvb/Makefile.am:
* sys/dvb/cam.c:
* sys/dvb/cam.h:
* sys/dvb/camapplication.c:
* sys/dvb/camapplication.h:
* sys/dvb/camapplicationinfo.c:
* sys/dvb/camapplicationinfo.h:
* sys/dvb/camconditionalaccess.c:
* sys/dvb/camconditionalaccess.h:
* sys/dvb/camdevice.c:
* sys/dvb/camdevice.h:
* sys/dvb/camresourcemanager.c:
* sys/dvb/camresourcemanager.h:
* sys/dvb/camsession.c:
* sys/dvb/camsession.h:
* sys/dvb/camswclient.c:
* sys/dvb/camswclient.h:
* sys/dvb/camtransport.c:
* sys/dvb/camtransport.h:
* sys/dvb/camutils.c:
* sys/dvb/camutils.h:
* sys/dvb/dvbbasebin.c:
* sys/dvb/dvbbasebin.h:
* sys/dvb/gstdvb.c:
* sys/dvb/gstdvbsrc.c:
* sys/dvb/gstdvbsrc.h:
Integrate SoC work done by Alessandro for the Freevo project.
Adds cam support to the dvb stack in GStreamer and a new
element (actually a bin) called dvbbasebin that integrates
dvbsrc and mpegtsparse to a) handle decryption and b) allow
acquiring multiple channels on same transponder without
knowing pid numbers.
Diffstat (limited to 'sys/dvb/camapplication.c')
-rw-r--r-- | sys/dvb/camapplication.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/sys/dvb/camapplication.c b/sys/dvb/camapplication.c new file mode 100644 index 00000000..03f9e552 --- /dev/null +++ b/sys/dvb/camapplication.c @@ -0,0 +1,292 @@ +/* + * camapplication.c - GStreamer CAM (EN50221) Application Layer + * Copyright (C) 2007 Alessandro Decina + * + * Authors: + * Alessandro Decina <alessandro@nnva.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "camapplication.h" + +#define GST_CAT_DEFAULT cam_debug_cat + +static CamReturn open_session_request_cb (CamSL * sl, + CamSLSession * session, CamSLResourceStatus * status); +static CamReturn session_opened_cb (CamSL * sl, CamSLSession * session); +static CamReturn session_closed_cb (CamSL * sl, CamSLSession * session); +static CamReturn session_data_cb (CamSL * sl, + CamSLSession * session, guint8 * data, guint length); + +static guint +resource_id_hash (gconstpointer key) +{ + guint resource_id = (guint) key; + + if (!CAM_AL_RESOURCE_ID_IS_PUBLIC (resource_id)) { + /* private identifier, leave it as is */ + return resource_id; + } + + /* public identifier, mask out the version number */ + return resource_id >> 6; +} + +CamAL * +cam_al_new (CamSL * sl) +{ + CamAL *al = g_new0 (CamAL, 1); + + al->sl = sl; + al->applications = g_hash_table_new (resource_id_hash, g_direct_equal); + + sl->user_data = al; + sl->open_session_request = open_session_request_cb; + sl->session_opened = session_opened_cb; + sl->session_closed = session_closed_cb; + sl->session_data = session_data_cb; + + return al; +} + +void +cam_al_destroy (CamAL * al) +{ + g_hash_table_destroy (al->applications); + g_free (al); +} + +gboolean +cam_al_install (CamAL * al, CamALApplication * application) +{ + if (g_hash_table_lookup (al->applications, + GINT_TO_POINTER (application->resource_id)) != NULL) + return FALSE; + + application->al = al; + + g_hash_table_insert (al->applications, + GINT_TO_POINTER (application->resource_id), application); + + return TRUE; +} + +gboolean +cam_al_uninstall (CamAL * al, CamALApplication * application) +{ + gboolean ret; + + ret = g_hash_table_remove (al->applications, + GINT_TO_POINTER (application->resource_id)); + + return ret; +} + +CamALApplication * +cam_al_get (CamAL * al, guint resource_id) +{ + return CAM_AL_APPLICATION (g_hash_table_lookup (al->applications, + GINT_TO_POINTER (resource_id))); +} + +void +_cam_al_application_init (CamALApplication * application) +{ + application->sessions = NULL; +} + +void +_cam_al_application_destroy (CamALApplication * application) +{ + g_list_free (application->sessions); +} + +static void +foreach_get_key (gpointer key, gpointer value, gpointer user_data) +{ + GList **lst = (GList **) user_data; + + *lst = g_list_append (*lst, key); +} + +GList * +cam_al_get_resource_ids (CamAL * al) +{ + GList *resource_ids = NULL; + + g_hash_table_foreach (al->applications, foreach_get_key, &resource_ids); + + return resource_ids; +} + +void +cam_al_calc_buffer_size (CamAL * al, guint body_length, + guint * buffer_size, guint * offset) +{ + guint apdu_header_length; + guint8 length_field_len; + + /* get the length of the lenght_field() */ + length_field_len = cam_calc_length_field_size (body_length); + + /* sum the APDU header */ + apdu_header_length = 3 + length_field_len; + + /* chain up to the session layer to get the size of the buffer that can + * contain the whole APDU */ + cam_sl_calc_buffer_size (al->sl, apdu_header_length + body_length, + buffer_size, offset); + + /* add the APDU header to the SPDU offset */ + *offset += apdu_header_length; +} + +CamReturn +cam_al_application_write (CamALApplication * application, + CamSLSession * session, guint tag, guint8 * buffer, guint buffer_size, + guint body_length) +{ + guint length_field_len; + guint apdu_header_length; + guint8 *apdu; + + length_field_len = cam_calc_length_field_size (body_length); + apdu_header_length = 3 + length_field_len; + apdu = (buffer + buffer_size) - body_length - apdu_header_length; + apdu[0] = tag >> 16; + apdu[1] = (tag >> 8) & 0xFF; + apdu[2] = tag & 0xFF; + + cam_write_length_field (&apdu[3], body_length); + + return cam_sl_session_write (session, buffer, buffer_size, + apdu_header_length + body_length); +} + +static CamReturn +open_session_request_cb (CamSL * sl, CamSLSession * session, + CamSLResourceStatus * status) +{ + CamAL *al = CAM_AL (sl->user_data); + CamALApplication *application; + guint resource_id = session->resource_id; + CamReturn ret; + + application = g_hash_table_lookup (al->applications, + GINT_TO_POINTER (resource_id)); + if (application == NULL) { + *status = CAM_SL_RESOURCE_STATUS_NOT_FOUND; + + return CAM_RETURN_OK; + } + + if (CAM_AL_RESOURCE_ID_VERSION (application->resource_id) + < CAM_AL_RESOURCE_ID_VERSION (resource_id)) { + *status = CAM_SL_RESOURCE_STATUS_INVALID_VERSION; + + return CAM_RETURN_OK; + } + + ret = application->session_request (application, session, status); + if (CAM_FAILED (ret)) { + *status = CAM_SL_RESOURCE_STATUS_NOT_FOUND; + + return ret; + } + + if (*status == CAM_SL_RESOURCE_STATUS_OPEN) { + session->user_data = application; + application->sessions = g_list_append (application->sessions, session); + } + + return CAM_RETURN_OK; +} + +static CamReturn +session_opened_cb (CamSL * sl, CamSLSession * session) +{ + CamALApplication *application; + + application = CAM_AL_APPLICATION (session->user_data); + if (application == NULL) { + GST_ERROR ("session is established but has no application"); + return CAM_RETURN_APPLICATION_ERROR; + } + + return application->open (application, session); +} + +static CamReturn +session_closed_cb (CamSL * sl, CamSLSession * session) +{ + CamALApplication *application; + CamReturn ret; + GList *walk; + + application = CAM_AL_APPLICATION (session->user_data); + if (application == NULL) { + GST_ERROR ("session is established but has no application"); + return CAM_RETURN_APPLICATION_ERROR; + } + + ret = application->close (application, session); + for (walk = application->sessions; walk; walk = g_list_next (walk)) { + CamSLSession *s = CAM_SL_SESSION (walk->data); + + if (s->session_nb == session->session_nb) { + application->sessions = g_list_delete_link (application->sessions, walk); + break; + } + } + + return ret; +} + +static CamReturn +session_data_cb (CamSL * sl, CamSLSession * session, guint8 * data, guint size) +{ + CamALApplication *application; + guint tag = 0; + guint8 length_field_len; + guint length; + guint i; + + application = CAM_AL_APPLICATION (session->user_data); + if (application == NULL) { + GST_ERROR ("session is established but has no application"); + return CAM_RETURN_APPLICATION_ERROR; + } + + if (size < 4) { + GST_ERROR ("invalid APDU length %d", size); + return CAM_RETURN_APPLICATION_ERROR; + } + + for (i = 0; i < 3; ++i) + tag = (tag << 8) | data[i]; + + length_field_len = cam_read_length_field (&data[3], &length); + + if (length != size - 4) { + GST_ERROR ("unexpected APDU length %d expected %d", length, size); + + return CAM_RETURN_APPLICATION_ERROR; + } + + return application->data (application, session, + tag, data + 3 + length_field_len, length); +} |