SASC
DVBSoftCAM

plugin_ffdecsa.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 "plugin_ringbuf.h"
#include "plugin_getsid.h"
#include "../FFdecsa/FFdecsa.h"
#include "debug.h"

Go to the source code of this file.

Classes

struct  keyindex
struct  csastruct
struct  pid

Defines

#define PLUGIN_ID   30
#define DBG_NAME   "CSA"
#define FF_MAX_IDX   16
#define FF_MAX_PID   8
#define push_empty_queue(_item, _queue)

Enumerations

enum  { NOT_ENCRYPTED = 0, ENCRYPTED_NOT_READY = 1, ENCRYPTED_READY = 2 }

Functions

static LIST_HEAD (csalist)
static LIST_HEAD (pidmap_empty_queue)
static struct csastruct * find_csa_from_adpt (int adapt)
void update_keys (int adpt, unsigned char keytype, int index, unsigned char *key, int pid)
static int process_ts (struct csastruct *csa, unsigned char *buffer, uint end, int force)
static struct csastruct * find_csa_from_rb (struct ringbuffer *rb, int init)
int check_state (struct csastruct *csa, struct ringbuffer *rb)
int check_encrypted (struct ringbuffer *rb, int need_bytes)
static void process_ffd (struct msg *msg, unsigned int priority)
static void connect_ffd (struct parser_adpt *pc_all)
int __attribute__ ((constructor))

Variables

static unsigned char ** range
static int cluster_size
static uint cluster_size_bytes
static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER
static struct plugin_cmd plugin_cmds

Define Documentation

#define DBG_NAME   "CSA"

Definition at line 15 of file plugin_ffdecsa.c.

#define FF_MAX_IDX   16

Definition at line 18 of file plugin_ffdecsa.c.

Referenced by connect_ffd(), and update_keys().

#define FF_MAX_PID   8

Definition at line 19 of file plugin_ffdecsa.c.

#define PLUGIN_ID   30

Definition at line 14 of file plugin_ffdecsa.c.

Referenced by process_ts().

#define push_empty_queue (   _item,
  _queue 
)
Value:
{      \
          pthread_mutex_lock(&list_lock);    \
          list_add(_item, _queue);             \
          pthread_mutex_unlock(&list_lock);  \
}

Definition at line 21 of file plugin_ffdecsa.c.

Referenced by update_keys().


Enumeration Type Documentation

anonymous enum
Enumerator:
NOT_ENCRYPTED 
ENCRYPTED_NOT_READY 
ENCRYPTED_READY 

Definition at line 61 of file plugin_ffdecsa.c.


Function Documentation

int __attribute__ ( (constructor)  )

Definition at line 633 of file plugin_ffdecsa.c.

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

{
  list_add_tail(&plugin_cmds.list, &plugin_cmdlist);
  return 0;
}
int check_encrypted ( struct ringbuffer *  rb,
int  need_bytes 
)

Definition at line 393 of file plugin_ffdecsa.c.

References ringbuffer::buffer, check_state(), csastruct::csa_cond, csastruct::csaPtr, dprintf0, ringbuffer::end, find_csa_from_adpt(), MSG_HIGH_PRIORITY, msg_replace, MSG_RINGBUF, NOT_ENCRYPTED, ringbuffer::num, csastruct::rb, ringbuffer::rdPtr, ringbuffer::rw_lock, csastruct::state, csastruct::state_lock, TSPacketSIZE, and ringbuffer::wrPtr.

Referenced by connect_ffd().

{
  int processed_bytes = 0;
  int avail_bytes;
  int state;
  struct csastruct *csa = find_csa_from_adpt(rb->num);

  assert(csa);
  if(csa) {
    pthread_mutex_lock(&csa->state_lock);
    state = check_state(csa, rb);
  } else {
    state = NOT_ENCRYPTED;
  }

  if(state == NOT_ENCRYPTED) {
#if 0
    unsigned char *ptr = rb->buffer;
    while(ptr < rb->end) {
      ptr[3] &= 0x3f;
      ptr += TSPacketSIZE;
    }
#endif
    if(rb->rdPtr > rb->wrPtr)
      avail_bytes = rb->end - rb->rdPtr + rb->wrPtr - rb->buffer - TSPacketSIZE;
    else
      avail_bytes = rb->wrPtr - rb->rdPtr - TSPacketSIZE;
    if(csa) {
      pthread_mutex_unlock(&csa->state_lock);
    }
    //printf("Unencrypted.  Returning %d bytes\n", avail_bytes);
    return avail_bytes;
  }
  pthread_mutex_lock(&rb->rw_lock); // protect csaPtr
  pthread_mutex_unlock(&csa->state_lock);

  //There should be no way for csa not to be set here
  assert(csa->rb);

  if((rb->rdPtr <= csa->csaPtr  && csa->csaPtr <= rb->wrPtr) ||
     (rb->wrPtr < rb->rdPtr && rb->rdPtr <= csa->csaPtr)) {
    processed_bytes = csa->csaPtr -  rb->rdPtr;
  } else if(csa->csaPtr <= rb->wrPtr && rb->wrPtr < rb->rdPtr) {
    processed_bytes = rb->end - rb->rdPtr + csa->csaPtr - rb->buffer ;
  } else {
    //rd == wr && csa != rd
    //     OR
    //wr < csa < rd
    //We used to get here when switching between encrypted and clear
    //But no more!
    //csa->csaPtr = rb->rdPtr;
    //processed_bytes = 0;
    dprintf0("buf: %p rd: %p csa: %p wr: %p end: %p\n",
           rb->buffer, rb->rdPtr, csa->csaPtr, rb->wrPtr, rb->end);
    assert(0);
  }
  if(need_bytes > 0 && processed_bytes < need_bytes) {
    //ring-read is waiting for decrypted data.  we will stall until we get some
    //NOTE: We don't care about the return in this case as we need to call again
    //      to compute processed_bytes
    dprintf0("buf: %p rd: %p csa: %p wr: %p end: %p\n",
           rb->buffer, rb->rdPtr, csa->csaPtr, rb->wrPtr, rb->end);
    msg_replace(MSG_HIGH_PRIORITY, MSG_RINGBUF, rb->num, rb);
    pthread_cond_wait(&csa->csa_cond, &rb->rw_lock);
  }
  //printf("buf: %p rd: %p csa: %p wr: %p end: %p processed: %d\n",
  //       rb->buffer, rb->rdPtr, csa->csaPtr, rb->wrPtr, rb->end,
  //       processed_bytes);
  pthread_mutex_unlock(&rb->rw_lock);
  return processed_bytes;
}
int check_state ( struct csastruct *  csa,
struct ringbuffer *  rb 
)

Definition at line 376 of file plugin_ffdecsa.c.

References dprintf1, ENCRYPTED_NOT_READY, ENCRYPTED_READY, find_csa_from_rb(), list_empty(), NOT_ENCRYPTED, csastruct::pid_map, and csastruct::state.

Referenced by check_encrypted(), and process_ffd().

                                                              {
  if(csa->state == NOT_ENCRYPTED)
    return NOT_ENCRYPTED;
  if(csa->state == ENCRYPTED_READY)
    return ENCRYPTED_READY;
  if(csa->state == ENCRYPTED_NOT_READY) {
    if(list_empty(&csa->pid_map))
      return NOT_ENCRYPTED;
    find_csa_from_rb(rb, 1);
    csa->state = ENCRYPTED_READY;
    dprintf1("Setting state: ENCRYPTED_READY\n");
    return ENCRYPTED_READY;
  }
  return NOT_ENCRYPTED;
}
static void connect_ffd ( struct parser_adpt *  pc_all) [static]

Definition at line 587 of file plugin_ffdecsa.c.

References csastruct::adapter, common_data::buffersize, check_encrypted(), cluster_size, cluster_size_bytes, parser_cmds::common, csastruct::csa_cond, dprintf1, csastruct::dvr, parser_adpt::dvr, FF_MAX_IDX, get_key_struct(), get_suggested_cluster_size(), i, INIT_LIST_HEAD, csastruct::keyindex, csastruct::keylock, keyindex::keys, csastruct::list, cmd_list::list, list_add(), list_add_tail(), list_entry, list_for_each, NOT_ENCRYPTED, NULL, csastruct::pid_map, plugin_cmd::plugin, plugin_cmdlist, PLUGIN_RINGBUF, parser_cmds::post_read, parser_cmds::pre_read, range, read_call(), ringbuf_register_callback(), plugin_cmd::send_msg, csastruct::state, csastruct::state_lock, TSPacketSIZE, keyindex::valid, and common_data::virt_adapt.

{
  struct list_head *ptr;
  struct csastruct *csa;
#ifdef NO_RINGBUF
  struct cmd_list *dvr_preread = register_cmd(preread_call);
  struct cmd_list *dvr_postread = register_cmd(read_call);
  list_add(&dvr_preread.list, &pc_all->dvr->pre_read);
  list_add(&dvr_postread.list, &pc_all->dvr->post_read);
#else
  
  range = (unsigned char **)malloc(pc_all->dvr->common->buffersize /
                                   TSPacketSIZE + 1);
  csa = (struct csastruct *)malloc(sizeof(struct csastruct));
  memset(csa, 0, sizeof(struct csastruct));
  pthread_mutex_init(&csa->keylock, NULL);
  pthread_mutex_init(&csa->state_lock, NULL);
  pthread_cond_init(&csa->csa_cond, NULL);
  INIT_LIST_HEAD(&csa->pid_map);

  csa->adapter = pc_all->dvr->common->virt_adapt;
  csa->dvr = pc_all->dvr;
  csa->state = NOT_ENCRYPTED;
  dprintf1("Setting state: NOT_ENCRYPTED\n");
  for(int i = 0; i < FF_MAX_IDX; i++) {
    csa->keyindex[i].valid = 0;
    csa->keyindex[i].keys =  get_key_struct();
  }
  list_add_tail(&csa->list, &csalist);
  cluster_size = get_suggested_cluster_size();
  cluster_size_bytes = (uint)cluster_size * TSPacketSIZE;
  ringbuf_register_callback(check_encrypted);
  list_for_each(ptr, &plugin_cmdlist) {
    struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd);
    if(cmd->plugin == PLUGIN_RINGBUF) {
      cmd->send_msg(pc_all->dvr, 1);
      break;
    }
  }
#endif
}
static struct csastruct* find_csa_from_adpt ( int  adapt) [static, read]

Definition at line 74 of file plugin_ffdecsa.c.

References csastruct::adapter, and ll_find_elem.

Referenced by check_encrypted(), find_csa_from_rb(), process_ffd(), and update_keys().

{
  struct csastruct *csa;
  ll_find_elem(csa, csalist, adapter, adapt, struct csastruct);
  return csa;
}
static struct csastruct* find_csa_from_rb ( struct ringbuffer *  rb,
int  init 
) [static, read]

Definition at line 325 of file plugin_ffdecsa.c.

References csastruct::avg, csastruct::avgcnt, ringbuffer::buffer, cluster_size, csastruct::csaPtr, dprintf0, dprintf1, ringbuffer::end, find_csa_from_adpt(), list_lock, ll_find_elem, NULL, ringbuffer::num, csastruct::rb, RB_OPEN, ringbuffer::rdPtr, ringbuffer::rw_lock, ringbuffer::state, TSPacketSIZE, and ringbuffer::wrPtr.

Referenced by check_state().

                                                                           {
  struct csastruct *entry;
  int notalign;

  if(rb->state != RB_OPEN)
    return NULL;
  pthread_mutex_lock(&list_lock);
  ll_find_elem(entry, csalist, rb, rb, struct csastruct);
  if (! init) {
    pthread_mutex_unlock(&list_lock);
    return entry;
  }
  if(! entry) {
    dprintf0("Creating csa for rb: %d\n", rb->num);
    entry = find_csa_from_adpt(rb->num);
    assert(entry);
  } else {
    dprintf0("Resetting csa for rb: %d\n", rb->num);
  }
  pthread_mutex_lock(&rb->rw_lock);
  //things may have changed since above
  if(rb->state != RB_OPEN) {
    pthread_mutex_unlock(&rb->rw_lock);
    pthread_mutex_unlock(&list_lock);
    return NULL;
  }
  entry->rb = rb;
  entry->csaPtr = rb->rdPtr;
  entry->avg = cluster_size * 100;
  entry->avgcnt = 0;
  notalign = (entry->csaPtr - rb->buffer) % TSPacketSIZE;
  if(notalign) {
    //The read pointer is not aligned, but the wrptr is required to be
    entry->csaPtr += TSPacketSIZE - notalign;
    if(entry->csaPtr > rb->end)
      entry->csaPtr = rb->buffer + (entry->csaPtr - rb->end);
    if((rb->rdPtr > rb->wrPtr && entry->csaPtr > rb->wrPtr && entry->csaPtr < rb->rdPtr) || (rb->rdPtr <= rb->wrPtr && entry->csaPtr > rb->wrPtr)) { 
      dprintf0("INIT buf: %p rd: %p csa: %p wr: %p end: %p\n",
          rb->buffer, rb->rdPtr, entry->csaPtr, rb->wrPtr, rb->end);
      assert(0);
    }
  }
  dprintf1("INIT buf: %p rd: %p csa: %p wr: %p end: %p\n",
         rb->buffer, rb->rdPtr, entry->csaPtr, rb->wrPtr, rb->end);
  pthread_mutex_unlock(&rb->rw_lock);
  pthread_mutex_unlock(&list_lock);
  return entry;
}
static LIST_HEAD ( pidmap_empty_queue  ) [static]
static LIST_HEAD ( csalist  ) [static]
static void process_ffd ( struct msg *  msg,
unsigned int  priority 
) [static]

Definition at line 465 of file plugin_ffdecsa.c.

References ringbuffer::buffer, check_state(), dvblb_pollmsg::count, csastruct::csa_cond, csastruct::csaPtr, msg::data, dprintf0, dprintf1, DVBLB_CMD_ASYNC, csastruct::dvr, ENCRYPTED_NOT_READY, ENCRYPTED_READY, ringbuffer::end, find_csa_from_adpt(), ringbuffer::flags, list_lock, MSG_HIGH_PRIORITY, MSG_PROCESSED, msg_remove_type_from_list(), msg_replace, MSG_RINGBUF, MSG_RINGCLOSE, NOT_ENCRYPTED, NULL, ringbuffer::num, parser_cmds::poll_mutex, process_ts(), csastruct::rb, ringbuffer::rdPtr, ringbuffer::release, ringbuffer::rw_lock, csastruct::state, csastruct::state_lock, msg::type, parser_cmds::virtfd, and ringbuffer::wrPtr.

{
  struct csastruct *csa;
  int ret;
  int end = 0;
  unsigned char *wrPtr;
  if(msg->type == MSG_RINGBUF) {
    struct ringbuffer *rb = (struct ringbuffer *)msg->data;
    int bytes;
    msg->type = MSG_PROCESSED;
#ifdef NO_RINGBUF
    return;
#endif
    csa = find_csa_from_adpt(rb->num);
    assert(csa);
    if(! csa)
      return;

    pthread_mutex_lock(&csa->state_lock);
    if(check_state(csa, rb) == NOT_ENCRYPTED) {
      pthread_mutex_unlock(&csa->state_lock);
      return;
    }

    assert(csa->rb);

    pthread_mutex_lock(&rb->rw_lock);
    pthread_mutex_unlock(&csa->state_lock);

    wrPtr = rb->wrPtr;

    if (csa->csaPtr > wrPtr) {
      bytes = rb->end - csa->csaPtr;
      end = 1;
    } else
      bytes = wrPtr - csa->csaPtr;
    pthread_mutex_unlock(&rb->rw_lock);
    ret = process_ts(csa, csa->csaPtr, bytes, end);
    pthread_mutex_lock(&rb->rw_lock);
    if (csa->csaPtr + ret > rb->end) {
      dprintf0("rdPtr: %lu csaPtr: %lu wrPtr: %lu end: %lu bytes: %d end: %d\n",
             (unsigned long) (rb->rdPtr - rb->buffer),
             (unsigned long)(csa->csaPtr - rb->buffer),
             (unsigned long)(rb->wrPtr - rb->buffer),
             (unsigned long)(rb->end - rb->buffer), bytes, ret);
      assert(csa->csaPtr + ret <= rb->end);
    }
    csa->csaPtr += ret;
    if(csa->csaPtr == rb->end)
      csa->csaPtr = rb->buffer;

    if(ret) {
      if (rb->flags & O_NONBLOCK) {
        struct dvblb_pollmsg msg;
        msg.count = 0;
        //Is this thread safe?
        pthread_mutex_lock(&csa->dvr->poll_mutex);
        ioctl(csa->dvr->virtfd, DVBLB_CMD_ASYNC, &msg);
        pthread_mutex_unlock(&csa->dvr->poll_mutex);
      } else
        pthread_cond_signal(&csa->csa_cond);
    }
    pthread_mutex_unlock(&rb->rw_lock);
//    dprintf0("decoded: %d - %d\n", ret, bytes);
    if(ret) {
//      dprintf0("Sending RB1: %p\n", rb);
      msg_replace(MSG_HIGH_PRIORITY, MSG_RINGBUF, rb->num, rb);
    }
    sched_yield();
  }
  else if(msg->type == MSG_RINGCLOSE) {
    msg->type = MSG_PROCESSED;
    struct ringbuffer *rb = (struct ringbuffer *)msg->data;
    csa = find_csa_from_adpt(rb->num);
    msg_remove_type_from_list(MSG_HIGH_PRIORITY, MSG_RINGBUF, rb->num, NULL);
    msg_remove_type_from_list(MSG_HIGH_PRIORITY, MSG_RINGCLOSE, rb->num, NULL);
    assert(csa);
    if(! csa)
      return;
    dprintf0("Removing csa for rb: %d\n", rb->num);
    pthread_mutex_lock(&csa->state_lock);
    rb->release(rb);
    pthread_mutex_lock(&list_lock);
    csa->rb = NULL;
    pthread_mutex_unlock(&list_lock);
    if(csa->state == ENCRYPTED_READY) {
      csa->state = ENCRYPTED_NOT_READY;
      dprintf1("Setting state: ENCRYPTED_NOT_READY\n");
    }
    pthread_mutex_unlock(&csa->state_lock);
  }
}
static int process_ts ( struct csastruct *  csa,
unsigned char *  buffer,
uint  end,
int  force 
) [static]

Definition at line 204 of file plugin_ffdecsa.c.

References _dbglvl, csastruct::avg, csastruct::avgcnt, cluster_size, cluster_size_bytes, decrypt_packets(), dprintf0, dprintf3, keyindex::even, pid::index, csastruct::keyindex, csastruct::keylock, keyindex::keys, ll_find_elem, csastruct::nexus_fixup, NULL, keyindex::odd, csastruct::pid_map, PLUGIN_ID, keyindex::queued, range, set_even_control_word(), set_odd_control_word(), csastruct::state_lock, keyindex::status, TSPacketSIZE, and keyindex::valid.

Referenced by process_ffd().

{
    unsigned char tmp;
    struct pid *pid_ll;
    int ret = 0, rangeptr = 0, dec = 0;
    uint pos = 0;
    uint start_enc, end_enc;
    int index = -1;
    int odd_even;
    int pkt_count = 0;
    if(csa->nexus_fixup) {
      while(pos < end) {
        buffer[pos+3] &= 0x3F;
        pos += TSPacketSIZE;
      }
      return end;
    }
    //old way
    //if(! end || ! force && end < 6000)
    //  return 0;

    while (pos < end)
    {
        tmp=buffer[pos+3] & 0xC0;
        if(tmp == 0xc0 || tmp == 0x80)
            break;
        pos += TSPacketSIZE;
    }
    //new way
    if(! force && end - pos < cluster_size_bytes)
      return  pos;
    ret = pos;
    start_enc = end_enc = pos;
    pthread_mutex_lock(&csa->state_lock);
    while(end - end_enc >= TSPacketSIZE && pkt_count < cluster_size) {
        odd_even = buffer[end_enc+3] & 0xC0;
        if(odd_even) {
            int pid = ((buffer[end_enc + 1] << 8) + buffer[end_enc + 2])
                      & 0x1FFF;
            ll_find_elem(pid_ll, csa->pid_map, pid, pid, struct pid);
            if(pid_ll == NULL) {
                //What to do with an unknown pid?
                //Let's try to decode it anyway
                dprintf3("Didn't find pid %d\n", pid);
                end_enc+=TSPacketSIZE;
                continue;
            }
            if(index == -1) {
                //First encrypted packet (with a valid pid)
                index = pid_ll->index;
                tmp=odd_even;
                pkt_count++;
            }
            else if(index != pid_ll->index) {
                //Encrypted packet with a different index
                if(start_enc != end_enc) {
                    //there are previous packets that can be decoded
                    range[rangeptr++] = buffer + start_enc;
                    range[rangeptr++] = buffer + end_enc;
                    range[rangeptr] = 0;
                }
                //skip this packet
                start_enc = end_enc + TSPacketSIZE;
            } else {
              pkt_count++;
            }
        }
        end_enc+=TSPacketSIZE;
    }
    pthread_mutex_unlock(&csa->state_lock);
    if (index != -1 && start_enc != end_enc) {
        //add the last set of packets to the encryption queue
        range[rangeptr++] = buffer + start_enc;
        range[rangeptr++] = buffer + end_enc;
        range[rangeptr] = 0;
    }
    if (rangeptr > 0) {
        pthread_mutex_lock(&csa->keylock);
        if (! csa->keyindex[index].valid || csa->keyindex[index].status != 3) {
           pthread_mutex_unlock(&csa->keylock);
           return ret;
        }
        if (csa->keyindex[index].queued == 3)
        {
            csa->keyindex[index].queued = 0;
            set_even_control_word(csa->keyindex[index].keys, csa->keyindex[index].even);
            set_odd_control_word(csa->keyindex[index].keys, csa->keyindex[index].odd);
        }

        if (csa->keyindex[index].queued & 0x02 && tmp != 0x80)
        {
            csa->keyindex[index].queued &= 0x01;
            set_even_control_word(csa->keyindex[index].keys, csa->keyindex[index].even);
        }
        if (csa->keyindex[index].queued & 0x01 && tmp != 0xC0)
        {
            csa->keyindex[index].queued &= 0x02;
            set_odd_control_word(csa->keyindex[index].keys, csa->keyindex[index].odd);
        }
        pthread_mutex_unlock(&csa->keylock);

        if((_dbglvl >> PLUGIN_ID) & 3) {
          csa->avg = (csa->avg * 99 + pkt_count*100) / 100;
          if(csa->avg == 0)
            csa->avg = 1;
          csa->avgcnt++;
          if(csa->avgcnt == 100) {
            csa->avgcnt = 0;
            dprintf0("decrypted packets max:%d now:%u of %u avg:%f\n",
                cluster_size, pkt_count, end / TSPacketSIZE, csa->avg / 100.0);
          }
        }
        dec = decrypt_packets(csa->keyindex[index].keys, range) * TSPacketSIZE;
        if(ret + buffer == range[0])
          ret+=dec;
        //printf("decrypted now=%d, decrypted=%d, total=%d\n", pkt, pkt_done, pkt_cnt);
    }
    return ret;
}
void update_keys ( int  adpt,
unsigned char  keytype,
int  index,
unsigned char *  key,
int  pid 
)

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;
}

Variable Documentation

int cluster_size [static]

Definition at line 54 of file plugin_ffdecsa.c.

Referenced by connect_ffd(), find_csa_from_rb(), and process_ts().

uint cluster_size_bytes [static]

Definition at line 55 of file plugin_ffdecsa.c.

Referenced by connect_ffd(), and process_ts().

pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER [static]

Definition at line 58 of file plugin_ffdecsa.c.

Referenced by find_csa_from_rb(), process_ffd(), and update_keys().

struct plugin_cmd plugin_cmds [static]
Initial value:
 {{NULL, NULL}, PLUGIN_ID, "ffdecsa", 
                 NULL, connect_ffd, NULL, process_ffd, NULL, NULL}

Definition at line 631 of file plugin_ffdecsa.c.

unsigned char** range [static]
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines