SASC
DVBSoftCAM

plugin_cam.c File Reference

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <linux/dvb/ca.h>
#include <linux/dvb/dmx.h>
#include "../sc/include/vdr/plugin.h"
#include "../sc/include/vdr/dvbdevice.h"
#include "../sc/include/vdr/sclink.h"
#include "../sc/include/vdr/channels.h"
#include "../sc/include/vdr/tools.h"
#include "../sc/sasccam.h"
#include "process_req.h"
#include "plugin_getsid.h"
#include "plugin_cam.h"
#include "plugin_msg.h"
#include "debug.h"

Go to the source code of this file.

Classes

struct  cam_epid
struct  fdmap_list
struct  scopt_list

Defines

#define PLUGIN_ID   28
#define DBG_NAME   "CAM"
#define ll_find_elem(elem, lhead, item, value, type)

Functions

char * get_camdir ()
 LIST_HEAD (sclist)
 LIST_HEAD (pid_empty_queue)
 LIST_HEAD (pid_list)
 LIST_HEAD (fdmap_empty_queue)
 LIST_HEAD (fdmap_ll)
void update_keys (int, unsigned char, int, unsigned char *, int)
void SetCAMPrint (const char *_plugin_name, unsigned int plugin_id, unsigned int _print_level, unsigned int *_log_level)
static int init_sc (void)
static struct sc_data * find_sc_from_adpt (int adapter)
void cam_del_pid (struct sc_data *sc_data, struct cam_epid *cam_epid)
void _SetCaDescr (int adapter, ca_descr_t *ca_descr)
void _SetCaPid (int adapter, ca_pid_t *ca_pid)
void process_cam (struct msg *msg, unsigned int priority)
unsigned int crc32 (const unsigned char *d, int len, unsigned int crc)
static int parse_ca (unsigned char *buf, int len)
static void replace_cat (unsigned char *buf, int len, int pid)
static void dmxread_call (struct parser_cmds *pc, struct poll_ll *fdptr, cmdret_t *result, int *ret, unsigned long int cmd, unsigned char *data)
static void dmxioctl_call (struct parser_cmds *pc, struct poll_ll *fdptr, cmdret_t *result, int *ret, unsigned long int cmd, unsigned char *data)
static void dmxclose_call (struct parser_cmds *pc, struct poll_ll *fdptr, cmdret_t *result, int *ret, unsigned long int cmd, unsigned char *data)
void connect_cam (struct parser_adpt *pc_all)
static void launch_cam ()
static void shutdown_cam ()
static void usermsg_cam (char *str)
static struct option * parseopt_cam (arg_enum_t cmd)
int __attribute__ ((constructor))

Variables

static int cam_opt = 0
static int opt_budget = 0
static int opt_fixcat = 1
static char opt_camdir [256] = {"./sc_files"}
static char opt_extau [256]
static struct option Cam_Opts []
struct scopt_list scopts [32] = {{{'\0'}}}
static cPlugin * sc = NULL
static char scCap [80]
const char * externalAU
static unsigned int crc_table [256]
static struct plugin_cmd plugin_cmds

Define Documentation

#define DBG_NAME   "CAM"

Definition at line 26 of file plugin_cam.c.

Referenced by init_sc().

#define ll_find_elem (   elem,
  lhead,
  item,
  value,
  type 
)
Value:
{  \
  struct list_head *lptr;                               \
  type *ptr;                                            \
  elem = NULL;                                          \
  list_for_each(lptr, &lhead) {                         \
    ptr = list_entry(lptr, type);                       \
    if(ptr->item == value)                              \
      elem = ptr;                                       \
  }                                                     \
}

Definition at line 29 of file plugin_cam.c.

Referenced by close_demux(), dmxclose_call(), dmxioctl_call(), dmxread_call(), find_csa_from_adpt(), find_csa_from_rb(), find_sc_from_adpt(), process_cam(), process_scan(), process_ts(), read_pat(), read_pmt(), read_sid(), set_demux(), start(), and update_keys().

#define PLUGIN_ID   28

Definition at line 25 of file plugin_cam.c.

Referenced by init_sc().


Function Documentation

int __attribute__ ( (constructor)  )

Definition at line 691 of file plugin_cam.c.

References plugin_cmd::list, list_add_tail(), and plugin_cmdlist.

{
  list_add_tail(&plugin_cmds.list, &plugin_cmdlist);
  return 0;
}
void _SetCaDescr ( int  adapter,
ca_descr_t *  ca_descr 
)

Definition at line 155 of file plugin_cam.c.

References sc_data::cafd, dprintf0, dprintf1, find_sc_from_adpt(), MSG_CAMUPDATE, MSG_LOW_PRIORITY, msg_send, NULL, update_keys(), and sc_data::virt.

Referenced by start_loopbackca().

                                                    {
  struct sc_data *sc_data = find_sc_from_adpt(adapter);
  unsigned long cadata;
  if(!sc_data)
    return;
  dprintf1("Sending key(%d) %c %d %x%x...%x\n", sc_data->cafd,
           (ca_descr->parity ? 'O' : 'E'), ca_descr->index,
           ca_descr->cw[0], ca_descr->cw[1], ca_descr->cw[7]);
  
  cadata = (ca_descr->index << 1) | (ca_descr->parity==0 ? 0 : 1);
  msg_send(MSG_LOW_PRIORITY, MSG_CAMUPDATE, sc_data->virt, (void *)cadata);
  if(sc_data->cafd >= 0) {
    //Using a real CA
    ca_descr_t tmp_dscr;
    memcpy(&tmp_dscr, ca_descr, sizeof(tmp_dscr));
    tmp_dscr.index--;
    if(ioctl(sc_data->cafd,CA_SET_DESCR,&tmp_dscr)<0) {
      dprintf0("CA_SET_DESCR failed (%s)\n", strerror(errno));
    } else {
      update_keys(sc_data->virt, 'N', ca_descr->index, NULL, 0);
    }
  } else {
    update_keys(sc_data->virt, (ca_descr->parity==0) ? 'E' : 'O',
                ca_descr->index, ca_descr->cw, 0);
  }
}
void _SetCaPid ( int  adapter,
ca_pid_t *  ca_pid 
)

Definition at line 182 of file plugin_cam.c.

References sc_data::cafd, dprintf0, dprintf1, find_sc_from_adpt(), NULL, update_keys(), and sc_data::virt.

Referenced by start_loopbackca().

                                              {
  struct sc_data *sc_data = find_sc_from_adpt(adapter);
  if(!sc_data)
    return;
  dprintf1("Sending (%d) key P %d PID: %d\n", sc_data->virt, ca_pid->index,
           ca_pid->pid);
  if(sc_data->cafd >= 0) {
    //Using a real CA
    ca_pid_t tmp_pid;
    memcpy(&tmp_pid, ca_pid, sizeof(tmp_pid));
    tmp_pid.index--;
    if(ioctl(sc_data->cafd,CA_SET_PID,&tmp_pid) < 0 && tmp_pid.index > 0) {
      dprintf0("CA_SET_PID failed (%s)\n", strerror(errno));
    }
  }
  update_keys(sc_data->virt, 'P', ca_pid->index, NULL, ca_pid->pid);
}
void cam_del_pid ( struct sc_data *  sc_data,
struct cam_epid *  cam_epid 
)

Definition at line 135 of file plugin_cam.c.

References sascCam::AddPrg(), sc_data::cam, cam_epid::epid, cam_epid::list, list_add(), list_del(), list_entry, list_for_each, MAXDPIDS, and cam_epid::sid.

Referenced by process_cam().

                                                                     {
  //struct ScLink link;
  struct list_head *ptr;
  struct cam_epid *cam_epid1;
  int epidlist[MAXDPIDS], *epidptr = epidlist;
  list_del(&cam_epid->list);
  list_for_each(ptr, &pid_list) {
    cam_epid1 = list_entry(ptr, struct cam_epid);
    if(cam_epid1->sid == cam_epid->sid)
      *(epidptr++) = cam_epid1->epid;
  }
  *epidptr = 0;
  sc_data->cam->AddPrg(cam_epid->sid,epidlist,0,0);
  //PrepareScLink(&link, sc_data->dev, OP_DELPID);
  //link.data.pids.pid=cam_epid->epid;
  //link.data.pids.type=cam_epid->type;
  //DoScLinkOp(sc, &link);
  list_add(&cam_epid->list, &pid_empty_queue);
}
void connect_cam ( struct parser_adpt *  pc_all)

Definition at line 526 of file plugin_cam.c.

References ATTACH_CALLBACK, sc_data::cafd, sc_data::cam, cmd, parser_cmds::common, parser_adpt::demux, dmxclose_call(), dmxioctl_call(), dmxread_call(), dprintf0, free, parser_adpt::frontend, init_sc(), sc_data::list, list_add(), list_entry, list_for_each, open(), opt_budget, opt_fixcat, plugin_cmd::plugin, plugin_cmdlist, PLUGIN_GETSID, parser_cmds::post_read, parser_cmds::pre_close, parser_cmds::pre_ioctl, sc_data::real, common_data::real_adapt, scCap, plugin_cmd::send_msg, cPlugin::SetupParse(), sc_data::valid, sc_data::virt, and common_data::virt_adapt.

{
  int cardnum = pc_all->frontend->common->real_adapt;
  struct list_head *ptr;
  char *cadev;
  char tmpstr[5];
  struct sc_data *sc_data;

  if(! sc)
    if(! init_sc())
      return;
 
  sc_data = (struct sc_data *)malloc(sizeof(struct sc_data));
  memset(sc_data, 0, sizeof(struct sc_data));


  sprintf(tmpstr," %d",cardnum+1);
  strncat(scCap, tmpstr, 80);
  sc->SetupParse("ScCaps",scCap);

  sc_data->valid = 0;
  sc_data->virt = pc_all->frontend->common->virt_adapt;
  sc_data->real = cardnum;
  sc_data->cam = new sascCam(cardnum);

  if (opt_budget) {
    sc_data->cafd = -1;
  } else {
    asprintf(&cadev, "/dev/dvb/adapter%d/ca0", cardnum);
    sc_data->cafd = open(cadev, O_RDWR|O_NONBLOCK);
    if (sc_data->cafd >= 0) {
      ca_caps_t ca_caps;
      if (ioctl(sc_data->cafd, CA_GET_CAP, &ca_caps) == 0 &&
          ca_caps.slot_num > 0 && (ca_caps.slot_type & CA_CI_LINK)) {
        dprintf0("Found a FF card\n");
      } else {
        sc_data->cafd = -1;
      }
    }
    free(cadev);
  }
  list_add(&sc_data->list, &sclist);
  if(opt_fixcat) {
    ATTACH_CALLBACK(&pc_all->demux->pre_ioctl, dmxioctl_call, 0);
    ATTACH_CALLBACK(&pc_all->demux->post_read, dmxread_call, 0);
    ATTACH_CALLBACK(&pc_all->demux->pre_close, dmxclose_call, 0);
  }
  list_for_each(ptr, &plugin_cmdlist) {
    struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd);
    if(cmd->plugin == PLUGIN_GETSID) {
      cmd->send_msg(pc_all->frontend, 1);
      break;
    }
  }
}
unsigned int crc32 ( const unsigned char *  d,
int  len,
unsigned int  crc 
)

Definition at line 409 of file plugin_cam.c.

References crc_table, and i.

Referenced by replace_cat().

{
   register int i;
   const unsigned char *u=(unsigned char*)d; // Saves '& 0xff'

   for (i=0; i<len; i++)
      crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)];

   return crc;
}
static void dmxclose_call ( struct parser_cmds *  pc,
struct poll_ll *  fdptr,
cmdret_t *  result,
int *  ret,
unsigned long int  cmd,
unsigned char *  data 
) [static]

Definition at line 514 of file plugin_cam.c.

References poll_ll::fd, fd, fdmap_list::list, list_add(), list_del(), and ll_find_elem.

Referenced by connect_cam().

{
  struct fdmap_list *fd_map;
  ll_find_elem(fd_map, fdmap_ll, fd, fdptr->fd, struct fdmap_list);
  if(fd_map) {
    list_del(&fd_map->list);
    list_add(&fd_map->list, &fdmap_empty_queue);
  }
}
static void dmxioctl_call ( struct parser_cmds *  pc,
struct poll_ll *  fdptr,
cmdret_t *  result,
int *  ret,
unsigned long int  cmd,
unsigned char *  data 
) [static]

Definition at line 484 of file plugin_cam.c.

References fdmap_list::fd, poll_ll::fd, fd, fdmap_list::list, list_add(), ll_find_elem, fdmap_list::pid, and pop_entry_from_queue.

Referenced by connect_cam().

{
  struct fdmap_list *fd_map;
  int pid;
  ll_find_elem(fd_map, fdmap_ll, fd, fdptr->fd, struct fdmap_list);
  if(fd_map)
    return;
  if(cmd == DMX_SET_FILTER) {
    struct dmx_sct_filter_params *dmx =
           (struct dmx_sct_filter_params *)data;
    pid = dmx->pid;
  } else if(cmd == DMX_SET_PES_FILTER) {
    struct dmx_pes_filter_params *dmx =
           (struct dmx_pes_filter_params *)data;
    pid = dmx->pid;
    //supporting PES filters means parsing dvr.  let's skip that for now.
    return;
  } else {
    return;
  }
  //This is a hack.  We need to get the pmt handels from the pat like getsid
  if(pid > 100)
    return;
  pop_entry_from_queue(fd_map, &fdmap_empty_queue, struct fdmap_list);
  fd_map->fd = fdptr->fd;
  fd_map->pid = pid;
  list_add(&fd_map->list, &fdmap_ll);
}
static void dmxread_call ( struct parser_cmds *  pc,
struct poll_ll *  fdptr,
cmdret_t *  result,
int *  ret,
unsigned long int  cmd,
unsigned char *  data 
) [static]

Definition at line 473 of file plugin_cam.c.

References poll_ll::fd, fd, ll_find_elem, parser_cmds::mmap, fdmap_list::pid, and replace_cat().

Referenced by connect_cam().

{
  struct fdmap_list *fd_map;
  ll_find_elem(fd_map, fdmap_ll, fd, fdptr->fd, struct fdmap_list);
  if(! fd_map)
    return;
  replace_cat(pc->mmap, *ret, fd_map->pid);
}
static struct sc_data* find_sc_from_adpt ( int  adapter) [static, read]

Definition at line 129 of file plugin_cam.c.

References ll_find_elem, and sc_data::real.

Referenced by _SetCaDescr(), _SetCaPid(), and process_cam().

                                                      {
  struct sc_data *sc_data;
  ll_find_elem(sc_data, sclist, real, adapter, struct sc_data);
  return sc_data;
}
char* get_camdir ( )

Definition at line 44 of file plugin_cam.c.

References opt_camdir.

Referenced by connect_scan().

{ return opt_camdir;}
static int init_sc ( void  ) [static]

Definition at line 90 of file plugin_cam.c.

References _dbglvl, cmd, scopt_list::cmd, DBG_NAME, cPlugin::Description(), dprintf0, i, cPlugin::Initialize(), PLUGIN_ID, scCap, SetCAMPrint(), cPlugin::SetupParse(), cPlugin::Start(), scopt_list::value, VDRPluginCreator(), and cPlugin::Version().

Referenced by connect_cam().

                         {
  sc=(cPlugin *)VDRPluginCreator();

  dprintf0("initializing plugin: SoftCam (%s): %s\n", sc->Version(), sc->Description());
#ifndef __x86_64__
  //I have no idea why 64bit systems crash with the redirect
  SetCAMPrint(DBG_NAME, PLUGIN_ID, 0, &_dbglvl);
#endif
  if (!sc->Initialize()) {
    dprintf0("Failed to initialize sc\n");
    return false;
  }
  dprintf0("starting plugin:\n");
  if (!sc->Start()) {
    dprintf0("Failed to start sc plugin\n");
    return false;
  }

  memset(scCap, 0, 80);
  sc->SetupParse("LoggerActive","2");
#ifdef USE_AUXSERVER
  sc->SetupParse("Nagra2.AuxServerEnable", "1");
  #ifdef AUXSERVER_PORT
  sc->SetupParse("Nagra2.AuxServerPort", AUXSERVER_PORT);
  #endif
  #ifdef AUXSERVER_HOST
  sc->SetupParse("Nagra2.AuxServerAddr", AUXSERVER_HOST);
  #endif
  #ifdef AUXSERVER_PASSWD
  sc->SetupParse("Nagra2.AuxServerPass", AUXSERVER_PASSWD);
  #endif
#endif
  for(int i = 0; i < 32 && scopts[i].cmd[0] != '\0'; i++) {
    dprintf0("Setting SC options: %s = %s\n", scopts[i].cmd, scopts[i].value);
    sc->SetupParse(scopts[i].cmd, scopts[i].value);
  }
  return true;
}
static void launch_cam ( ) [static]

Definition at line 582 of file plugin_cam.c.

References MSG_HOUSEKEEPING, MSG_LOW_PRIORITY, MSG_RECURRING, msg_send_replace(), and NULL.

{
  //Call housecleaning every 60 seconds
  msg_send_replace(MSG_LOW_PRIORITY, MSG_HOUSEKEEPING, 0, NULL,
                   60, MSG_RECURRING);
}
LIST_HEAD ( sclist  )
LIST_HEAD ( pid_list  )
LIST_HEAD ( fdmap_empty_queue  )
LIST_HEAD ( fdmap_ll  )
LIST_HEAD ( pid_empty_queue  )
static int parse_ca ( unsigned char *  buf,
int  len 
) [static]

Definition at line 420 of file plugin_cam.c.

References count.

Referenced by replace_cat().

{
  int count, pos = 0;
  int found = 0;
  while (pos < len) {
    count = buf[pos+1] +2;
    //printf("Found CA: %d (len %d)\n", buf[pos], count);
    if(buf[pos] == 0x09) {
      buf[pos] = 0xff;
      found++;
    }
    pos+=count;
  }
  return found;
}
static struct option* parseopt_cam ( arg_enum_t  cmd) [static, read]

Definition at line 627 of file plugin_cam.c.

References ARG_HELP, ARG_INIT, cam_opt, Cam_Opts, scopt_list::cmd, dprintf0, externalAU, i, NULL, opt_budget, opt_camdir, opt_extau, and opt_fixcat.

{
  if(cmd == ARG_INIT) {
    return Cam_Opts;
  }
  if(cmd == ARG_HELP) {
    printf("   --cam-budget      : Force budget card mode\n");
    printf("   --cam-dir <dir>   : Set directory for sc files (default ./sc_files)\n");
    printf("   --cam-nofixcat    : Don't remove cat entries\n");
    printf("   --cam-extau <cmd> : Execute cmd to retrieve updated keys\n");
    printf("   --cam-scopts <cmd>: Set sc options (opt=value)\n");
    return NULL;
  }
  if(! cam_opt)
    return NULL;

  switch(cam_opt) {
    case 'b':
      opt_budget = 1;
      break;
    case 'd':
      strncpy(opt_camdir, optarg, sizeof(opt_camdir)-1);
      opt_camdir[sizeof(opt_camdir)-1]=0;
      break;
    case 'e':
      strncpy(opt_extau, optarg, sizeof(opt_extau)-1);
      opt_extau[sizeof(opt_extau)-1]=0;
      externalAU = opt_extau;
    case 'f':
      opt_fixcat = 0;
      break;
    case 'o':
      {
        int i;
        for(i = 0; i < 32 && scopts[i].cmd[0] != '\0'; i++)
          ;
        if(i == 32) {
          dprintf0("Too many SC options.  Ignoring: %s\n", optarg);
        } else {
          char *pos =optarg;
          while(*pos != '=' && *pos != '\0')
            pos++;
          if(*pos == '\0') {
            dprintf0("Could not parse SC argument: %s\n", optarg);
          } else {
            memcpy(scopts[i].cmd, optarg, pos - optarg);
            memcpy(scopts[i].value, pos+1, strlen(optarg) - (1+pos - optarg));
printf("here: %s %s %d\n", scopts[i].cmd, scopts[i].value, i);
            if(i != 31)
              scopts[i+1].cmd[0] = '\0';
          }
        }
        break;
      }
  }
  //must reset cam_opt after every call
  cam_opt = 0;
  return NULL;
}
void process_cam ( struct msg *  msg,
unsigned int  priority 
)

Definition at line 200 of file plugin_cam.c.

References cListBase::Add(), sascCam::AddPrg(), BCD2INT(), sid_msg::ca, sid_msg::calen, sc_data::cam, cam_del_pid(), Channels, msg::data, cListBase::Del(), cam_epid::delayclose, dprintf0, dprintf1, sid_msg::epid, cam_epid::epid, sid_msg::epid_count, find_sc_from_adpt(), cList< T >::First(), free_sidmsg(), nit_data::frequency, cPlugin::Housekeeping(), i, msg::id, nit_data::is_east, cList< T >::Last(), cam_epid::list, list_add(), list_empty(), list_entry, list_for_each, ll_find_elem, MAXAPIDS, MAXDPIDS, MSG_ADDSID, MSG_HOUSEKEEPING, MSG_PROCESSED, MSG_REMOVESID, MSG_RESETSID, cList< T >::Next(), sid_msg::nit, NULL, nit_data::orbit, nit_data::polarization, pop_entry_from_queue, cChannel::SetCableTransponderData(), cChannel::SetId(), cChannel::SetPids(), cChannel::SetSatTransponderData(), sid_msg::sid, cChannel::Sid(), cam_epid::sid, sascCam::Stop(), nit_data::symbolrate, sascCam::Tune(), cam_epid::type, nit_data::type, msg::type, update_keys(), sc_data::valid, and sc_data::virt.

{
  struct list_head *ptr;
  struct cam_epid *cam_epid;
  struct sid_msg *sidmsg;
  int match = 0;
  cChannel *ch;

  int vpid = 0, ppid = 0, tpid = 0, dcnt = 0;
  int apid[MAXAPIDS], dpid[MAXDPIDS];

  //struct ScLink link;
  struct sc_data *sc_data;

  if (msg->type == MSG_RESETSID) {
    sc_data = find_sc_from_adpt(msg->id);
    assert(sc_data);
    dprintf1("Got MSG_RESETSID\n");
    while(! list_empty(&pid_list)) {
      cam_epid = list_entry(pid_list.next, struct cam_epid);
      cam_del_pid(sc_data, cam_epid);
    }
    sc_data->cam->Stop();
    //PrepareScLink(&link, sc_data->dev, OP_TUNE);
    //link.data.tune.source=0;
    //link.data.tune.transponder=0;
    //DoScLinkOp(sc, &link);
    //sc_data->dev->SetChannelDevice(0, 0);
    update_keys(sc_data->virt, 'I', 0, NULL, 0);
    sc_data->valid = 0;
    msg->type = MSG_PROCESSED;
    return;
  }
  if (msg->type == MSG_REMOVESID) {
    unsigned int sid = 0xffff & (unsigned long)(msg->data);
    dprintf1("Got MSG_REMOVESID with sid: %d\n", sid);
    //delay removal of pids so we can continue to watch for key-rolls
    list_for_each(ptr, &pid_list) {
      cam_epid = list_entry(ptr, struct cam_epid);
      if(cam_epid->sid == sid) {
        dprintf1("Mapped sid to %d\n", cam_epid->epid);
        cam_epid->delayclose = 1;
        //update_keys('C', 0, NULL, cam_epid->epid);
        //cam_del_pid(sc_data, cam_epid);
      }
    }
    msg->type = MSG_PROCESSED;
    return;
  }
  if (msg->type == MSG_HOUSEKEEPING) {
    sc->Housekeeping();
    msg->type = MSG_PROCESSED;
    return;
  }
  if (msg->type != MSG_ADDSID)
    return;

  sc_data = find_sc_from_adpt(msg->id);
  assert(sc_data);
  sidmsg = (struct sid_msg *)msg->data;

  if (sidmsg->calen == 0) {
    free_sidmsg(sidmsg);
    return;
  }
  for(ch=Channels.First(); ch; ch=Channels.Next(ch)) {
    if((unsigned int)ch->Sid() == sidmsg->sid) {
      match = 1;
      break;
    }
  }
  if(match) {
    //if the sid is the same as last time, and a tune hasn't happened, we're
    //already good to go
    if(sc_data->valid) {
      list_for_each(ptr, &pid_list) {
        cam_epid = list_entry(ptr, struct cam_epid);
        if(cam_epid->delayclose && cam_epid->sid == sidmsg->sid) {
          dprintf1("Reenabling delayed-closed sid: %d\n", sidmsg->sid);
          cam_epid->delayclose = 0;
        }
      }
      free_sidmsg(sidmsg);
      return;
    }
  } else {
    //the sid is different, but we may be on the same transponder, so clear
    //all delayed-close pids before proceeding
    while (1) {
      ll_find_elem(cam_epid, pid_list, delayclose, 1, struct cam_epid);
      if(cam_epid == NULL)
        break;
      dprintf1("Mapped sid %d to epid %d\n", cam_epid->sid, cam_epid->epid);
      update_keys(sc_data->virt, 'C', 0, NULL, cam_epid->epid);
      for(ch=Channels.First(); ch; ch=Channels.Next(ch)) {
        if((unsigned int)ch->Sid() == cam_epid->sid) {
          Channels.Del(ch);
          break;
        }
      }
      cam_del_pid(sc_data, cam_epid);
    }
  }
  msg->type = MSG_PROCESSED;

  //create new channel
  memset(apid, 0, sizeof(int)*MAXAPIDS);
  memset(dpid, 0, sizeof(int)*MAXDPIDS);
  ch = new cChannel();

  ch->SetId(0, 1, sidmsg->sid, 0);
  if(sidmsg->nit.type==0x43) { //set source type to Satellite.  Use orbit and E/W data
    int source = 0x8000 | (BCD2INT(sidmsg->nit.orbit) & 0x7ff) | ((int)sidmsg->nit.is_east << 11);
    static char Polarizations[] = { 'h', 'v', 'l', 'r' };
    ch->SetSatTransponderData(source, BCD2INT(sidmsg->nit.frequency)/100, Polarizations[sidmsg->nit.polarization], BCD2INT(sidmsg->nit.symbolrate)/10, 0);
    }
  else if(sidmsg->nit.type==0x44) { //set source type to Cable
    ch->SetCableTransponderData(0x4000, BCD2INT(sidmsg->nit.frequency)/10, 0, BCD2INT(sidmsg->nit.symbolrate)/10, 0);
    }
  dcnt = (MAXDPIDS >= sidmsg->epid_count) ?
            sidmsg->epid_count : MAXDPIDS;
  memcpy(dpid, sidmsg->epid, sizeof(int)*dcnt);
  ch->SetPids(vpid, ppid, apid, NULL, dpid, NULL, tpid);

  if(! sc_data->valid) {
    sc_data->valid = 1;
    while(Channels.First())
      Channels.Del(Channels.First());
  }

  Channels.Add(ch);
  if(Channels.First() == Channels.Last()) {
    sc_data->cam->Tune(ch);
    //This is the first channel
    //PrepareScLink(&link, sc_data->dev, OP_TUNE);
    //link.data.tune.source=ch->Source();
    //link.data.tune.transponder=ch->Transponder();
    //dprintf0("Sending Tune cmd to SC\n");
    //DoScLinkOp(sc, &link);
    dprintf0("SC completed  Tune cmd\n");
  }

  int i, epidlist[MAXDPIDS], *epidptr = epidlist;
  for(i=0; i < sidmsg->epid_count && i < MAXDPIDS; i++) {
    pop_entry_from_queue(cam_epid, &pid_empty_queue, struct cam_epid);
    cam_epid->delayclose = 0;
    cam_epid->epid = sidmsg->epid[i];
    cam_epid->type = 5; //epid->type;
    cam_epid->sid = sidmsg->sid;
    list_add(&cam_epid->list, &pid_list);
    *(epidptr++) = sidmsg->epid[i];
    dprintf1("Adding pid %d for sid %d to pidlist\n", cam_epid->epid, cam_epid->sid);
    //PrepareScLink(&link, sc_data->dev, OP_ADDPID);
    //link.data.pids.pid=epid->epid;
    //link.data.pids.type = 5; //epid->type;
    //DoScLinkOp(sc, &link);
  }
  *epidptr = 0;
  sc_data->cam->AddPrg(sidmsg->sid,epidlist,sidmsg->ca,sidmsg->calen);
  free_sidmsg(sidmsg);
}
static void replace_cat ( unsigned char *  buf,
int  len,
int  pid 
) [static]

Definition at line 436 of file plugin_cam.c.

References count, crc32(), dprintf1, and parse_ca().

Referenced by dmxread_call().

{
  int desc_len, count;
  int found = 0;
  int pos = 0;
  if(len > 0) {
    if (buf[0] == 0x02) {
      count = (((buf[1] & 0x03) << 8) | buf[2]) + 3 - 4;
      desc_len = ((buf[10] & 0x03) << 8) | buf[11];
      if(desc_len > len - 12 || count > len) {
        //bogus data
        return;
      }
      found+=parse_ca(buf+12, desc_len);
      //handle epids here
      for(pos = 12 + desc_len; pos < count;) {
        desc_len = ((buf[pos+3] & 0x03) << 8) | buf[pos+4];
        if(pos+desc_len +5 > count) {
          //bogus data
          return;
        }
        found+=parse_ca(buf+pos+5, desc_len);
        pos += desc_len + 5;
      }
      if(found) {
        //compute CRC32
        int crc = crc32(buf, len-4, 0xFFFFFFFF);
        buf[len-4] = (crc >> 24) & 0xff;
        buf[len-3] = (crc >> 16) & 0xff;
        buf[len-2] = (crc >> 8) & 0xff;
        buf[len-1] = (crc >> 0) & 0xff;
      }
      dprintf1("Replaced %d cas on pid %d (len=%d)\n", found, pid, len);
    }
  }
}
void SetCAMPrint ( const char *  _plugin_name,
unsigned int  plugin_id,
unsigned int  _print_level,
unsigned int *  _log_level 
)

Definition at line 15 of file log.cpp.

References log_level, LogPrintSasc(), plugin_name, print_level, and cLogging::SetLogPrint().

Referenced by init_sc().

                                                                                                                        {
  plugin_name = _plugin_name;
  id = plugin_id;
  log_level = _log_level;
  print_level = _print_level;
  cLogging::SetLogPrint(&LogPrintSasc);
}
static void shutdown_cam ( ) [static]

Definition at line 589 of file plugin_cam.c.

References sc_data::cafd, list_entry, list_for_each, NULL, sc, cPlugin::Stop(), and sc_data::valid.

{
  if (sc)
  {
    sc->Stop();
    struct sc_data *sc_data;
    struct list_head *ptr;
    list_for_each(ptr, &sclist) {
      sc_data = list_entry(ptr, struct sc_data);
      if (sc_data->cafd >= 0) {
        close(sc_data->cafd);
        sc_data->cafd = -1;
        sc_data->valid = 0;
      }
    }
    delete sc;
    sc = NULL;
  }
}
void update_keys ( int  ,
unsigned  char,
int  ,
unsigned char *  ,
int   
)

Definition at line 81 of file plugin_ffdecsa.c.

References dprintf0, dprintf1, ENCRYPTED_NOT_READY, keyindex::even, FF_MAX_IDX, find_csa_from_adpt(), i, pid::index, csastruct::keyindex, csastruct::keylock, pid::list, list_add(), list_del(), list_empty(), list_entry, list_lock, ll_find_elem, list_head::next, csastruct::nexus_fixup, NOT_ENCRYPTED, NULL, keyindex::odd, pid::pid, csastruct::pid_map, pop_entry_from_queue_l, push_empty_queue, keyindex::queued, csastruct::state, csastruct::state_lock, keyindex::status, and keyindex::valid.

Referenced by _SetCaDescr(), _SetCaPid(), and process_cam().

{
    int i;
    struct pid *pid_ll;
    struct csastruct *csa = find_csa_from_adpt(adpt);

    if(key == NULL) {
      dprintf0("Got command(%d): %c idx: %d pid: %d\n", adpt, keytype, index,
               pid);
    } else {
      dprintf0("Got command(%d): %c idx: %d pid: %d key: "
             "%02x%02x...%02x\n", adpt, keytype, index, pid,
             key[0], key[1], key[7]);
    }
    assert(csa);
    if(! csa)
      return;
    if(index < 0 || index >= FF_MAX_IDX)
      return;

    pthread_mutex_lock(&csa->state_lock);
    if (keytype == 'I') //Invalidate
    {
        csa->state = NOT_ENCRYPTED;
        dprintf1("Setting state: NOT_ENCRYPTED\n");
        pthread_mutex_lock(&csa->keylock);
        for(i=0; i < FF_MAX_IDX; i++)
          csa->keyindex[i].valid = 0;
        //csa_ready = 0;
        pthread_mutex_unlock(&csa->keylock);
        while(! list_empty(&csa->pid_map)) {
          pid_ll = list_entry(csa->pid_map.next, struct pid);
          list_del(&pid_ll->list);
          push_empty_queue(&pid_ll->list, &pidmap_empty_queue);
        }
        pthread_mutex_unlock(&csa->state_lock);
        return;
    }
    if (keytype == 'P') //PID
    {
        ll_find_elem(pid_ll, csa->pid_map, pid, pid, struct pid);
        if(pid_ll) {
          pthread_mutex_unlock(&csa->state_lock);
          return;
        }
        if(! csa->keyindex[index].valid) {
          csa->keyindex[index].valid = 1;
          csa->keyindex[index].status = 0;
          csa->keyindex[index].queued = 0;
        }
        pop_entry_from_queue_l(pid_ll, &pidmap_empty_queue, struct pid, &list_lock);
        pid_ll->pid = pid;
        pid_ll->index = index;
        list_add(&pid_ll->list, &csa->pid_map);
        pthread_mutex_unlock(&csa->state_lock);
        dprintf1("Adding pid %d to list\n", pid);
        return;
    }
    if (keytype == 'C') //Close PID
    {
        ll_find_elem(pid_ll, csa->pid_map, pid, pid, struct pid);
        if(pid_ll) {
          index = pid_ll->index;
          list_del(&pid_ll->list);
          push_empty_queue(&pid_ll->list, &pidmap_empty_queue);
          ll_find_elem(pid_ll, csa->pid_map, index, index, struct pid);
          if(pid_ll == NULL) {
            //no valid pids on this index
            csa->keyindex[index].status = 0;
            if(list_empty(&csa->pid_map)) {
              //state = ENCRYPTED_NOT_READY;
              csa->state = NOT_ENCRYPTED;
              dprintf1("Setting state: NOT_ENCRYPTED\n");
            }
          }
        }
        pthread_mutex_unlock(&csa->state_lock);
        dprintf1("Removing pid %d to list state = %d\n", pid, csa->state);
        return;
    }
    ll_find_elem(pid_ll, csa->pid_map, index, index, struct pid);
    if(pid_ll == NULL) {
        pthread_mutex_unlock(&csa->state_lock);
        return;
    }
    pthread_mutex_lock(&csa->keylock);
    if (keytype == 'E') //Even
    {
        memcpy( csa->keyindex[index].even, key, 8);
        csa->keyindex[index].queued |= 0x02;
        csa->keyindex[index].status |= 0x02;
        if(csa->state == NOT_ENCRYPTED && csa->keyindex[index].status == 3) {
          csa->state = ENCRYPTED_NOT_READY;
          dprintf1("Setting state: ENCRYPTED_NOT_READY\n");
        }
        dprintf1("Processed Even Key (idx=%d): State = %d, ready = %d\n",
                 index, csa->state, csa->keyindex[index].status);
    }
    else if (keytype == 'O') //Odd
    {
        memcpy( csa->keyindex[index].odd, key, 8);
        csa->keyindex[index].queued |= 0x01;
        csa->keyindex[index].status |= 0x01;
        if(csa->state == NOT_ENCRYPTED && csa->keyindex[index].status == 3) {
          csa->state = ENCRYPTED_NOT_READY;
          dprintf1("Setting state: ENCRYPTED_NOT_READY\n");
        }
        dprintf1("Processed Odd Key (idx=%d): State = %d, ready = %d\n",
                 index, csa->state, csa->keyindex[index].status);
    }
    else if (keytype == 'N') //Nexus
    {
        csa->nexus_fixup = 1;
        if(csa->state == NOT_ENCRYPTED) {
          csa->state = ENCRYPTED_NOT_READY;
          dprintf1("Setting state: ENCRYPTED_NOT_READY\n");
        }
    }
    pthread_mutex_unlock(&csa->keylock);
    pthread_mutex_unlock(&csa->state_lock);
    return;
}
static void usermsg_cam ( char *  str) [static]

Definition at line 609 of file plugin_cam.c.

References data, and cPlugin::SVDRPCommand().

                                    {
  char *data;
  cString outstr;
  int res;
  if(sc) {
    printf(":: %s ||\n", str);
    data = strchr(str, ' ');
    if(data) {
      *data = '\0';
      data++;
    }
    printf("User Message %s data: %s\n", str, data);
    outstr = sc->SVDRPCommand((const char *)str, (const char *)data, res);
    printf("%s",*outstr);
    printf("User Message %s returned: %d\n", str, res);
  }
}

Variable Documentation

int cam_opt = 0 [static]

Definition at line 40 of file plugin_cam.c.

Referenced by parseopt_cam().

struct option Cam_Opts[] [static]
Initial value:
 {
  {"cam-budget", 0, &cam_opt, 'b'},
  {"cam-dir", 1, &cam_opt, 'd'},
  {"cam-nofixcat", 0, &cam_opt, 'f'},
  {"cam-extau", 1, &cam_opt, 'e'},
  {"cam-scopts", 1, &cam_opt, 'o'},
  {0, 0, 0, 0},
}

Definition at line 46 of file plugin_cam.c.

Referenced by parseopt_cam().

unsigned int crc_table[256] [static]

Definition at line 364 of file plugin_cam.c.

Referenced by crc32().

const char* externalAU

Definition at line 879 of file data.c.

Referenced by main(), parseopt_cam(), and cScPlugin::ProcessArgs().

int opt_budget = 0 [static]

Definition at line 41 of file plugin_cam.c.

Referenced by connect_cam(), and parseopt_cam().

char opt_camdir[256] = {"./sc_files"} [static]

Definition at line 43 of file plugin_cam.c.

Referenced by cPlugin::ConfigDirectory(), get_camdir(), and parseopt_cam().

char opt_extau[256] [static]

Definition at line 45 of file plugin_cam.c.

Referenced by parseopt_cam().

int opt_fixcat = 1 [static]

Definition at line 42 of file plugin_cam.c.

Referenced by connect_cam(), and parseopt_cam().

struct plugin_cmd plugin_cmds [static]
Initial value:

Definition at line 687 of file plugin_cam.c.

cPlugin* sc = NULL [static]

Definition at line 82 of file plugin_cam.c.

Referenced by cSmartCardSlot::Action(), cSmartCards::LockCard(), and shutdown_cam().

char scCap[80] [static]

Definition at line 83 of file plugin_cam.c.

Referenced by connect_cam(), and init_sc().

struct scopt_list scopts[32] = {{{'\0'}}}

Definition at line 80 of file plugin_cam.c.

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines