/* * camdevice.c - GStreamer hardware CAM support * 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 <glib.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <linux/dvb/ca.h> #include "camdevice.h" #define GST_CAT_DEFAULT cam_debug_cat CamDevice * cam_device_new (void) { CamDevice *device = g_new0 (CamDevice, 1); device->state = CAM_DEVICE_STATE_CLOSED; return device; } static void reset_state (CamDevice * device) { if (device->filename) { g_free (device->filename); device->filename = NULL; } if (device->fd) { close (device->fd); device->fd = -1; } if (device->cas) { cam_conditional_access_destroy (device->cas); device->cas = NULL; } if (device->mgr) { cam_resource_manager_destroy (device->mgr); device->mgr = NULL; } if (device->info) { cam_application_info_destroy (device->info); device->info = NULL; } if (device->al) { cam_al_destroy (device->al); device->al = NULL; } if (device->sl) { cam_sl_destroy (device->sl); device->sl = NULL; } if (device->tl) { cam_tl_destroy (device->tl); device->tl = NULL; } device->state = CAM_DEVICE_STATE_CLOSED; } void cam_device_free (CamDevice * device) { if (device->state != CAM_DEVICE_STATE_CLOSED) GST_WARNING ("device not in CLOSED state when free'd"); reset_state (device); g_free (device); } gboolean cam_device_open (CamDevice * device, const char *filename) { ca_caps_t ca_caps; int ret; int i; g_return_val_if_fail (device != NULL, FALSE); g_return_val_if_fail (device->state == CAM_DEVICE_STATE_CLOSED, FALSE); g_return_val_if_fail (filename != NULL, FALSE); GST_INFO ("opening ca device %s", filename); ret = open (filename, O_RDWR); if (ret == -1) { GST_ERROR ("can't open ca device: %s", strerror (errno)); return FALSE; } device->fd = ret; ret = ioctl (device->fd, CA_RESET); sleep (1); /* get the capabilities of the CA */ ret = ioctl (device->fd, CA_GET_CAP, &ca_caps); if (ret == -1) { GST_ERROR ("CA_GET_CAP ioctl failed: %s", strerror (errno)); reset_state (device); return FALSE; } device->tl = cam_tl_new (device->fd); device->sl = cam_sl_new (device->tl); device->al = cam_al_new (device->sl); device->mgr = cam_resource_manager_new (); cam_al_install (device->al, CAM_AL_APPLICATION (device->mgr)); device->info = cam_application_info_new (); cam_al_install (device->al, CAM_AL_APPLICATION (device->info)); device->cas = cam_conditional_access_new (); cam_al_install (device->al, CAM_AL_APPLICATION (device->cas)); /* open a connection to each slot */ for (i = 0; i < ca_caps.slot_num; ++i) { CamTLConnection *connection; ret = cam_tl_create_connection (device->tl, i, &connection); if (CAM_FAILED (ret)) { /* just ignore the slot, error out later only if no connection has been * established */ GST_WARNING ("connection to slot %d failed, error: %d", i, ret); continue; } } if (g_hash_table_size (device->tl->connections) == 0) { GST_ERROR ("couldn't connect to any slot"); reset_state (device); return FALSE; } device->state = CAM_DEVICE_STATE_OPEN; device->filename = g_strdup (filename); /* poll each connection to initiate the protocol */ cam_tl_read_all (device->tl, TRUE); return TRUE; } void cam_device_close (CamDevice * device) { g_return_if_fail (device != NULL); g_return_if_fail (device->state == CAM_DEVICE_STATE_OPEN); GST_INFO ("closing ca device %s", device->filename); reset_state (device); } void cam_device_poll (CamDevice * device) { g_return_if_fail (device != NULL); g_return_if_fail (device->state == CAM_DEVICE_STATE_OPEN); cam_tl_read_all (device->tl, TRUE); } gboolean cam_device_ready (CamDevice * device) { g_return_val_if_fail (device != NULL, FALSE); g_return_val_if_fail (device->state == CAM_DEVICE_STATE_OPEN, FALSE); return device->cas->ready; } void cam_device_set_pmt (CamDevice * device, GstStructure * pmt, CamConditionalAccessPmtFlag flag) { g_return_if_fail (device != NULL); g_return_if_fail (device->state == CAM_DEVICE_STATE_OPEN); g_return_if_fail (pmt != NULL); cam_conditional_access_set_pmt (device->cas, pmt, flag); cam_tl_read_all (device->tl, FALSE); }