summaryrefslogtreecommitdiff
path: root/mcast/common/.svn/text-base/ciparser.c.svn-base
diff options
context:
space:
mode:
Diffstat (limited to 'mcast/common/.svn/text-base/ciparser.c.svn-base')
-rw-r--r--mcast/common/.svn/text-base/ciparser.c.svn-base702
1 files changed, 702 insertions, 0 deletions
diff --git a/mcast/common/.svn/text-base/ciparser.c.svn-base b/mcast/common/.svn/text-base/ciparser.c.svn-base
new file mode 100644
index 0000000..5ce563d
--- /dev/null
+++ b/mcast/common/.svn/text-base/ciparser.c.svn-base
@@ -0,0 +1,702 @@
+/*
+ * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de
+ *
+ * See the COPYING file for copyright information and
+ * how to reach the author.
+ *
+ */
+
+//#define TESTING
+#ifdef TESTING
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+#include "ciparser.h"
+static unsigned char ll[] = { 0x00, 0x01, 0xA0, 0x28, 0x01, 0x90, 0x02, 0x00, 0x05, 0x9F, 0x80, 0x32, 0x1F, 0x03, 0x32, 0xC9, 0x01, 0x00, 0x0F, 0x01, 0x09, 0x06, 0x17, 0x62, 0xE0, 0x65, 0x00, 0x09, 0x09, 0x04, 0x17, 0x02, 0xE1, 0x2D, 0x02, 0x00, 0xA0, 0x00, 0x00, 0x04, 0x00, 0xA1, 0x00, 0x00 };
+static unsigned char lr[] = { 0x00, 0x01, 0x80, 0x02, 0x01, 0x80 };
+static unsigned char la[] = { 0x00, 0x01, 0xA0, 0x07, 0x01, 0x91, 0x04, 0x00, 0x01, 0x00, 0x41, 0x80, 0x02, 0x01, 0x00 };
+static unsigned char lb[] = { 0x00, 0x01, 0xA0, 0x82, 0x00, 0x17, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x31, 0x0E, 0x06, 0x02, 0x06, 0x02, 0x17, 0x02, 0x17, 0x62, 0x01, 0x00, 0x05, 0x00, 0x18, 0x00, 0x80, 0x02, 0x01, 0x00 };
+static unsigned char lc[] = { 0x01, 0x02, 0xA0, 0x5F, 0x02, 0x90, 0x02, 0x00, 0x06, 0x9F, 0x80, 0x32, 0x56, 0x03, 0x03, 0x8B, 0x01, 0x00, 0x00, 0x02, 0x00, 0xA3, 0x00, 0x23, 0x01, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xC3, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x00, 0x94, 0x0D, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xCD, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x02, 0x38, 0x08, 0x04, 0x00, 0x5C, 0x00, 0x23, 0x01, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xC3, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x00, 0x94, 0x0D, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xCD, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x02, 0x38, 0x08 };
+static unsigned char ld[] = { 0x00, 0x01, 0xA0, 0x82, 0x00, 0x10, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x33, 0x07, 0x2D, 0xB9, 0x01, 0x81, 0x00, 0x08, 0x00, 0x80, 0x02, 0x01, 0x00 };
+static unsigned char le[] = { 0x00, 0x01, 0xA0, 0x34, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x32, 0x2B, 0x03, 0x00, 0x0B, 0x01, 0x00, 0x11, 0x01, 0x09, 0x06, 0x17, 0x22, 0xF0, 0x0B, 0x00, 0x0B, 0x09, 0x06, 0x17, 0x02, 0xF0, 0x0B, 0x00, 0x0B, 0x02, 0x06, 0xFF, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x04, 0x07, 0x01, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00};
+
+#define dbg(format, arg...) printf("%s:%d " format , __FILE__ , __LINE__ , ## arg)
+#define err(format, arg...) {printf("err:%s:%d: %s (%d): " format , __FILE__ , __LINE__ ,strerror(errno), errno, ## arg);print_trace();abort();}
+#define info(format, arg...) printf("%s:%d: " format , __FILE__ , __LINE__ ,## arg)
+#define warn(format, arg...) printf("%s:%d: " format , __FILE__ , __LINE__ ,## arg)
+#define STATIC
+#else
+//#define DEBUG
+#include "headers.h"
+#endif
+
+#define CA_MAX_CAIDS 16
+#define CA_MAX_PIDS 16
+#ifndef CA_MAX_SLOTS
+#define CA_MAX_SLOTS 3
+#endif
+typedef struct
+{
+ u_int16_t caid[CA_MAX_CAIDS];
+ u_int16_t pid[CA_MAX_PIDS];
+ u_int16_t capid[CA_MAX_PIDS];
+} caid_pid_list_t;
+
+static caid_pid_list_t cpl[CA_MAX_SLOTS];
+
+STATIC void dump(u_int8_t *data, int len)
+{
+#ifdef DEBUG
+ int j;
+ printf("Dump: ");
+ for(j=0;j<len;j++) {
+ printf("%02x ",data[j]);
+ }
+ printf("\n");
+#endif
+}
+
+STATIC int ci_cpl_find_pid (int slot, int pid)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ int i;
+ for (i = 0; i < CA_MAX_PIDS; i++) {
+ if (pid == cpl[slot].pid[i])
+ return 1;
+ }
+ return 0;
+}
+
+STATIC int ci_cpl_find_caid (int slot, int caid)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ int i;
+ for (i = 0; i < CA_MAX_CAIDS; i++) {
+ if (caid == cpl[slot].caid[i])
+ return 1;
+ }
+ return 0;
+}
+
+STATIC int ci_cpl_find_capid (int slot, int pid)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ int i;
+ for (i = 0; i < CA_MAX_PIDS; i++) {
+ if (pid == cpl[slot].capid[i])
+ return 1;
+ }
+ return 0;
+}
+
+STATIC int ci_cpl_delete_pid (int slot, int pid)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ int i;
+ for (i = 0; i < CA_MAX_PIDS; i++) {
+ if (cpl[slot].pid[i]==pid) {
+ cpl[slot].pid[i] = 0;
+ dbg ("-------> Slot: %d Deleted pid: %04x\n", slot, pid);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+STATIC int ci_cpl_update_pid (int slot, int pid)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ if (!ci_cpl_find_pid (slot, pid)) {
+ int i;
+ for (i = 0; i < CA_MAX_PIDS; i++) {
+ if (!cpl[slot].pid[i]) {
+ cpl[slot].pid[i] = pid;
+ dbg ("-------> Slot: %d Added pid: %04x\n", slot, pid);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+STATIC int ci_cpl_update_caid (int slot, int caid)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ if (!ci_cpl_find_caid (slot, caid)) {
+ int i;
+ for (i = 0; i < CA_MAX_CAIDS; i++) {
+ if (!cpl[slot].caid[i]) {
+ cpl[slot].caid[i] = caid;
+ dbg ("-------> Slot: %d Added caid: %04x\n", slot, caid);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+STATIC int ci_cpl_update_capid (int slot, int capid)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ if (!ci_cpl_find_capid (slot, capid)) {
+ int i;
+ for (i = 0; i < CA_MAX_PIDS; i++) {
+ if (!cpl[slot].capid[i]) {
+ cpl[slot].capid[i] = capid;
+ dbg ("-------> Slot: %d Added capid: %04x\n", slot, capid);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int ci_cpl_find_caid_by_pid (int pid)
+{
+ int i;
+ int slot;
+
+ if(!pid) {
+ return 0;
+ }
+ for (slot = 0; slot < CA_MAX_SLOTS; slot++) {
+ for (i = 0; i < CA_MAX_PIDS; i++) {
+ if (pid == cpl[slot].pid[i]) {
+ return cpl[slot].caid[0];
+ }
+ }
+ }
+ return 0;
+}
+
+int ci_cpl_find_slot_by_caid_and_pid (int caid, int pid)
+{
+ int slot;
+ for (slot = 0; slot < CA_MAX_SLOTS; slot++) {
+ if (ci_cpl_find_pid (slot, pid) && ci_cpl_find_caid (slot, caid)) {
+ return slot;
+ }
+ }
+ return -1;
+}
+
+int ci_cpl_clear (int slot)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ memset (&cpl[slot], 0, sizeof (caid_pid_list_t));
+ return 0;
+}
+
+int ci_cpl_clear_pids (int slot)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ memset (cpl[slot].pid, 0, sizeof (u_int16_t) * CA_MAX_PIDS);
+ return 0;
+}
+
+int ci_cpl_clear_caids (int slot)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ memset (cpl[slot].caid, 0, sizeof (u_int16_t) * CA_MAX_CAIDS);
+ return 0;
+}
+
+int ci_cpl_clear_capids (int slot)
+{
+ if (slot < 0 || slot >= CA_MAX_SLOTS) {
+ return -1;
+ }
+ memset (cpl[slot].capid, 0, sizeof (u_int16_t) * CA_MAX_PIDS);
+ return 0;
+}
+
+STATIC int ci_decode_length (unsigned int *len, u_int8_t * v)
+{
+ int ret = 0;
+
+ if (*v & LENGTH_SIZE_INDICATOR) {
+ int l = *v & 0x7f;
+ if (l > 4) {
+ return -1;
+ }
+ ret = l + 1;
+ *len = 0;
+ while (l--) {
+ v++;
+ *len <<= 8;
+ *len |= *v;
+ }
+ } else {
+ *len = *v;
+ ret = 1;
+ }
+ return ret;
+}
+
+#if 0
+STATIC int ci_decode_al_ca_info (ci_al_t * al)
+{
+ int i = 0;
+ u_int8_t *data = al->data;
+ int len = al->length;
+
+ if (len & 1) {
+ dbg ("ci_decode_al_ca_info: invalid length %d\n", len);
+ }
+
+ len >>= 1;
+
+ u_int16_t *caid = (u_int16_t *) malloc (sizeof (u_int16_t) * len);
+ ci_cpl_clear_caids (al->sl->tl->ll->slot);
+ while (i < len) {
+ caid[i++] = ntohs16 (data);
+ data += 2;
+ ci_cpl_update_caid (al->sl->tl->ll->slot, caid[i - 1]);
+ dbg ("CAID[%d]: %04x\n", i - 1, caid[i - 1]);
+ }
+ if (caid) {
+ free (caid);
+ }
+ return data - al->data;
+}
+#endif
+
+STATIC int ca_decode_ca_descr (ca_desc_t ** cadescr, int count, u_int8_t * data, int len, int *magic)
+{
+ *cadescr = (ca_desc_t *) realloc (*cadescr, sizeof (ca_desc_t *) * (count + 1));
+ if (!*cadescr) {
+ err ("ca_decode_ca_descr: out of memory\n");
+ }
+ ca_desc_t *c = *cadescr + count;
+
+// u_int8_t descriptor_tag = *data;
+ data++;
+ u_int8_t descriptor_length = *data;
+ data++;
+ c->ca_id = ntohs16 (data);
+ data += 2;
+ c->ca_pid = ntohs16 (data);
+ data += 2;
+ dbg ("cadescr: %p %d ca_id: %04x ca_pid: %04x\n", cadescr, count, c->ca_id, c->ca_pid);
+ if(magic && c->ca_id > 0 && c->ca_id < 3 && c->ca_pid > 0 && c->ca_pid < 3 && c->ca_id == c->ca_pid){
+ *magic = c->ca_id;
+ }
+ return descriptor_length + 2;
+}
+
+
+STATIC int ci_decode_al_ca_pmt (ci_al_t * al)
+{
+ ca_pmt_t p;
+ int magic = 0;
+ int slot = 0;
+ int cleared = 0;
+
+ memset (&p, 0, sizeof (ca_pmt_t));
+
+ int ret;
+ u_int8_t *data = al->data;
+ int len;
+
+ p.ca_pmt_list_management = *data;
+ data++;
+
+ p.program_number = ntohs16 (data);
+ data += 2;
+
+ p.version_number = *data;
+ data++;
+
+ p.program_info_length = (u_int16_t) ntohs16 (data);
+ data += 2;
+
+ dbg ("ci_decode_al_ca_pmt: ca_pmt_list_management:%02x program_number:%04x version_number:%02x program_info_length:%04x\n", p.ca_pmt_list_management, p.program_number, p.version_number, p.program_info_length);
+ if (p.program_info_length) {
+ int ca_descr_count = 0;
+ len = p.program_info_length - 1;
+ p.ca_pmt_cmd_id = *data;
+ dbg ("p.ca_pmt_cmd_id:%02x\n", p.ca_pmt_cmd_id);
+ data++;
+ while (len>0) {
+ ret = ca_decode_ca_descr (&p.cadescr, ca_descr_count, data, len, &magic);
+ if (magic)
+ slot = magic - 1;
+ else
+ slot = al->sl->tl->ll->slot;
+ if (!cleared) {
+ if(p.ca_pmt_list_management == CPLM_ONLY || p.ca_pmt_list_management == CPLM_FIRST || p.ca_pmt_list_management == CPLM_UPDATE) {
+ ci_cpl_clear_pids(slot);
+ ci_cpl_clear_capids(slot);
+ ci_cpl_clear_caids(slot);
+ cleared = 1;
+ }
+ }
+ if (ret < 0) {
+ warn ("error decoding ca_descriptor\n");
+ break;
+ }
+ if((magic != p.cadescr[ca_descr_count].ca_id) || (magic != p.cadescr[ca_descr_count].ca_pid)){
+ ci_cpl_update_caid (slot, p.cadescr[ca_descr_count].ca_id);
+ ci_cpl_update_capid (slot, p.cadescr[ca_descr_count].ca_pid);
+ }
+ ca_descr_count++;
+ data += ret;
+ len -= ret;
+ }
+ if (p.cadescr) {
+ free (p.cadescr);
+ }
+ }
+
+ len = al->length - (data - al->data);
+ int pidn = 0;
+
+ while (len>0) {
+ p.pidinfo = (pidinfo_t *) realloc (p.pidinfo, sizeof (pidinfo_t) * (pidn + 1));
+ if (!p.pidinfo) {
+ err ("ci_decode_al_ca_pmt: out of memory");
+ }
+ memset (&p.pidinfo[pidn], 0, sizeof (pidinfo_t));
+ p.pidinfo[pidn].stream_type = *data;
+ data++;
+ len--;
+ p.pidinfo[pidn].pid = ntohs16 (data);
+ data += 2;
+ len -= 2;
+ p.pidinfo[pidn].es_info_length = ntohs16 (data);
+ data += 2;
+ len -= 2;
+
+ dbg ("len: %d count: %d, stream_type: %02x, pid: %04x es_info_length: %04x\n", len, pidn, p.pidinfo[pidn].stream_type, p.pidinfo[pidn].pid, p.pidinfo[pidn].es_info_length);
+ if (p.pidinfo[pidn].es_info_length) {
+ int pi_len = p.pidinfo[pidn].es_info_length - 1;
+ p.pidinfo[pidn].ca_pmt_cmd_id = *data;
+ data++;
+ len--;
+ int pid_ca_descr_count = 0;
+ while (pi_len>0) {
+ ret = ca_decode_ca_descr (&p.pidinfo[pidn].cadescr, pid_ca_descr_count, data, pi_len, NULL);
+ if (!cleared) {
+ if(p.ca_pmt_list_management == CPLM_ONLY || p.ca_pmt_list_management == CPLM_FIRST || p.ca_pmt_list_management == CPLM_UPDATE) {
+ ci_cpl_clear_pids(slot);
+ ci_cpl_clear_capids(slot);
+ ci_cpl_clear_caids(slot);
+ cleared = 1;
+ }
+ }
+ if (ret < 0) {
+ warn ("error decoding ca_descriptor\n");
+ break;
+ }
+ if((magic != p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_id) || (magic != p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_pid)){
+ ci_cpl_update_pid (slot, p.pidinfo[pidn].pid);
+ ci_cpl_update_caid (slot, p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_id);
+ ci_cpl_update_capid (slot, p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_pid);
+ }
+ pid_ca_descr_count++;
+ data += ret;
+ pi_len -= ret;
+ len -= ret;
+ }
+ }
+ if (p.pidinfo[pidn].cadescr) {
+ free (p.pidinfo[pidn].cadescr);
+ }
+ pidn++;
+ }
+ if (p.pidinfo) {
+ free (p.pidinfo);
+ }
+ return 0;
+}
+
+STATIC int ci_decode_al_ca_pmt_reply (ci_al_t * al)
+{
+ ca_pmt_reply_t p;
+
+ memset (&p, 0, sizeof (ca_pmt_reply_t));
+
+ u_int8_t *data = al->data;
+ int len;
+
+ p.program_number = ntohs16 (data);
+ data += 2;
+
+ p.version_number = *data;
+ data++;
+
+ p.ca_enable = *data;
+ data++;
+
+ len = al->length - (data - al->data);
+ int pidn = 0;
+
+ dbg ("ci_decode_al_ca_pmt_reply: program_number: %04x ca_enable: %02x\n", p.program_number, p.ca_enable);
+
+ while (len>0) {
+ p.pidcaenable = (pid_ca_enable_t *) realloc (p.pidcaenable, sizeof (pid_ca_enable_t) * (pidn + 1));
+ if (!p.pidcaenable) {
+ err ("ci_decode_al_ca_pmt_reply: out of memory\n");
+ }
+ memset (&p.pidcaenable[pidn], 0, sizeof (pid_ca_enable_t));
+ p.pidcaenable[pidn].pid = ntohs16 (data);
+ data += 2;
+ p.pidcaenable[pidn].ca_enable = *data;
+ data++;
+ len -= 3;
+ if ((p.pidcaenable[pidn].ca_enable == CPCI_OK_DESCRAMBLING) || (p.pidcaenable[pidn].ca_enable == CPCI_OK_MMI) || (p.pidcaenable[pidn].ca_enable == CPCI_QUERY)) {
+ ci_cpl_update_pid (al->sl->tl->ll->slot, p.pidcaenable[pidn].pid);
+ } else {
+ ci_cpl_delete_pid (al->sl->tl->ll->slot, p.pidcaenable[pidn].pid);
+ }
+ dbg ("count: %d pid: %04x pid_ca_enable: %02x\n", pidn, p.pidcaenable[pidn].pid, p.pidcaenable[pidn].ca_enable);
+ pidn++;
+ }
+ if (p.pidcaenable) {
+ free (p.pidcaenable);
+ }
+ return 0;
+}
+
+STATIC int ci_decode_al (ci_sl_t * sl)
+{
+ int ret = 0;
+ int done = 0;
+ int len = 3;
+ ci_al_t al;
+ u_int8_t *data = sl->data;
+ al.sl = sl;
+
+ al.tag = 0;
+ while (len--) {
+ al.tag <<= 8;
+ al.tag |= *data;
+ data++;
+ }
+ done += 3;
+ ret = ci_decode_length (&al.length, data);
+ if (ret < 0) {
+ warn ("ci_decode_al ci_decode_length failed\n");
+ return ret;
+ }
+
+ data += ret;
+ done += ret;
+ //Fake
+ al.data = data;
+
+ dbg ("ci_decode_al: tag:%03x length: %02x data[0]:%02x done: %02x\n", al.tag, al.length, al.data[0], done);
+
+ switch (al.tag) {
+ case AOT_CA_INFO:
+// ci_decode_al_ca_info (&al);
+ break;
+ case AOT_CA_PMT:
+ ci_decode_al_ca_pmt (&al);
+ break;
+ case AOT_CA_PMT_REPLY:
+ ci_decode_al_ca_pmt_reply (&al);
+ break;
+ }
+
+ done += al.length;
+
+ dbg ("ci_decode_al: done %02x\n", done);
+ return done;
+}
+
+STATIC int ci_decode_sl (ci_tl_t * tl)
+{
+ int ret = 0;
+ int done = 0;
+ unsigned int len;
+ ci_sl_t sl;
+ u_int8_t *data = tl->data;
+ sl.tl = tl;
+
+ sl.tag = *data;
+ data++;
+ done++;
+
+ if(sl.tag != ST_SESSION_NUMBER) {
+ return tl->length;
+ }
+
+ ret = ci_decode_length (&len, data);
+ if (ret < 0) {
+ warn ("ci_decode_sl ci_decode_length failed\n");
+ return ret;
+ }
+ data += ret;
+ done += ret;
+
+ if (len > 4) {
+ warn ("invalid length (%d) for session_object_value\n", len);
+ return -1;
+ }
+
+ sl.object_value = 0;
+ while (len--) {
+ sl.object_value <<= 8;
+ sl.object_value |= *data;
+ data++;
+ done++;
+ }
+
+ sl.data = data;
+ sl.length = tl->length - done;
+
+ while (sl.length>0) {
+ dbg ("ci_decode_sl: object_value:%02x length: %02x done: %02x\n", sl.object_value, sl.length, done);
+ ret = ci_decode_al (&sl);
+ if (ret < 0) {
+ warn ("ci_decode_al failed\n");
+ return ret;
+ }
+ sl.length -= ret;
+ sl.data += ret;
+ done += ret;
+ }
+ dbg ("ci_decode_sl: done %02x\n", done);
+ return done;
+}
+
+STATIC int ci_decode_tl (ci_ll_t * ll)
+{
+ int ret = 0;
+ int done = 0;
+ ci_tl_t tl;
+ u_int8_t *data = ll->data;
+ tl.ll = ll;
+
+ tl.c_tpdu_tag = *data;
+ data++;
+ done++;
+
+ ret = ci_decode_length (&tl.length, data);
+ if (ret < 0) {
+ warn ("ci_decode_tl ci_decode_length failed\n");
+ return ret;
+ }
+
+ data += ret;
+ done += ret;
+
+ tl.tcid = *data;
+ data++;
+ done++;
+
+ if (tl.tcid != ll->tcid) {
+ warn ("Error: redundant tcid mismatch %02x %02x\n",tl.tcid, ll->tcid);
+ return -1;
+ }
+
+ tl.data = data;
+
+ //According to A.4.1.1
+ tl.length--;
+
+ while (tl.length>0) {
+ dbg ("ci_decode_tl: c_tpdu_tag:%02x tcid:%02x length: %02x done: %02x\n", tl.c_tpdu_tag, tl.tcid, tl.length, done);
+ if (tl.c_tpdu_tag == T_DATA_LAST || tl.c_tpdu_tag == T_DATA_MORE) {
+ ret = ci_decode_sl (&tl);
+ if (ret < 0) {
+ warn ("ci_decode_sl failed\n");
+ return ret;
+ }
+ } else {
+ ret = tl.length;
+ }
+ tl.length -= ret;
+ tl.data += ret;
+ done += ret;
+ }
+ dbg ("ci_decode_tl: done %02x\n", done);
+ return done;
+}
+
+int ci_decode_ll (uint8_t * tpdu, int len)
+{
+ int ret = 0;
+ int done = 0;
+ u_int8_t *data=tpdu;
+ ci_ll_t ll;
+ dump(tpdu,len);
+
+ ll.slot = *data;
+ data++;
+
+ ll.tcid = *data;
+ data++;
+
+ ll.data = data;
+ ll.length = len - (data-tpdu);
+
+ while (ll.length) {
+
+ dbg ("ci_decode_ll: slot:%02x tcid:%02x length: %02x\n", ll.slot, ll.tcid, ll.length);
+ ret = ci_decode_tl (&ll);
+ if (ret < 0) {
+ warn ("ci_decode_tl failed\n");
+ return ret;
+ }
+ ll.length -= ret;
+ ll.data += ret;
+ }
+ dbg ("ci_decode_ll: done %02x\n", len);
+ return done;
+}
+
+#ifdef TESTING
+int main (int argc, char **argv)
+{
+ int ret;
+
+ printf ("ci_decode_ll len: %02x\n", sizeof (lb));
+ ret = ci_decode_ll (lb, sizeof (lb));
+ printf ("ci_decode_ll ret: %02x\n", ret);
+
+ printf ("ci_decode_ll len: %02x\n", sizeof (ll));
+ ret = ci_decode_ll (ll, sizeof (ll));
+ printf ("ci_decode_ll ret: %02x\n", ret);
+
+
+ printf ("ci_decode_ll len: %02x\n", sizeof (ld));
+ ret = ci_decode_ll (ld, sizeof (ld));
+ printf ("ci_decode_ll ret: %02x\n", ret);
+
+ printf ("ci_decode_ll len: %02x\n", sizeof (lc));
+ ret = ci_decode_ll (lc, sizeof (lc));
+ printf ("ci_decode_ll ret: %02x\n", ret);
+
+ printf ("ci_decode_ll len: %02x\n", sizeof (le));
+ ret = ci_decode_ll (le, sizeof (le));
+ printf ("ci_decode_ll ret: %02x\n", ret);
+
+// printf ("caid %04x for pid %04x\n", ci_cpl_find_caid_by_pid (0x5c), 0x5c);
+ return 0;
+}
+#endif