Merge remote-tracking branch 'origin/pr/308'

This commit is contained in:
Adam Sutton 2013-12-04 15:48:57 +00:00
commit 67a585c96a
2 changed files with 337 additions and 240 deletions

View file

@ -203,6 +203,9 @@ typedef struct capmt {
uint16_t capmt_seq;
} capmt_t;
static void capmt_enumerate_services(capmt_t *capmt, int es_pid, int force);
static void capmt_send_request(capmt_service_t *ct, int es_pid, int lm);
/**
*
*/
@ -210,48 +213,49 @@ static int
capmt_send_msg(capmt_t *capmt, int sid, const uint8_t *buf, size_t len)
{
if (capmt->capmt_oscam) {
int i;
// dumping current SID table
for (i = 0; i < MAX_SOCKETS; i++)
tvhlog(LOG_DEBUG, "capmt", "%s: SOCKETS TABLE DUMP [%d]: sid=%d socket=%d", __FUNCTION__, i, capmt->sids[i], capmt->capmt_sock[i]);
if (sid == 0) {
tvhlog(LOG_DEBUG, "capmt", "%s: got empty SID - returning from function", __FUNCTION__);
return -1;
}
// searching for the SID and socket
int i = 0;
int found = 0;
for (i = 0; i < MAX_SOCKETS; i++) {
if (capmt->sids[i] == sid) {
found = 1;
break;
if (capmt->capmt_oscam == 1) {
// dumping current SID table
for (i = 0; i < MAX_SOCKETS; i++)
tvhlog(LOG_DEBUG, "capmt", "%s: SOCKETS TABLE DUMP [%d]: sid=%d socket=%d", __FUNCTION__, i, capmt->sids[i], capmt->capmt_sock[i]);
if (sid == 0) {
tvhlog(LOG_DEBUG, "capmt", "%s: got empty SID - returning from function", __FUNCTION__);
return -1;
}
}
if (found)
tvhlog(LOG_DEBUG, "capmt", "%s: found sid, reusing socket, i=%d", __FUNCTION__, i);
else { //not found - adding to first free in table
// searching for the SID and socket
for (i = 0; i < MAX_SOCKETS; i++) {
if (capmt->sids[i] == 0) {
capmt->sids[i] = sid;
if (capmt->sids[i] == sid) {
found = 1;
break;
}
}
}
if (i == MAX_SOCKETS) {
tvhlog(LOG_DEBUG, "capmt", "%s: no free space for new SID!!!", __FUNCTION__);
return -1;
} else {
capmt->sids[i] = sid;
tvhlog(LOG_DEBUG, "capmt", "%s: added: i=%d", __FUNCTION__, i);
if (found)
tvhlog(LOG_DEBUG, "capmt", "%s: found sid, reusing socket, i=%d", __FUNCTION__, i);
else { //not found - adding to first free in table
for (i = 0; i < MAX_SOCKETS; i++) {
if (capmt->sids[i] == 0) {
capmt->sids[i] = sid;
break;
}
}
}
if (i == MAX_SOCKETS) {
tvhlog(LOG_DEBUG, "capmt", "%s: no free space for new SID!!!", __FUNCTION__);
return -1;
} else {
capmt->sids[i] = sid;
tvhlog(LOG_DEBUG, "capmt", "%s: added: i=%d", __FUNCTION__, i);
}
}
// check if the socket is still alive by writing 0 bytes
if (capmt->capmt_sock[i] > 0) {
if (write(capmt->capmt_sock[i], NULL, 0) < 0)
capmt->capmt_sock[i] = 0;
else if (found)
else if (capmt->capmt_oscam != 2 && found)
return 0;
}
@ -350,7 +354,8 @@ capmt_service_destroy(th_descrambler_t *td)
capmt_service_t *ct = (capmt_service_t *)td;
/* send stop to client */
capmt_send_stop(ct);
if (ct->ct_capmt->capmt_oscam != 2)
capmt_send_stop(ct);
capmt_caid_ecm_t *cce;
while (!LIST_EMPTY(&ct->ct_caid_ecm))
@ -367,6 +372,9 @@ capmt_service_destroy(th_descrambler_t *td)
tvhcsa_destroy(&ct->ct_csa);
free(ct);
if (ct->ct_capmt->capmt_oscam == 2)
capmt_enumerate_services(ct->ct_capmt, 0, 1);
}
static void
@ -374,11 +382,12 @@ handle_ca0(capmt_t* capmt) {
capmt_service_t *ct;
mpegts_service_t *t;
int ret, bufsize;
int *request;
int *request = NULL;
ca_descr_t *ca;
ca_pid_t *cpd;
int process_key, process_next, cai;
int i, j;
int recvsock = 0;
if (capmt->capmt_oscam)
bufsize = sizeof(int) + sizeof(ca_descr_t);
@ -407,36 +416,62 @@ handle_ca0(capmt_t* capmt) {
break;
}
} else {
process_next = 0;
if (capmt->capmt_sock_ca0[i] > 0) {
ret = recv(capmt->capmt_sock_ca0[i], buffer, bufsize, MSG_DONTWAIT);
if (ret < 0)
process_next = 1;
process_next = 1;
if (capmt->capmt_oscam == 2)
recvsock = capmt->capmt_sock[0];
else
recvsock = capmt->capmt_sock_ca0[i];
if (recvsock > 0) {
request = NULL;
ret = recv(recvsock, buffer, (capmt->capmt_oscam == 2) ? sizeof(int) : bufsize, MSG_DONTWAIT);
if (ret > 0) {
request = (int *) &buffer;
if (capmt->capmt_oscam != 2)
process_next = 0;
else {
int ret = 0;
if (*request == CA_SET_PID) //receive CA_SET_PID
ret = recv(recvsock, buffer+sizeof(int), sizeof(ca_pid_t), MSG_DONTWAIT);
else if (*request == CA_SET_DESCR) //receive CA_SET_DESCR
ret = recv(recvsock, buffer+sizeof(int), sizeof(ca_descr_t), MSG_DONTWAIT);
if (ret > 0)
process_next = 0;
}
}
else if (ret == 0) {
// normal socket shutdown
tvhlog(LOG_INFO, "capmt", "normal socket shutdown");
close(capmt->capmt_sock_ca0[i]);
capmt->capmt_sock_ca0[i] = -1;
int still_left = 0;
for (j = 0; j < MAX_CA; j++) {
if (capmt->capmt_sock_ca0[j] > 0) {
still_left = 1;
break;
// we are not connected any more - set services as unavailable
LIST_FOREACH(ct, &capmt->capmt_services, ct_link) {
if (ct->ct_keystate != CT_FORBIDDEN) {
ct->ct_keystate = CT_FORBIDDEN;
}
}
if (still_left) //this socket is closed but there are others active
process_next = 1;
else //all sockets closed
int still_left = 0;
if (capmt->capmt_oscam != 2) {
close(capmt->capmt_sock_ca0[i]);
capmt->capmt_sock_ca0[i] = -1;
for (j = 0; j < MAX_CA; j++) {
if (capmt->capmt_sock_ca0[j] > 0) {
still_left = 1;
break;
}
}
}
if (!still_left) //all sockets closed
break;
}
} else
process_next = 1;
}
}
if (process_next) {
i++;
if (i >= MAX_CA)
i = 0;
if (capmt->capmt_oscam != 2) {
i++;
if (i >= MAX_CA)
i = 0;
}
usleep(10 * 1000);
continue;
}
@ -444,8 +479,9 @@ handle_ca0(capmt_t* capmt) {
// parsing data
if (capmt->capmt_oscam) {
if (!request)
continue;
cai = i;
request = (int *) &buffer;
if (*request == CA_SET_PID) {
cpd = (ca_pid_t *)&buffer[sizeof(int)];
tvhlog(LOG_DEBUG, "capmt", "CA_SET_PID cai %d req %d (%d %04x)", cai, *request, cpd->index, cpd->pid);
@ -484,35 +520,35 @@ handle_ca0(capmt_t* capmt) {
process_key = 1;
}
// processing key
if (process_key) {
LIST_FOREACH(ct, &capmt->capmt_services, ct_link) {
t = ct->ct_service;
// processing key
if (process_key) {
LIST_FOREACH(ct, &capmt->capmt_services, ct_link) {
t = ct->ct_service;
if(ret < bufsize) {
if(ct->ct_keystate != CT_FORBIDDEN) {
tvhlog(LOG_ERR, "capmt", "Can not descramble service \"%s\", access denied", t->s_dvb_svcname);
if (!capmt->capmt_oscam && ret < bufsize) {
if(ct->ct_keystate != CT_FORBIDDEN) {
tvhlog(LOG_ERR, "capmt", "Can not descramble service \"%s\", access denied", t->s_dvb_svcname);
ct->ct_keystate = CT_FORBIDDEN;
ct->ct_keystate = CT_FORBIDDEN;
}
continue;
}
continue;
if(seq != ct->ct_seq)
continue;
if (memcmp(even, invalid, 8))
tvhcsa_set_key_even(&ct->ct_csa, even);
if (memcmp(odd, invalid, 8))
tvhcsa_set_key_odd(&ct->ct_csa, odd);
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_DEBUG, "capmt", "Obtained key for service \"%s\"",t->s_dvb_svcname);
ct->ct_keystate = CT_RESOLVED;
}
if(seq != ct->ct_seq)
continue;
if (memcmp(even, invalid, 8))
tvhcsa_set_key_even(&ct->ct_csa, even);
if (memcmp(odd, invalid, 8))
tvhcsa_set_key_odd(&ct->ct_csa, odd);
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_DEBUG, "capmt", "Obtained key for service \"%s\"",t->s_dvb_svcname);
ct->ct_keystate = CT_RESOLVED;
}
}
}
tvhlog(LOG_INFO, "capmt", "connection from client closed ...");
@ -563,44 +599,45 @@ capmt_thread(void *aux)
pthread_mutex_unlock(&global_lock);
/* open connection to camd.socket */
capmt->capmt_sock[0] = tvh_socket(AF_LOCAL, SOCK_STREAM, 0);
if (capmt->capmt_oscam == 2)
handle_ca0(capmt);
else {
/* open connection to camd.socket */
capmt->capmt_sock[0] = tvh_socket(AF_LOCAL, SOCK_STREAM, 0);
struct sockaddr_un serv_addr_un;
memset(&serv_addr_un, 0, sizeof(serv_addr_un));
serv_addr_un.sun_family = AF_LOCAL;
snprintf(serv_addr_un.sun_path, sizeof(serv_addr_un.sun_path), "%s", capmt->capmt_sockfile);
struct sockaddr_un serv_addr_un;
memset(&serv_addr_un, 0, sizeof(serv_addr_un));
serv_addr_un.sun_family = AF_LOCAL;
snprintf(serv_addr_un.sun_path, sizeof(serv_addr_un.sun_path), "%s", capmt->capmt_sockfile);
if (connect(capmt->capmt_sock[0], (const struct sockaddr*)&serv_addr_un, sizeof(serv_addr_un)) == 0) {
capmt->capmt_connected = 1;
if (connect(capmt->capmt_sock[0], (const struct sockaddr*)&serv_addr_un, sizeof(serv_addr_un)) == 0) {
capmt->capmt_connected = 1;
/* open connection to emulated ca0 device */
if (!capmt->capmt_oscam) {
bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[0],
capmt->capmt_port);
} else {
int i, n;
extern const idclass_t linuxdvb_adapter_class;
linuxdvb_adapter_t *la;
idnode_set_t *is = idnode_find_all(&linuxdvb_adapter_class);
for (i = 0; i < is->is_count; i++) {
la = (linuxdvb_adapter_t*)is->is_array[i];
if (!la || !la->la_is_enabled(la)) continue;
n = la->la_dvb_number;
if (n < 0 || n > MAX_CA) {
tvhlog(LOG_ERR, "capmt", "adapter number > MAX_CA");
continue;
/* open connection to emulated ca0 device */
if (!capmt->capmt_oscam) {
bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[0], capmt->capmt_port);
} else {
int i, n;
extern const idclass_t linuxdvb_adapter_class;
linuxdvb_adapter_t *la;
idnode_set_t *is = idnode_find_all(&linuxdvb_adapter_class);
for (i = 0; i < is->is_count; i++) {
la = (linuxdvb_adapter_t*)is->is_array[i];
if (!la || !la->la_is_enabled(la)) continue;
n = la->la_dvb_number;
if (n < 0 || n > MAX_CA) {
tvhlog(LOG_ERR, "capmt", "adapter number > MAX_CA");
continue;
}
tvhlog(LOG_INFO, "capmt", "created UDP socket %d", n);
bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[n], capmt->capmt_port + n);
}
tvhlog(LOG_INFO, "capmt", "created UDP socket %d", n);
bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[n],
capmt->capmt_port + n);
}
}
if (bind_ok)
handle_ca0(capmt);
} else
tvhlog(LOG_ERR, "capmt", "Error connecting to %s: %s", capmt->capmt_sockfile, strerror(errno));
if (bind_ok)
handle_ca0(capmt);
} else
tvhlog(LOG_ERR, "capmt", "Error connecting to %s: %s", capmt->capmt_sockfile, strerror(errno));
}
capmt->capmt_connected = 0;
/* close opened sockets */
@ -647,7 +684,6 @@ capmt_table_input(struct th_descrambler *td, struct service *s,
capmt_t *capmt = ct->ct_capmt;
mpegts_service_t *t = (mpegts_service_t*)s;
linuxdvb_frontend_t *lfe;
int adapter_num = -1;
int total_caids = 0, current_caid = 0;
/* Validate */
@ -657,7 +693,6 @@ capmt_table_input(struct th_descrambler *td, struct service *s,
lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
if (!idnode_is_instance(&lfe->ti_id, &linuxdvb_frontend_class))
return;
adapter_num = lfe->lfe_adapter->la_dvb_number;
caid_t *c;
@ -684,7 +719,7 @@ capmt_table_input(struct th_descrambler *td, struct service *s,
uint16_t caid = c->caid;
/* search ecmpid in list */
capmt_caid_ecm_t *cce, *cce2;
capmt_caid_ecm_t *cce;
LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link)
if (cce->cce_caid == caid)
break;
@ -711,133 +746,17 @@ capmt_table_input(struct th_descrambler *td, struct service *s,
break;
}
uint16_t sid = t->s_dvb_service_id;
uint16_t ecmpid = st->es_pid;
uint16_t transponder = t->s_dvb_mux->mm_tsid;
uint16_t onid = t->s_dvb_mux->mm_onid;
/* don't do too much requests */
if (current_caid == total_caids && caid != ct->ct_caid_last)
return;
static uint8_t pmtversion = 1;
/* buffer for capmt */
int pos = 0;
uint8_t buf[4094];
capmt_header_t head = {
.capmt_indicator = { 0x9F, 0x80, 0x32, 0x82, 0x00, 0x00 },
.capmt_list_management = CAPMT_LIST_ONLY,
.program_number = sid,
.version_number = 0,
.current_next_indicator = 0,
.program_info_length = 0,
.capmt_cmd_id = CAPMT_CMD_OK_DESCRAMBLING,
};
memcpy(&buf[pos], &head, sizeof(head));
pos += sizeof(head);
if (capmt->capmt_oscam)
{
capmt_descriptor_t dmd = {
.cad_type = CAPMT_DESC_DEMUX,
.cad_length = 0x02,
.cad_data = {
0, adapter_num }};
memcpy(&buf[pos], &dmd, dmd.cad_length + 2);
pos += dmd.cad_length + 2;
}
capmt_descriptor_t prd = {
.cad_type = CAPMT_DESC_PRIVATE,
.cad_length = 0x08,
.cad_data = { 0x00, 0x00, 0x00, 0x00, // enigma namespace goes here
transponder >> 8, transponder & 0xFF,
onid >> 8, onid & 0xFF
}};
memcpy(&buf[pos], &prd, prd.cad_length + 2);
pos += prd.cad_length + 2;
if (!capmt->capmt_oscam)
{
capmt_descriptor_t dmd = {
.cad_type = CAPMT_DESC_DEMUX,
.cad_length = 0x02,
.cad_data = {
1 << adapter_num, adapter_num }};
memcpy(&buf[pos], &dmd, dmd.cad_length + 2);
pos += dmd.cad_length + 2;
}
capmt_descriptor_t ecd = {
.cad_type = CAPMT_DESC_PID,
.cad_length = 0x02,
.cad_data = {
ecmpid >> 8, ecmpid & 0xFF }};
memcpy(&buf[pos], &ecd, ecd.cad_length + 2);
pos += ecd.cad_length + 2;
LIST_FOREACH(cce2, &ct->ct_caid_ecm, cce_link) {
capmt_descriptor_t cad = {
.cad_type = 0x09,
.cad_length = 0x04,
.cad_data = {
cce2->cce_caid >> 8, cce2->cce_caid & 0xFF,
cce2->cce_ecmpid >> 8 | 0xE0, cce2->cce_ecmpid & 0xFF}};
if (cce2->cce_providerid) { //we need to add provider ID to the data
if (cce2->cce_caid >> 8 == 0x01) {
cad.cad_length = 0x11;
cad.cad_data[4] = cce2->cce_providerid >> 8;
cad.cad_data[5] = cce2->cce_providerid & 0xffffff;
} else if (cce2->cce_caid >> 8 == 0x05) {
cad.cad_length = 0x0f;
cad.cad_data[10] = 0x14;
cad.cad_data[11] = cce2->cce_providerid >> 24;
cad.cad_data[12] = cce2->cce_providerid >> 16;
cad.cad_data[13] = cce2->cce_providerid >> 8;
cad.cad_data[14] = cce2->cce_providerid & 0xffffff;
} else if (cce2->cce_caid >> 8 == 0x18) {
cad.cad_length = 0x07;
cad.cad_data[5] = cce2->cce_providerid >> 8;
cad.cad_data[6] = cce2->cce_providerid & 0xffffff;
} else if (cce2->cce_caid >> 8 == 0x4a) {
cad.cad_length = 0x05;
cad.cad_data[4] = cce2->cce_providerid & 0xffffff;
} else
tvhlog(LOG_WARNING, "capmt", "Unknown CAID type, don't know where to put provider ID");
}
memcpy(&buf[pos], &cad, cad.cad_length + 2);
pos += cad.cad_length + 2;
tvhlog(LOG_DEBUG, "capmt", "adding ECMPID=0x%X (%d), CAID=0x%X (%d) PROVID=0x%X (%d)",
cce2->cce_ecmpid, cce2->cce_ecmpid,
cce2->cce_caid, cce2->cce_caid,
cce2->cce_providerid, cce2->cce_providerid);
}
uint8_t end[] = {
0x01, (ct->ct_seq >> 8) & 0xFF, ct->ct_seq & 0xFF, 0x00, 0x06 };
memcpy(&buf[pos], end, sizeof(end));
pos += sizeof(end);
buf[10] = ((pos - 5 - 12) & 0xF00) >> 8;
buf[11] = ((pos - 5 - 12) & 0xFF);
buf[4] = ((pos - 6) >> 8);
buf[5] = ((pos - 6) & 0xFF);
buf[7] = sid >> 8;
buf[8] = sid & 0xFF;
memcpy(cce->cce_ecm, data, len);
cce->cce_ecmsize = len;
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_DEBUG, "capmt",
"Trying to obtain key for service \"%s\"",t->s_dvb_svcname);
buf[9] = pmtversion;
pmtversion = (pmtversion + 1) & 0x1F;
capmt_send_msg(capmt, sid, buf, pos);
if (capmt->capmt_oscam == 2)
capmt_enumerate_services(capmt, st->es_pid, 0);
else
capmt_send_request(ct, st->es_pid, CAPMT_LIST_ONLY);
break;
}
default:
@ -847,6 +766,166 @@ capmt_table_input(struct th_descrambler *td, struct service *s,
}
}
static void
capmt_send_request(capmt_service_t *ct, int es_pid, int lm)
{
capmt_t *capmt = ct->ct_capmt;
mpegts_service_t *t = ct->ct_service;
uint16_t sid = t->s_dvb_service_id;
uint16_t ecmpid = es_pid;
uint16_t transponder = t->s_dvb_mux->mm_tsid;
uint16_t onid = t->s_dvb_mux->mm_onid;
static uint8_t pmtversion = 1;
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)t->s_dvb_active_input;
int adapter_num = lfe->lfe_adapter->la_dvb_number;
/* buffer for capmt */
int pos = 0;
uint8_t buf[4094];
capmt_header_t head = {
.capmt_indicator = { 0x9F, 0x80, 0x32, 0x82, 0x00, 0x00 },
.capmt_list_management = lm,
.program_number = sid,
.version_number = 0,
.current_next_indicator = 0,
.program_info_length = 0,
.capmt_cmd_id = CAPMT_CMD_OK_DESCRAMBLING,
};
memcpy(&buf[pos], &head, sizeof(head));
pos += sizeof(head);
if (capmt->capmt_oscam) {
capmt_descriptor_t dmd = {
.cad_type = CAPMT_DESC_DEMUX,
.cad_length = 0x02,
.cad_data = {
0, adapter_num }};
memcpy(&buf[pos], &dmd, dmd.cad_length + 2);
pos += dmd.cad_length + 2;
}
capmt_descriptor_t prd = {
.cad_type = CAPMT_DESC_PRIVATE,
.cad_length = 0x08,
.cad_data = { 0x00, 0x00, 0x00, 0x00, // enigma namespace goes here
transponder >> 8, transponder & 0xFF,
onid >> 8, onid & 0xFF }};
memcpy(&buf[pos], &prd, prd.cad_length + 2);
pos += prd.cad_length + 2;
if (!capmt->capmt_oscam) {
capmt_descriptor_t dmd = {
.cad_type = CAPMT_DESC_DEMUX,
.cad_length = 0x02,
.cad_data = {
1 << adapter_num, adapter_num }};
memcpy(&buf[pos], &dmd, dmd.cad_length + 2);
pos += dmd.cad_length + 2;
}
capmt_descriptor_t ecd = {
.cad_type = CAPMT_DESC_PID,
.cad_length = 0x02,
.cad_data = {
ecmpid >> 8, ecmpid & 0xFF }};
memcpy(&buf[pos], &ecd, ecd.cad_length + 2);
pos += ecd.cad_length + 2;
capmt_caid_ecm_t *cce2;
LIST_FOREACH(cce2, &ct->ct_caid_ecm, cce_link) {
capmt_descriptor_t cad = {
.cad_type = 0x09,
.cad_length = 0x04,
.cad_data = {
cce2->cce_caid >> 8, cce2->cce_caid & 0xFF,
cce2->cce_ecmpid >> 8 | 0xE0, cce2->cce_ecmpid & 0xFF}};
if (cce2->cce_providerid) { //we need to add provider ID to the data
if (cce2->cce_caid >> 8 == 0x01) {
cad.cad_length = 0x11;
cad.cad_data[4] = cce2->cce_providerid >> 8;
cad.cad_data[5] = cce2->cce_providerid & 0xffffff;
} else if (cce2->cce_caid >> 8 == 0x05) {
cad.cad_length = 0x0f;
cad.cad_data[10] = 0x14;
cad.cad_data[11] = cce2->cce_providerid >> 24;
cad.cad_data[12] = cce2->cce_providerid >> 16;
cad.cad_data[13] = cce2->cce_providerid >> 8;
cad.cad_data[14] = cce2->cce_providerid & 0xffffff;
} else if (cce2->cce_caid >> 8 == 0x18) {
cad.cad_length = 0x07;
cad.cad_data[5] = cce2->cce_providerid >> 8;
cad.cad_data[6] = cce2->cce_providerid & 0xffffff;
} else if (cce2->cce_caid >> 8 == 0x4a) {
cad.cad_length = 0x05;
cad.cad_data[4] = cce2->cce_providerid & 0xffffff;
} else
tvhlog(LOG_WARNING, "capmt", "Unknown CAID type, don't know where to put provider ID");
}
memcpy(&buf[pos], &cad, cad.cad_length + 2);
pos += cad.cad_length + 2;
tvhlog(LOG_DEBUG, "capmt", "adding ECMPID=0x%X (%d), CAID=0x%X (%d) PROVID=0x%X (%d)",
cce2->cce_ecmpid, cce2->cce_ecmpid,
cce2->cce_caid, cce2->cce_caid,
cce2->cce_providerid, cce2->cce_providerid);
}
uint8_t end[] = {
0x01, (ct->ct_seq >> 8) & 0xFF, ct->ct_seq & 0xFF, 0x00, 0x06 };
memcpy(&buf[pos], end, sizeof(end));
pos += sizeof(end);
buf[10] = ((pos - 5 - 12) & 0xF00) >> 8;
buf[11] = ((pos - 5 - 12) & 0xFF);
buf[4] = ((pos - 6) >> 8);
buf[5] = ((pos - 6) & 0xFF);
buf[7] = sid >> 8;
buf[8] = sid & 0xFF;
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_DEBUG, "capmt",
"Trying to obtain key for service \"%s\"",t->s_dvb_svcname);
buf[9] = pmtversion;
pmtversion = (pmtversion + 1) & 0x1F;
capmt_send_msg(capmt, sid, buf, pos);
}
static void
capmt_enumerate_services(capmt_t *capmt, int es_pid, int force)
{
int lm = CAPMT_LIST_FIRST; //list management
int all_srv_count = 0; //all services
int res_srv_count = 0; //services with resolved state
int i = 0;
capmt_service_t *ct;
LIST_FOREACH(ct, &capmt->capmt_services, ct_link) {
all_srv_count++;
if (ct->ct_keystate == CT_RESOLVED)
res_srv_count++;
}
if (!all_srv_count && !res_srv_count) {
// closing socket (oscam handle this as event and stop decrypting)
tvhlog(LOG_DEBUG, "capmt", "%s: no subscribed services, closing socket, fd=%d", __FUNCTION__, capmt->capmt_sock[0]);
if (capmt->capmt_sock[0] > 0)
close(capmt->capmt_sock[0]);
capmt->capmt_sock[0] = 0;
}
else if (force || (res_srv_count != all_srv_count)) {
LIST_FOREACH(ct, &capmt->capmt_services, ct_link) {
if (all_srv_count == i + 1)
lm |= CAPMT_LIST_LAST;
capmt_send_request(ct, es_pid, lm);
lm = CAPMT_LIST_MORE;
i++;
}
}
}
/**
*
@ -922,6 +1001,7 @@ capmt_service_start(service_t *s)
tvhcsa_init(&ct->ct_csa);
ct->ct_capmt = capmt;
ct->ct_service = t;
ct->ct_seq = capmt->capmt_seq++;
TAILQ_FOREACH(st, &t->s_components, es_link) {
@ -1023,7 +1103,7 @@ capmt_record_build(capmt_t *capmt)
htsmsg_add_str(e, "camdfilename", capmt->capmt_sockfile ?: "");
htsmsg_add_u32(e, "port", capmt->capmt_port);
htsmsg_add_u32(e, "oscam", !!capmt->capmt_oscam);
htsmsg_add_u32(e, "oscam", capmt->capmt_oscam);
htsmsg_add_str(e, "comment", capmt->capmt_comment ?: "");
return e;

View file

@ -13,6 +13,24 @@ tvheadend.capmteditor = function() {
meta.attr = 'style="color:red;"';
}
}
var selectMode = new Ext.form.ComboBox({
displayField:'name',
valueField: 'res',
value: 2,
mode: 'local',
editable: false,
triggerAction: 'all',
emptyText: 'Select mode...',
store: new Ext.data.SimpleStore({
fields: ['res','name'],
id: 0,
data: [
['2','Recent OSCam (svn rev >= 9063)'],
['1','Older OSCam'],
['0','Wrapper (capmt_ca.so)']
]
})
});
var cm = new Ext.grid.ColumnModel({
defaultSortable: true,
@ -21,7 +39,12 @@ tvheadend.capmteditor = function() {
header : "Enabled",
dataIndex : 'enabled',
width : 60
}, {
}, {
header: "Mode",
dataIndex: 'oscam',
width: 150,
editor: selectMode
}, {
header : "Camd.socket Filename",
dataIndex : 'camdfilename',
width : 200,
@ -43,12 +66,6 @@ tvheadend.capmteditor = function() {
allowBlank : false
})
}, {
xtype: 'checkcolumn',
header : "OSCam mode",
dataIndex : 'oscam',
width : 60
} , {
header : "Comment",
dataIndex : 'comment',
width : 400,