void linuxdvb_ca_enqueue_capmt(linuxdvb_ca_t *lca, uint8_t slot, const uint8_t *ptr, int len, uint8_t list_mgmt, uint8_t cmd_id) { linuxdvb_ca_capmt_t *lcc; int c = 1; if (!lca) return; if (lca->lca_capmt_query && cmd_id == CA_PMT_CMD_ID_OK_DESCRAMBLING) c = 2; while (c--) { lcc = calloc(1, sizeof(*lcc)); if (!lcc) return; lcc->data = malloc(len); lcc->len = len; lcc->slot = slot; lcc->list_mgmt = list_mgmt; lcc->cmd_id = (c ? CA_PMT_CMD_ID_QUERY : cmd_id); memcpy(lcc->data, ptr, len); TAILQ_INSERT_TAIL(&lca->lca_capmt_queue, lcc, lcc_link); tvhtrace(LS_EN50221, "%s CAPMT enqueued (%s)", ca_pmt_cmd_id2str(lcc->cmd_id), ca_pmt_list_mgmt2str(lcc->list_mgmt)); } mtimer_arm_rel(&lca->lca_capmt_queue_timer, linuxdvb_ca_process_capmt_queue, lca, ms2mono(50)); }
static void linuxdvb_ca_process_capmt_queue ( void *aux ) { linuxdvb_ca_t *lca = aux; linuxdvb_ca_capmt_t *lcc; struct section *section; struct section_ext *result; struct mpeg_pmt_section *pmt; uint8_t capmt[4096]; int size, i; lcc = TAILQ_FIRST(&lca->lca_capmt_queue); if (!lcc) return; if (!(section = section_codec(lcc->data, lcc->len))){ tvherror("en50221", "failed to decode PMT section"); goto done; } if (!(result = section_ext_decode(section, 0))){ tvherror("en50221", "failed to decode PMT ext_section"); goto done; } if (!(pmt = mpeg_pmt_section_codec(result))){ tvherror("en50221", "failed to decode PMT"); goto done; } size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), 0, lcc->list_mgmt, lcc->cmd_id); if (size < 0) { tvherror("en50221", "Failed to format CAPMT"); } if (en50221_app_ca_pmt(lca->lca_ca_resource, lca->lca_ca_session_number, capmt, size)) { tvherror("en50221", "Failed to send CAPMT"); } tvhtrace("en50221", "%s CAPMT sent (%s)", ca_pmt_cmd_id2str(lcc->cmd_id), ca_pmt_list_mgmt2str(lcc->list_mgmt)); tvhlog_hexdump("en50221", capmt, size); done: i = (lcc->cmd_id == CA_PMT_CMD_ID_QUERY) ? lca->lca_capmt_query_interval : lca->lca_capmt_interval; TAILQ_REMOVE(&lca->lca_capmt_queue, lcc, lcc_link); free(lcc->data); free(lcc); if (!TAILQ_EMPTY(&lca->lca_capmt_queue)) { gtimer_arm_ms(&lca->lca_capmt_queue_timer, linuxdvb_ca_process_capmt_queue, lca, i); } }