void coolapi_close_all(void) { if(dmx_opened) { int32_t result; int32_t i, j; for(i = 0; i < MAX_COOL_DMX; i++) { for(j = 0; j < MAX_FILTER; j++) { if(cdemuxes[i][j].fd > 0) { coolapi_remove_filter(cdemuxes[i][j].fd, cdemuxes[i][j].filter_num); coolapi_close_device(cdemuxes[i][j].fd); } } } for(i = 0; i < MAX_COOL_DMX; i++) { result = cnxt_dmx_close(dmx_device[i]); coolapi_check_error("cnxt_dmx_close", result); dmx_device[i] = NULL; } } cool_kal_opened = 0; cnxt_kal_terminate(); cnxt_drv_term(); }
static int32_t Cool_Init(struct s_reader *reader) { char *device = reader->device; int32_t reader_nb = 0; // this is to stay compatible with older config. if(strlen(device)) { reader_nb = atoi((const char *)device); } if(reader_nb > 1) { // there are only 2 readers in the coolstream : 0 or 1 rdr_log(reader, "Coolstream reader device can only be 0 or 1"); return 0; } if(!cs_malloc(&reader->crdr_data, sizeof(struct cool_data))) { return ERROR; } struct cool_data *crdr_data = reader->crdr_data; if(cnxt_smc_open(&crdr_data->handle, &reader_nb, NULL, NULL)) { return 0; } int32_t ret = cnxt_smc_enable_flow_control(crdr_data->handle, 0); coolapi_check_error("cnxt_smc_enable_flow_control", ret); crdr_data->cardbuflen = 0; crdr_data->pps = 0; return OK; }
static int32_t Cool_Transmit(struct s_reader *reader, unsigned char *sent, uint32_t size, uint32_t expectedlen, uint32_t UNUSED(delay), uint32_t UNUSED(timeout)) { struct cool_data *crdr_data = reader->crdr_data; int32_t ret; memset(crdr_data->cardbuffer, 0, 512); if(reader->protocol_type == ATR_PROTOCOL_TYPE_T0) { crdr_data->cardbuflen = expectedlen; ret = cnxt_smc_read_write(crdr_data->handle, 0, sent, size, crdr_data->cardbuffer, &crdr_data->cardbuflen, 0, NULL); } else { crdr_data->cardbuflen = 512; ret = cnxt_smc_read_write(crdr_data->handle, 0, sent, size, crdr_data->cardbuffer, &crdr_data->cardbuflen, 4000, NULL); } coolapi_check_error("cnxt_smc_read_write", ret); rdr_log_dump_dbg(reader, D_DEVICE, sent, size, "COOL Transmit:"); if(ret) { return ERROR; } return OK; }
int32_t Cool_WriteSettings (struct s_reader *reader, uint32_t UNUSED(BWT), uint32_t UNUSED(CWT), uint32_t UNUSED(EGT), uint32_t UNUSED(BGT)) { //this code worked with old cnxt_lnx.ko, but prevented nagra cards from working with new cnxt_lnx.ko /* struct { unsigned short CardActTime; //card activation time (in clock cycles = 1/54Mhz) unsigned short CardDeactTime; //card deactivation time (in clock cycles = 1/54Mhz) unsigned short ATRSTime; //ATR first char timeout in clock cycles (1/f) unsigned short ATRDTime; //ATR duration in ETU unsigned long BWT; unsigned long CWT; unsigned char EGT; unsigned char BGT; } params; params.BWT = BWT; params.CWT = CWT; params.EGT = EGT; params.BGT = BGT; call (cnxt_smc_set_config_timeout(specdev()->handle, params)); rdr_debug_mask(reader, D_DEVICE, "COOL WriteSettings OK");*/ //set freq back to reader->mhz if necessary uint32_t clk; int32_t ret = cnxt_smc_get_clock_freq (specdev()->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if (clk/10000 != (uint32_t)reader->mhz) { rdr_debug_mask(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i", clk, reader->mhz * 10000); call (Cool_SetClockrate(reader, reader->mhz)); } return OK; }
/* write cw to all demuxes in mask with passed index */ int32_t coolapi_write_cw(int32_t mask, uint16_t *STREAMpids, int32_t count, ca_descr_t *ca_descr) { int32_t i, idx = ca_descr->index; int32_t result; void *channel; cs_log_dbg(D_DVBAPI, "cw%d: mask %d index %d pid count %d", ca_descr->parity, mask, idx, count); for(i = 0; i < count; i++) { int32_t pid = STREAMpids[i]; int32_t j; for(j = 0; j < MAX_COOL_DMX; j++) { if(mask & (1 << j)) { result = cnxt_dmx_get_channel_from_pid(dmx_handles[j].handle, pid, &channel); if(result == 0) { cs_log_dbg(D_DVBAPI, "Found demux %d channel %x for pid %04x", j, (int32_t) channel, pid); result = cnxt_dmx_set_channel_key(channel, 0, ca_descr->parity, ca_descr->cw, 8); coolapi_check_error("cnxt_dmx_set_channel_key", result); if(result != 0) { cs_log("set_channel_key failed for demux %d pid %04x", j, pid); } } } } } return 0; }
static void coolapi_dmx_open(void) { int32_t result = 0; device_open_arg_t devarg; if(!dmx_opened) { int32_t i; cs_log_dbg(D_DVBAPI, "Open Coolstream DMX API"); memset(&devarg, 0, sizeof(device_open_arg_t)); devarg.unknown1 = 1; devarg.unknown3 = 3; devarg.unknown6 = 1; for(i = 0; i < MAX_COOL_DMX; i++) { devarg.number = i; result = cnxt_dmx_open(&dmx_handles[i].handle, &devarg, NULL, NULL); coolapi_check_error("cnxt_dmx_open", result); } dmx_opened = 1; } }
static int32_t Cool_Init (struct s_reader *reader) { char *device = reader->device; int32_t reader_nb = 0; // this is to stay compatible with older config. if(strlen(device)) reader_nb=atoi((const char *)device); if(reader_nb>1) { // there are only 2 readers in the coolstream : 0 or 1 rdr_log(reader, "Coolstream reader device can only be 0 or 1"); return 0; } if (!cs_malloc(&reader->spec_dev, sizeof(struct s_coolstream_reader))) return 0; if (cnxt_smc_open (&specdev()->handle, &reader_nb, NULL, NULL)) return 0; int32_t ret = cnxt_smc_enable_flow_control(specdev()->handle, 1); coolapi_check_error("cnxt_smc_enable_flow_control", ret); specdev()->cardbuflen = 0; if (reader->cool_timeout_init > 0) { rdr_debug_mask(reader, D_DEVICE, "init timeout set to cool_timeout_init = %i", reader->cool_timeout_init); specdev()->read_write_transmit_timeout = reader->cool_timeout_init; } else { rdr_debug_mask(reader, D_DEVICE, "No init timeout specified - using value from ATR. If you encounter any problems while card init try to use the reader parameter cool_timeout_init = 500"); specdev()->read_write_transmit_timeout = -1; } return OK; }
void coolapi_open(void) { int32_t result = 0; device_open_arg_t devarg; if(!dmx_opened) { int32_t i; cs_debug_mask(D_DVBAPI, "Open Coolstream DMX API"); cnxt_cbuf_init(NULL); cnxt_dmx_init(NULL); memset(&devarg, 0, sizeof(device_open_arg_t)); devarg.unknown1 = 1; devarg.unknown3 = 3; devarg.unknown6 = 1; for(i = 0; i < MAX_COOL_DMX; i++) { devarg.number = i; result = cnxt_dmx_open (&dmx_device[i], &devarg, NULL, NULL); coolapi_check_error("cnxt_dmx_open", result); } dmx_opened = 1; } }
int32_t Cool_FastReset_With_ATR (struct s_reader *reader, ATR * atr) { int32_t n = 40, ret; unsigned char buf[40]; //reset card ret = cnxt_smc_reset_card (specdev()->handle, ATR_TIMEOUT, NULL, NULL); coolapi_check_error("cnxt_smc_reset_card", ret); cs_sleepms(50); ret = cnxt_smc_get_atr (specdev()->handle, buf, &n); coolapi_check_error("cnxt_smc_get_atr", ret); call (!ATR_InitFromArray (atr, buf, n) == ATR_OK); { cs_sleepms(50); return OK; } }
static int32_t Cool_Close (struct s_reader *reader) { if (cool_kal_opened) { int32_t ret = cnxt_smc_close (specdev()->handle); coolapi_check_error("cnxt_smc_close", ret); } NULLFREE(reader->spec_dev); return OK; }
static int32_t Cool_Close(struct s_reader *reader) { struct cool_data *crdr_data = reader->crdr_data; if(cool_kal_opened) { int32_t ret = cnxt_smc_close(crdr_data->handle); coolapi_check_error("cnxt_smc_close", ret); } return OK; }
static int32_t Cool_SetClockrate (struct s_reader *reader, int32_t mhz) { uint32_t clk; clk = mhz * 10000; int32_t ret = cnxt_smc_set_clock_freq (specdev()->handle, clk); coolapi_check_error("cnxt_smc_set_clock_freq", ret); call (Cool_FastReset(reader)); rdr_debug_mask(reader, D_DEVICE, "COOL: clock succesfully set to %i", clk); return OK; }
int32_t Cool_Transmit (struct s_reader *reader, BYTE * sent, uint32_t size) { specdev()->cardbuflen = 256;//it needs to know max buffer size to respond? int32_t ret = cnxt_smc_read_write(specdev()->handle, FALSE, sent, size, specdev()->cardbuffer, &specdev()->cardbuflen, specdev()->read_write_transmit_timeout, 0); coolapi_check_error("cnxt_smc_read_write", ret); rdr_ddump_mask(reader, D_DEVICE, sent, size, "COOL Transmit:"); return OK; }
static int32_t Cool_SetClockrate(struct s_reader *reader, int32_t mhz) { struct cool_data *crdr_data = reader->crdr_data; uint32_t clk; clk = mhz * 10000; int32_t ret = cnxt_smc_set_clock_freq(crdr_data->handle, clk); coolapi_check_error("cnxt_smc_set_clock_freq", ret); call(Cool_FastReset(reader)); rdr_log_dbg(reader, D_DEVICE, "COOL: clock succesfully set to %i", clk); return OK; }
static int32_t Cool_Reset(struct s_reader *reader, ATR *atr) { struct cool_data *crdr_data = reader->crdr_data; int32_t ret; if(!reader->ins7e11_fast_reset) { //set freq to reader->cardmhz if necessary uint32_t clk; ret = cnxt_smc_get_clock_freq(crdr_data->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if(clk / 10000 != (uint32_t)reader->cardmhz) { rdr_log_dbg(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i for card reset", clk, reader->cardmhz * 10000); call(Cool_SetClockrate(reader, reader->cardmhz)); } } else { rdr_log(reader, "Doing fast reset"); } //reset card ret = cnxt_smc_reset_card(crdr_data->handle, ATR_TIMEOUT, NULL, NULL); coolapi_check_error("cnxt_smc_reset_card", ret); cs_sleepms(50); int32_t n = ATR_MAX_SIZE; unsigned char buf[ATR_MAX_SIZE]; ret = cnxt_smc_get_atr(crdr_data->handle, buf, &n); coolapi_check_error("cnxt_smc_get_atr", ret); call(!ATR_InitFromArray(atr, buf, n) != ERROR); { cs_sleepms(50); return OK; } }
int32_t coolapi_read(dmx_t *dmx, dmx_callback_data_t *data) { if(!dmx) { cs_debug_mask(D_DVBAPI, "dmx is NULL!"); return -1; } int32_t result; uint32_t done = 0, toread, len = data->len; uchar *buff = &dmx->buffer[0]; uint32_t bytes_used = 0; //cs_debug_mask(D_DVBAPI, "dmx channel %x pid %x len %d", (int) dmx->channel, dmx->pid, len); result = cnxt_cbuf_get_used(data->buf, &bytes_used); coolapi_check_error("cnxt_cbuf_get_used", result); if(bytes_used == 0) { return -1; } result = cnxt_cbuf_read_data(data->buf, buff, 3, &done); coolapi_check_error("cnxt_cbuf_read_data", result); if(done != 3) { return -1; } toread = ((buff[1] << 8) | buff[2]) & 0xFFF; if((toread + 3) > len) { return -1; } result = cnxt_cbuf_read_data(data->buf, buff + 3, toread, &done); coolapi_check_error("cnxt_cbuf_read_data", result); if(done != toread) { return -1; } done += 3; //cs_debug_mask(D_DVBAPI, "bytes read %d\n", done); return 0; }
static int32_t Cool_WriteSettings (struct s_reader *reader, uint32_t UNUSED(BWT), uint32_t UNUSED(CWT), uint32_t UNUSED(EGT), uint32_t UNUSED(BGT)) { //first set freq back to reader->mhz if necessary uint32_t clk; int32_t ret = cnxt_smc_get_clock_freq (specdev()->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if (clk/10000 != (uint32_t)reader->mhz) { rdr_debug_mask(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i", clk, reader->mhz * 10000); call (Cool_SetClockrate(reader, reader->mhz)); } //driver sets values in ETU automatically (except read_write_transmit_timeout) //... but lets see what the driver did uint16_t F; uint8_t D; ret = cnxt_smc_get_F_D_factors(specdev()->handle, &F, &D); coolapi_check_error("cnxt_smc_get_F_D_factors", ret); char *protocol; CNXT_SMC_COMM comm; ret = cnxt_smc_get_comm_parameters(specdev()->handle, &comm); coolapi_check_error("cnxt_smc_get_comm_parameters", ret); if (comm.protocol==0x01) protocol = "T0"; else if (comm.protocol==0x02) protocol = "T1"; else if (comm.protocol==0x04) protocol = "T14"; else protocol = "unknown"; rdr_log(reader, "Driver Settings: Convention=%s, Protocol=%s, FI=%i, F=%i, N=%i, DI=%i, D=%i, PI1=%i, PI2=%i, II=%i, TXRetries=%i, RXRetries=%i, FilterProtocolBytes=%i", comm.convention ? "Inverse" : "Direct", protocol, comm.FI, F, comm.N, comm.DI, D, comm.PI1, comm.PI2, comm.II, comm.retries.TXRetries, comm.retries.RXRetries, comm.filterprotocolbytes); CNXT_SMC_TIMEOUT timeout; ret = cnxt_smc_get_config_timeout(specdev()->handle, &timeout); coolapi_check_error("cnxt_smc_get_config_timeout", ret); rdr_log(reader, "Driver Settings: CardActTime=%i, CardDeactTime=%i, ATRSTime=%i, ATRDTime=%i, BLKTime=%i, CHTime=%i, CHGuardTime=%i, BKGuardTime=%i", timeout.CardActTime, timeout.CardDeactTime, timeout.ATRSTime, timeout.ATRDTime, timeout.BLKTime, timeout.CHTime, timeout.CHGuardTime, timeout.BKGuardTime); return OK; }
static int32_t Cool_Transmit (struct s_reader *reader, unsigned char * sent, uint32_t size, uint32_t UNUSED(delay), uint32_t timeout) { int32_t ret; specdev()->cardbuflen = 512;//it needs to know max buffer size to respond? if (specdev()->read_write_transmit_timeout == -1) ret = cnxt_smc_read_write(specdev()->handle, 0, sent, size, specdev()->cardbuffer, &specdev()->cardbuflen, timeout, NULL); else ret = cnxt_smc_read_write(specdev()->handle, 0, sent, size, specdev()->cardbuffer, &specdev()->cardbuflen, specdev()->read_write_transmit_timeout, NULL); coolapi_check_error("cnxt_smc_read_write", ret); rdr_ddump_mask(reader, D_DEVICE, sent, size, "COOL Transmit:"); return OK; }
static int32_t Cool_Reset (struct s_reader *reader, ATR * atr) { int32_t ret; if (!reader->ins7e11_fast_reset) { //set freq to reader->cardmhz if necessary uint32_t clk; ret = cnxt_smc_get_clock_freq (specdev()->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if (clk/10000 != (uint32_t)reader->cardmhz) { rdr_debug_mask(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i for card reset", clk, reader->cardmhz*10000); call (Cool_SetClockrate(reader, reader->cardmhz)); } } else { rdr_debug_mask(reader, D_DEVICE, "fast reset needed, restoring transmit parameter for coolstream device %s", reader->device); call(Cool_Set_Transmit_Timeout(reader, 0)); rdr_log(reader, "Doing fast reset"); } //reset card ret = cnxt_smc_reset_card (specdev()->handle, ATR_TIMEOUT, NULL, NULL); coolapi_check_error("cnxt_smc_reset_card", ret); cs_sleepms(50); int32_t n = ATR_MAX_SIZE; unsigned char buf[ATR_MAX_SIZE]; ret = cnxt_smc_get_atr (specdev()->handle, buf, &n); coolapi_check_error("cnxt_smc_get_atr", ret); call (!ATR_InitFromArray (atr, buf, n) != ERROR); { cs_sleepms(50); return OK; } }
static void coolapi_dmx_close(void) { if(dmx_opened) { int32_t result; int32_t i; for(i = 0; i < MAX_COOL_DMX; i++) { result = cnxt_dmx_close(dmx_handles[i].handle); coolapi_check_error("cnxt_dmx_close", result); dmx_handles[i].handle = NULL; } dmx_opened = 0; } }
static int32_t Cool_SetProtocol(struct s_reader *reader, unsigned char *params, uint32_t *UNUSED(length), uint32_t UNUSED(len_request)) { struct cool_data *crdr_data = reader->crdr_data; unsigned char pps[4], response[6]; uint8_t len = 0; //Driver sets PTSS and PCK on its own pps[0] = params[1]; //PPS0 pps[1] = params[2]; //PPS1 int32_t ret = cnxt_smc_start_pps(crdr_data->handle, pps, response, &len, 1); coolapi_check_error("cnxt_smc_start_pps", ret); if(ret) { return ERROR; } crdr_data->pps = 1; return OK; }
static int32_t Cool_GetStatus (struct s_reader *reader, int32_t * in) { if (cool_kal_opened) { int32_t state; int32_t ret = cnxt_smc_get_state(specdev()->handle, &state); if (ret) { coolapi_check_error("cnxt_smc_get_state", ret); return ERROR; } //state = 0 no card, 1 = not ready, 2 = ready if (state) *in = 1; //CARD, even if not ready report card is in, or it will never get activated else *in = 0; //NOCARD } else { *in = 0; } return OK; }
int32_t coolapi_remove_filter (int32_t fd, int32_t num) { dmx_t * dmx = find_demux(fd, 0); if(!dmx) { cs_debug_mask(D_DVBAPI, "dmx is NULL!"); return -1; } if(dmx->pid <= 0) return -1; int32_t result, filter_on_channel=0; cs_debug_mask(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04x on channel=%x", fd, num, dmx->pid, (int32_t) dmx->channel); pthread_mutex_lock(&dmx->mutex); if(dmx->filter) { result = cnxt_dmx_channel_detach_filter(dmx->channel, dmx->filter); coolapi_check_error("cnxt_dmx_channel_detach_filter", result); result = cnxt_dmx_close_filter(dmx->filter); coolapi_check_error("cnxt_dmx_close_filter", result); dmx->filter = NULL; result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); } LL_ITER itr = ll_iter_create(ll_cool_filter); S_COOL_FILTER *filter_item; while ((filter_item=ll_iter_next(&itr))) { if (filter_item->channel == (int32_t) dmx->channel) filter_on_channel++; if (filter_item->fd == fd) { ll_iter_remove_data(&itr); filter_on_channel--; } } if (!filter_on_channel) { cs_debug_mask(D_DVBAPI, "closing channel %x", (int32_t) dmx->channel); itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while ((handle_item=ll_iter_next(&itr))) { if (handle_item->demux_index == dmx->demux_index && handle_item->pid == dmx->pid) { dmx->buffer1=handle_item->buffer1; dmx->buffer2=handle_item->buffer2; ll_iter_remove_data(&itr); break; } } if (!dmx->buffer1 || !dmx->buffer2) cs_debug_mask(D_DVBAPI, "WARNING: buffer handle not found!"); result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); result = cnxt_dmx_set_channel_pid(dmx->channel, 0x1FFF); coolapi_check_error("cnxt_dmx_set_channel_pid", result); result = cnxt_cbuf_flush (dmx->buffer1, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_flush (dmx->buffer2, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_detach(dmx->buffer2, 2, dmx->channel); coolapi_check_error("cnxt_cbuf_detach", result); result = cnxt_dmx_channel_detach(dmx->channel, 0xB, 0, dmx->buffer1); coolapi_check_error("cnxt_dmx_channel_detach", result); result = cnxt_dmx_channel_close(dmx->channel); coolapi_check_error("cnxt_dmx_channel_close", result); result = cnxt_cbuf_close(dmx->buffer2); coolapi_check_error("cnxt_cbuf_close", result); result = cnxt_cbuf_close(dmx->buffer1); coolapi_check_error("cnxt_cbuf_close", result); } if (filter_on_channel) { result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); } pthread_mutex_unlock(&dmx->mutex); dmx->pid = -1; return 0; }
int32_t coolapi_set_filter (int32_t fd, int32_t num, int32_t pid, uchar * flt, uchar * mask, int32_t type) { dmx_t * dmx = find_demux(fd, 0); if(!dmx) { cs_debug_mask(D_DVBAPI, "dmx is NULL!"); return -1; } int32_t result, channel_found=0; void * channel = NULL; if (ll_count(ll_cool_chanhandle) > 0) { LL_ITER itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while ((handle_item=ll_iter_next(&itr))) { if (handle_item->demux_index == dmx->demux_index && handle_item->pid == pid) { channel = handle_item->channel; channel_found=1; break; } } } if (!channel) { buffer_open_arg_t bufarg; int32_t uBufferSize = 8256; memset(&bufarg, 0, sizeof(bufarg)); bufarg.type = 3; bufarg.size = uBufferSize; bufarg.unknown3 = (uBufferSize * 7) / 8; result = cnxt_cbuf_open(&dmx->buffer1, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); bufarg.type = 0; result = cnxt_cbuf_open(&dmx->buffer2, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); channel_open_arg_t chanarg; memset(&chanarg, 0, sizeof(channel_open_arg_t)); chanarg.type = 4; result = cnxt_dmx_channel_open(dmx->device, &dmx->channel, &chanarg, dmx_callback, dmx); coolapi_check_error("cnxt_dmx_channel_open", result); result = cnxt_dmx_set_channel_buffer(dmx->channel, 0, dmx->buffer1); coolapi_check_error("cnxt_dmx_set_channel_buffer", result); result = cnxt_dmx_channel_attach(dmx->channel, 0xB, 0, dmx->buffer2); coolapi_check_error("cnxt_dmx_channel_attach", result); result = cnxt_cbuf_attach(dmx->buffer2, 2, dmx->channel); coolapi_check_error("cnxt_cbuf_attach", result); result = cnxt_dmx_set_channel_pid(dmx->channel, pid); coolapi_check_error("cnxt_dmx_set_channel_pid", result); result = cnxt_cbuf_flush (dmx->buffer1, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_flush (dmx->buffer2, 0); coolapi_check_error("cnxt_cbuf_flush", result); S_COOL_CHANHANDLE *handle_item; if (cs_malloc(&handle_item,sizeof(S_COOL_CHANHANDLE))) { handle_item->pid = pid; handle_item->channel = dmx->channel; handle_item->buffer1 = dmx->buffer1; handle_item->buffer2 = dmx->buffer2; handle_item->demux_index = dmx->demux_index; ll_append(ll_cool_chanhandle, handle_item); } cs_debug_mask(D_DVBAPI, "opened new channel %x", (int32_t) dmx->channel); } else { channel_found=1; dmx->channel = channel; dmx->buffer1 = NULL; dmx->buffer2 = NULL; } cs_debug_mask(D_DVBAPI, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x", fd, dmx->demux_index, (int32_t) dmx->channel, num, pid, flt[0], mask[0]); pthread_mutex_lock(&dmx->mutex); filter_set_t filter; dmx->filter_num = num; dmx->pid = pid; dmx->type = type; memset(&filter, 0, sizeof(filter)); filter.length = 12; memcpy(filter.filter, flt, 16); memcpy(filter.mask, mask, 16); result = cnxt_dmx_open_filter(dmx->device, &dmx->filter); coolapi_check_error("cnxt_dmx_open_filter", result); result = cnxt_dmx_set_filter(dmx->filter, &filter, NULL); coolapi_check_error("cnxt_dmx_set_filter", result); result = cnxt_dmx_channel_attach_filter(dmx->channel, dmx->filter); coolapi_check_error("cnxt_dmx_channel_attach_filter", result); if (channel_found) { result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); } result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); pthread_mutex_unlock(&dmx->mutex); S_COOL_FILTER *filter_item; if (cs_malloc(&filter_item,sizeof(S_COOL_FILTER))) { // fill filter item filter_item->fd = fd; filter_item->pid = pid; filter_item->channel = (int32_t) dmx->channel; memcpy(filter_item->filter16, flt, 16); memcpy(filter_item->mask16, mask, 16); //add filter item ll_append(ll_cool_filter, filter_item); } return 0; }
int32_t coolapi_set_filter(int32_t fd, int32_t num, int32_t pid, uchar *flt, uchar *mask, int32_t type) { dmx_t *dmx = find_demux(fd, 0); if(!dmx) { cs_log_dbg(D_DVBAPI, "dmx is NULL!"); return -1; } int32_t result, channel_found; SAFE_MUTEX_LOCK(&dmx->mutex); // Find matching channel, if it exists. S_COOL_CHANHANDLE *handle_item = find_chanhandle(COOLDEMUX_DMX_DEV(fd), pid); if(!handle_item) { // No channel was found, allocate one buffer_open_arg_t bufarg; int32_t uBufferSize = 8192 + 64; /* Mark that we did not find any open channel on this PID */ channel_found = 0; if(!cs_malloc(&handle_item, sizeof(S_COOL_CHANHANDLE))) { return -1; } memset(&bufarg, 0, sizeof(bufarg)); #ifdef HAVE_COOLAPI2 bufarg.poolid = 5 #endif bufarg.type = 3; bufarg.size = uBufferSize; bufarg.hwm = (uBufferSize * 7) / 8; result = cnxt_cbuf_open(&handle_item->buffer1, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); bufarg.type = 0; #ifdef HAVE_COOLAPI2 bufarg.poolid = 0 #endif result = cnxt_cbuf_open(&handle_item->buffer2, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); channel_open_arg_t chanarg; memset(&chanarg, 0, sizeof(channel_open_arg_t)); chanarg.type = 4; result = cnxt_dmx_channel_open(dmx_handles[COOLDEMUX_DMX_DEV(fd)].handle, &handle_item->channel, &chanarg, dmx_callback, dmx); coolapi_check_error("cnxt_dmx_channel_open", result); result = cnxt_dmx_set_channel_buffer(handle_item->channel, 0, handle_item->buffer1); coolapi_check_error("cnxt_dmx_set_channel_buffer", result); result = cnxt_dmx_channel_attach(handle_item->channel, 0xB, 0, handle_item->buffer2); coolapi_check_error("cnxt_dmx_channel_attach", result); result = cnxt_cbuf_attach(handle_item->buffer2, 2, handle_item->channel); coolapi_check_error("cnxt_cbuf_attach", result); result = cnxt_dmx_set_channel_pid(handle_item->channel, pid); coolapi_check_error("cnxt_dmx_set_channel_pid", result); result = cnxt_cbuf_flush(handle_item->buffer1, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_flush(handle_item->buffer2, 0); coolapi_check_error("cnxt_cbuf_flush", result); handle_item->pid = pid; handle_item->dmx_handle = &dmx_handles[COOLDEMUX_DMX_DEV(fd)]; dmx_handles[COOLDEMUX_DMX_DEV(fd)].allocated_channels++; ll_append(ll_cool_chanhandle, handle_item); cs_log_dbg(D_DVBAPI, "opened new channel %x", (int32_t) handle_item->channel);; } else { channel_found = 1; } cs_log_dbg(D_DVBAPI, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x", fd, COOLDEMUX_DMX_DEV(fd), (int32_t) handle_item->channel, num, pid, flt[0], mask[0]); void *filter_handle = NULL; filter_set_t filterset; int32_t has_filter = 0; S_COOL_FILTER *filter_item = find_filter_by_chanhandle(handle_item, num); if (filter_item && type == dmx->type && pid == dmx->pid && (memcmp(flt, filter_item->filter16, 16) || memcmp(mask, filter_item->mask16, 16))) { cs_log_dbg(D_DVBAPI, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x, filter exists.. modifying", fd, COOLDEMUX_DMX_DEV(fd), (int32_t) handle_item->channel, num, pid, flt[0], mask[0]); filter_handle = filter_item->filter; has_filter = 1; memcpy(filter_item->filter16, flt, 16); memcpy(filter_item->mask16, mask, 16); } else { dmx->pid = pid; dmx->type = type; dmx->filter_num = num; result = cnxt_dmx_open_filter(dmx_handles[COOLDEMUX_DMX_DEV(fd)].handle, &filter_handle); coolapi_check_error("cnxt_dmx_open_filter", result); if(!cs_malloc(&filter_item, sizeof(S_COOL_FILTER))) { SAFE_MUTEX_UNLOCK(&dmx->mutex); return -1; } // fill filter item filter_item->fd = fd; filter_item->filter = filter_handle; filter_item->filter_num = num; filter_item->chanhandle = handle_item; memcpy(filter_item->filter16, flt, 16); memcpy(filter_item->mask16, mask, 16); //add filter item ll_append(ll_cool_filter, filter_item); // increase allocated filters handle_item->allocated_filters++; } if (has_filter) { result = cnxt_dmx_channel_suspend(handle_item->channel, 1); coolapi_check_error("cnxt_dmx_channel_suspend", result); result = cnxt_dmx_channel_detach_filter(handle_item->channel, filter_handle); coolapi_check_error("cnxt_dmx_channel_detach_filter", result); } memset(&filterset, 0, sizeof(filterset)); filterset.length = 12; memcpy(filterset.filter, flt, 16); memcpy(filterset.mask, mask, 16); result = cnxt_dmx_set_filter(filter_handle, &filterset, (void *)num); coolapi_check_error("cnxt_dmx_set_filter", result); result = cnxt_dmx_channel_attach_filter(handle_item->channel, filter_handle); coolapi_check_error("cnxt_dmx_channel_attach_filter", result); if (has_filter) { result = cnxt_dmx_channel_suspend(handle_item->channel, 0); coolapi_check_error("cnxt_dmx_channel_suspend", result); } if(!channel_found) { // Start channel result = cnxt_dmx_channel_ctrl(handle_item->channel, 2, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); } SAFE_MUTEX_UNLOCK(&dmx->mutex); return 0; }
int32_t coolapi_remove_filter(int32_t fd, int32_t num) { void * channel = NULL; void * filter = NULL; dmx_t *dmx = find_demux(fd, 0); if(!dmx) { cs_log_dbg(D_DVBAPI, "dmx is NULL!"); return -1; } if(dmx->pid <= 0) { return -1; } int32_t result; SAFE_MUTEX_LOCK(&dmx->mutex); // Find matching channel, if it exists. S_COOL_CHANHANDLE *handle_item = find_chanhandle(COOLDEMUX_DMX_DEV(fd), dmx->pid); if (!handle_item) { SAFE_MUTEX_UNLOCK(&dmx->mutex); cs_log_dbg(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04xcfailed, channel does not exist.", fd, num, dmx->pid); return -1; } channel = handle_item->channel; cs_log_dbg(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04x on channel=%p", fd, num, dmx->pid, channel); S_COOL_FILTER *filter_item = find_filter_by_chanhandle(handle_item, num); if(filter_item) { result = cnxt_dmx_channel_suspend(channel, 1); coolapi_check_error("cnxt_dmx_channel_suspend", result); result = cnxt_dmx_channel_detach_filter(channel, filter_item->filter); coolapi_check_error("cnxt_dmx_channel_detach_filter", result); #if 0 result = cnxt_dmx_close_filter(filter_item->filter); coolapi_check_error("cnxt_dmx_close_filter", result); #endif filter = filter_item->filter; remove_filter(filter_item); handle_item->allocated_filters--; } else { SAFE_MUTEX_UNLOCK(&dmx->mutex); cs_log_dbg(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04x on channel=%x failed, channel does not exist.", fd, num, dmx->pid, (int32_t) handle_item->channel); return -1; } if (!handle_item->allocated_filters) { result = cnxt_dmx_channel_ctrl(channel, 0, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); cs_log_dbg(D_DVBAPI, "closing channel %x", (int32_t) channel); result = cnxt_dmx_set_channel_pid(channel, 0x1FFF); coolapi_check_error("cnxt_dmx_set_channel_pid", result); result = cnxt_cbuf_flush(handle_item->buffer1, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_flush(handle_item->buffer2, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_detach(handle_item->buffer2, 2, channel); coolapi_check_error("cnxt_cbuf_detach", result); result = cnxt_dmx_channel_detach(channel, 0xB, 0, handle_item->buffer1); coolapi_check_error("cnxt_dmx_channel_detach", result); #if 0 result = cnxt_dmx_channel_close(channel); coolapi_check_error("cnxt_dmx_channel_close", result); #endif result = cnxt_cbuf_close(handle_item->buffer2); coolapi_check_error("cnxt_cbuf_close", result); result = cnxt_cbuf_close(handle_item->buffer1); coolapi_check_error("cnxt_cbuf_close", result); handle_item->channel = NULL; handle_item->buffer1 = NULL; handle_item->buffer2 = NULL; remove_chanhandle(handle_item); dmx_handles[COOLDEMUX_DMX_DEV(fd)].allocated_channels--; dmx->pid = -1; } else { result = cnxt_dmx_channel_suspend(channel, 0); coolapi_check_error("cnxt_dmx_channel_suspend", result); channel = NULL; } SAFE_MUTEX_UNLOCK(&dmx->mutex); if (filter) { result = cnxt_dmx_close_filter(filter); coolapi_check_error("cnxt_dmx_close_filter", result); } if (channel) { result = cnxt_dmx_channel_close(channel); coolapi_check_error("cnxt_dmx_channel_close", result); } return 0; }
static int32_t Cool_WriteSettings(struct s_reader *reader, struct s_cardreader_settings *s) { struct cool_data *crdr_data = reader->crdr_data; //first set freq back to reader->mhz if necessary uint32_t clk; int32_t ret = cnxt_smc_get_clock_freq(crdr_data->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if(clk / 10000 != (uint32_t)reader->mhz) { rdr_log_dbg(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i", clk, reader->mhz * 10000); call(Cool_SetClockrate(reader, reader->mhz)); } uint32_t BLKTime = 0, CHTime = 0; uint8_t BKGuardTime = 0; switch(reader->protocol_type) { case ATR_PROTOCOL_TYPE_T1: if(reader->BWT > 11) { BLKTime = (reader->BWT - 11); } if(reader->CWT > 11) { CHTime = (reader->CWT - 11); } if(s->BGT > 11) { BKGuardTime = (s->BGT - 11); } else { BKGuardTime = 11; } //For T1, the BGT minimum time shall be 22 work etus. BGT is effectively offset by 11 etus internally. if(!crdr_data->pps) { ret = cnxt_smc_set_F_D_factors(crdr_data->handle, s->F, s->D); coolapi_check_error("cnxt_smc_set_F_D_factors", ret); } break; case ATR_PROTOCOL_TYPE_T0: case ATR_PROTOCOL_TYPE_T14: default: BLKTime = 0; if(s->WWT > 12) { CHTime = (s->WWT - 12); } if(s->BGT > 12) { BKGuardTime = (s->BGT - 12); } if(BKGuardTime < 4) { BKGuardTime = 4; } //For T0, the BGT minimum time shall be 16 work etus. BGT is effectively offset by 12 etus internally. if(!crdr_data->pps) { if(reader->protocol_type == ATR_PROTOCOL_TYPE_T14) { ret = cnxt_smc_set_F_D_factors(crdr_data->handle, 620, 1); } else { ret = cnxt_smc_set_F_D_factors(crdr_data->handle, s->F, s->D); } coolapi_check_error("cnxt_smc_set_F_D_factors", ret); } break; } ret = cnxt_smc_set_convention(crdr_data->handle, reader->convention); coolapi_check_error("cnxt_smc_set_convention", ret); CNXT_SMC_TIMEOUT timeout; ret = cnxt_smc_get_config_timeout(crdr_data->handle, &timeout); coolapi_check_error("cnxt_smc_get_config_timeout", ret); timeout.BLKTime = BLKTime; timeout.CHTime = CHTime; timeout.CHGuardTime = s->EGT; timeout.BKGuardTime = BKGuardTime; ret = cnxt_smc_set_config_timeout(crdr_data->handle, timeout); coolapi_check_error("cnxt_smc_set_config_timeout", ret); Cool_Print_Comm_Parameters(reader); return OK; }