bool cardreader_init(struct s_reader *reader) { struct s_client *client = reader->client; client->typ = 'r'; set_localhost_ip(&client->ip); while (cardreader_device_init(reader) == 2) { int8_t i = 0; do { cs_sleepms(2000); if (!ll_contains(configured_readers, reader) || !is_valid_client(client) || reader->enable != 1) return false; i++; } while (i < 30); } if (reader->mhz > 2000) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f Mhz, wanted cardmhz=%.2f Mhz", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], (float)reader->mhz /100, (float)reader->cardmhz / 100); } else { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->mhz, reader->cardmhz); } return true; }
static void process_clients(void) { int32_t i, k, j, rc, pfdcount = 0; struct s_client *cl; struct s_reader *rdr; struct pollfd *pfd; struct s_client **cl_list; uint32_t cl_size = 0; char buf[10]; if (pipe(thread_pipe) == -1) { printf("cannot create pipe, errno=%d\n", errno); exit(1); } cl_size = chk_resize_cllist(&pfd, &cl_list, 0, 100); pfd[pfdcount].fd = thread_pipe[0]; pfd[pfdcount].events = POLLIN | POLLPRI | POLLHUP; cl_list[pfdcount] = NULL; while (!exit_oscam) { pfdcount = 1; //connected tcp clients for (cl=first_client->next; cl; cl=cl->next) { if (cl->init_done && !cl->kill && cl->pfd && cl->typ=='c' && !cl->is_udp) { if (cl->pfd && !cl->thread_active) { cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount); cl_list[pfdcount] = cl; pfd[pfdcount].fd = cl->pfd; pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP; } } //reader: //TCP: // - TCP socket must be connected // - no active init thread //UDP: // - connection status ignored // - no active init thread rdr = cl->reader; if (rdr && cl->typ=='p' && cl->init_done) { if (cl->pfd && !cl->thread_active && ((rdr->tcp_connected && rdr->ph.type==MOD_CONN_TCP)||(rdr->ph.type==MOD_CONN_UDP))) { cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount); cl_list[pfdcount] = cl; pfd[pfdcount].fd = cl->pfd; pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP; } } } //server (new tcp connections or udp messages) for (k = 0; k < CS_MAX_MOD; k++) { struct s_module *module = &modules[k]; if ((module->type & MOD_CONN_NET)) { for (j = 0; j < module->ptab.nports; j++) { if (module->ptab.ports[j].fd) { cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount); cl_list[pfdcount] = NULL; pfd[pfdcount].fd = module->ptab.ports[j].fd; pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP; } } } } if (pfdcount >= 1024) cs_log("WARNING: too many users!"); rc = poll(pfd, pfdcount, 5000); if (rc<1) continue; for (i=0; i<pfdcount; i++) { //clients cl = cl_list[i]; if (cl && !is_valid_client(cl)) continue; if (pfd[i].fd == thread_pipe[0] && (pfd[i].revents & (POLLIN | POLLPRI))) { // a thread ended and cl->pfd should be added to pollfd list again (thread_active==0) if(read(thread_pipe[0], buf, sizeof(buf)) == -1){ cs_debug_mask(D_TRACE, "Reading from pipe failed (errno=%d %s)", errno, strerror(errno)); } continue; } //clients // message on an open tcp connection if (cl && cl->init_done && cl->pfd && (cl->typ == 'c' || cl->typ == 'm')) { if (pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL))) { //client disconnects kill_thread(cl); continue; } if (pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLIN | POLLPRI))) { add_job(cl, ACTION_CLIENT_TCP, NULL, 0); } } //reader // either an ecm answer, a keepalive or connection closed from a proxy // physical reader ('r') should never send data without request rdr = NULL; struct s_client *cl2 = NULL; if (cl && cl->typ == 'p'){ rdr = cl->reader; if(rdr) cl2 = rdr->client; } if (rdr && cl2 && cl2->init_done) { if (cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL))) { //connection to remote proxy was closed //oscam should check for rdr->tcp_connected and reconnect on next ecm request sent to the proxy network_tcp_connection_close(rdr, "closed"); rdr_debug_mask(rdr, D_READER, "connection closed"); } if (cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLIN | POLLPRI))) { add_job(cl2, ACTION_READER_REMOTE, NULL, 0); } } //server sockets // new connection on a tcp listen socket or new message on udp listen socket if (!cl && (pfd[i].revents & (POLLIN | POLLPRI))) { for (k = 0; k < CS_MAX_MOD; k++) { struct s_module *module = &modules[k]; if ((module->type & MOD_CONN_NET)) { for (j = 0; j < module->ptab.nports; j++) { if (module->ptab.ports[j].fd && module->ptab.ports[j].fd == pfd[i].fd) { accept_connection(module, k, j); } } } } } } first_client->last=time((time_t *)0); } free(pfd); free(cl_list); return; }
static void *chkcache_process(void) { set_thread_name(__func__); time_t timeout; struct ecm_request_t *er, *ecm; #ifdef CS_CACHEEX uint8_t add_hitcache_er; struct s_reader *cl_rdr; struct s_reader *rdr; struct s_ecm_answer *ea; struct s_client *cex_src=NULL; #endif struct s_write_from_cache *wfc=NULL; while(1) { cs_readlock(&ecmcache_lock); for(er = ecmcwcache; er; er = er->next) { timeout = time(NULL)-((cfg.ctimeout+500)/1000+1); if(er->tps.time < timeout) { break; } if(er->rc<E_UNHANDLED || er->readers_timeout_check) //already answered { continue; } //******** CHECK IF FOUND ECM IN CACHE ecm = check_cache(er, er->client); if(ecm) //found in cache { #ifdef CS_CACHEEX //check for add_hitcache if(ecm->cacheex_src) //cw from cacheex { if((er->cacheex_wait_time && !er->cacheex_wait_time_expired) || !er->cacheex_wait_time) //only when no wait_time expires (or not wait_time) { //add_hitcache already called, but we check if we have to call it for these (er) caid|prid|srvid if(ecm->prid!=er->prid || ecm->srvid!=er->srvid) { cex_src = ecm->cacheex_src && is_valid_client(ecm->cacheex_src) && !ecm->cacheex_src->kill ? ecm->cacheex_src : NULL; //here we should be sure cex client has not been freed! if(cex_src) { //add_hitcache only if client is really active add_hitcache_er=1; cl_rdr = cex_src->reader; if(cl_rdr && cl_rdr->cacheex.mode == 2) { for(ea = er->matching_rdr; ea; ea = ea->next) { rdr = ea->reader; if(cl_rdr == rdr && ((ea->status & REQUEST_ANSWERED) == REQUEST_ANSWERED)) { cs_debug_mask(D_CACHEEX|D_CSP|D_LB,"{client %s, caid %04X, prid %06X, srvid %04X} [CACHEEX] skip ADD self request!", (check_client(er->client)?er->client->account->usr:"******"),er->caid, er->prid, er->srvid); add_hitcache_er=0; //don't add hit cache, reader requested self } } } if(add_hitcache_er) { add_hitcache(cex_src, er); //USE cacheex client (to get correct group) and ecm from requesting client (to get correct caid|prid|srvid)!!! } } } } else { //add_hitcache already called, but we have to remove it because cacheex not coming before wait_time if(ecm->prid==er->prid && ecm->srvid==er->srvid) { del_hitcache(ecm); } } } //END check for add_hitcache #endif if(check_client(er->client)) { wfc=NULL; if(!cs_malloc(&wfc, sizeof(struct s_write_from_cache))) { NULLFREE(ecm); continue; } wfc->er_new=er; wfc->er_cache=ecm; if(!add_job(er->client, ACTION_ECM_ANSWER_CACHE, wfc, sizeof(struct s_write_from_cache))) //write_ecm_answer_fromcache { NULLFREE(ecm); continue; } } else { NULLFREE(ecm); } } } cs_readunlock(&ecmcache_lock); cs_sleepms(10); } return NULL; }
void *work_thread(void *ptr) { struct job_data *data = (struct job_data *)ptr; struct s_client *cl = data->cl; struct s_reader *reader = cl->reader; struct timeb start, end; // start time poll, end time poll struct job_data tmp_data; struct pollfd pfd[1]; pthread_setspecific(getclient, cl); cl->thread = pthread_self(); cl->thread_active = 1; set_work_thread_name(data); struct s_module *module = get_module(cl); uint16_t bufsize = module->bufsize; //CCCam needs more than 1024bytes! if(!bufsize) { bufsize = 1024; } uint8_t *mbuf; if(!cs_malloc(&mbuf, bufsize)) { return NULL; } cl->work_mbuf = mbuf; // Track locally allocated data, because some callback may call cs_exit/cs_disconect_client/pthread_exit and then mbuf would be leaked int32_t n = 0, rc = 0, i, idx, s; uint8_t dcw[16]; int8_t restart_reader = 0; while(cl->thread_active) { cs_ftime(&start); // register start time while(cl->thread_active) { if(!cl || cl->kill || !is_valid_client(cl)) { pthread_mutex_lock(&cl->thread_lock); cl->thread_active = 0; pthread_mutex_unlock(&cl->thread_lock); cs_debug_mask(D_TRACE, "ending thread (kill)"); __free_job_data(cl, data); cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf) free_client(cl); if(restart_reader) { restart_cardreader(reader, 0); } NULLFREE(mbuf); pthread_exit(NULL); return NULL; } if(data && data->action != ACTION_READER_CHECK_HEALTH) { cs_debug_mask(D_TRACE, "data from add_job action=%d client %c %s", data->action, cl->typ, username(cl)); } if(!data) { if(!cl->kill && cl->typ != 'r') { client_check_status(cl); } // do not call for physical readers as this might cause an endless job loop pthread_mutex_lock(&cl->thread_lock); if(cl->joblist && ll_count(cl->joblist) > 0) { LL_ITER itr = ll_iter_create(cl->joblist); data = ll_iter_next_remove(&itr); if(data) { set_work_thread_name(data); } //cs_debug_mask(D_TRACE, "start next job from list action=%d", data->action); } pthread_mutex_unlock(&cl->thread_lock); } if(!data) { /* for serial client cl->pfd is file descriptor for serial port not socket for example: pfd=open("/dev/ttyUSB0"); */ if(!cl->pfd || module->listenertype == LIS_SERIAL) { break; } pfd[0].fd = cl->pfd; pfd[0].events = POLLIN | POLLPRI; pthread_mutex_lock(&cl->thread_lock); cl->thread_active = 2; pthread_mutex_unlock(&cl->thread_lock); rc = poll(pfd, 1, 3000); pthread_mutex_lock(&cl->thread_lock); cl->thread_active = 1; pthread_mutex_unlock(&cl->thread_lock); if(rc > 0) { cs_ftime(&end); // register end time cs_debug_mask(D_TRACE, "[OSCAM-WORK] new event %d occurred on fd %d after %"PRId64" ms inactivity", pfd[0].revents, pfd[0].fd, comp_timeb(&end, &start)); data = &tmp_data; data->ptr = NULL; cs_ftime(&start); // register start time for new poll next run if(reader) { data->action = ACTION_READER_REMOTE; } else { if(cl->is_udp) { data->action = ACTION_CLIENT_UDP; data->ptr = mbuf; data->len = bufsize; } else { data->action = ACTION_CLIENT_TCP; } if(pfd[0].revents & (POLLHUP | POLLNVAL | POLLERR)) { cl->kill = 1; } } } } if(!data) { continue; } if(!reader && data->action < ACTION_CLIENT_FIRST) { __free_job_data(cl, data); break; } if(!data->action) { break; } struct timeb actualtime; cs_ftime(&actualtime); int32_t gone = comp_timeb(&actualtime, &data->time); if(data != &tmp_data && gone > (int) cfg.ctimeout+1000) { cs_debug_mask(D_TRACE, "dropping client data for %s time %dms", username(cl), gone); __free_job_data(cl, data); continue; } if(data != &tmp_data) { cl->work_job_data = data; } // Track the current job_data switch(data->action) { case ACTION_READER_IDLE: reader_do_idle(reader); break; case ACTION_READER_REMOTE: s = check_fd_for_data(cl->pfd); if(s == 0) // no data, another thread already read from fd? { break; } if(s < 0) { if(reader->ph.type == MOD_CONN_TCP) { network_tcp_connection_close(reader, "disconnect"); } break; } rc = reader->ph.recv(cl, mbuf, bufsize); if(rc < 0) { if(reader->ph.type == MOD_CONN_TCP) { network_tcp_connection_close(reader, "disconnect on receive"); } break; } cl->last = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER **************** idx = reader->ph.c_recv_chk(cl, dcw, &rc, mbuf, rc); if(idx < 0) { break; } // no dcw received if(!idx) { idx = cl->last_idx; } reader->last_g = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER **************** // for reconnect timeout for(i = 0, n = 0; i < cfg.max_pending && n == 0; i++) { if(cl->ecmtask[i].idx == idx) { cl->pending--; casc_check_dcw(reader, i, rc, dcw); n++; } } break; case ACTION_READER_RESET: cardreader_do_reset(reader); break; case ACTION_READER_ECM_REQUEST: reader_get_ecm(reader, data->ptr); break; case ACTION_READER_EMM: reader_do_emm(reader, data->ptr); break; case ACTION_READER_CARDINFO: reader_do_card_info(reader); break; case ACTION_READER_INIT: if(!cl->init_done) { reader_init(reader); } break; case ACTION_READER_RESTART: cl->kill = 1; restart_reader = 1; break; case ACTION_READER_RESET_FAST: reader->card_status = CARD_NEED_INIT; cardreader_do_reset(reader); break; case ACTION_READER_CHECK_HEALTH: cardreader_do_checkhealth(reader); break; case ACTION_READER_CAPMT_NOTIFY: if(reader->ph.c_capmt) { reader->ph.c_capmt(cl, data->ptr); } break; case ACTION_CLIENT_UDP: n = module->recv(cl, data->ptr, data->len); if(n < 0) { break; } module->s_handler(cl, data->ptr, n); break; case ACTION_CLIENT_TCP: s = check_fd_for_data(cl->pfd); if(s == 0) // no data, another thread already read from fd? { break; } if(s < 0) // system error or fd wants to be closed { cl->kill = 1; // kill client on next run continue; } n = module->recv(cl, mbuf, bufsize); if(n < 0) { cl->kill = 1; // kill client on next run continue; } module->s_handler(cl, mbuf, n); break; case ACTION_CACHEEX_TIMEOUT: #ifdef CS_CACHEEX cacheex_timeout(data->ptr); #endif break; case ACTION_FALLBACK_TIMEOUT: fallback_timeout(data->ptr); break; case ACTION_CLIENT_TIMEOUT: ecm_timeout(data->ptr); break; case ACTION_ECM_ANSWER_READER: chk_dcw(data->ptr); break; case ACTION_ECM_ANSWER_CACHE: write_ecm_answer_fromcache(data->ptr); break; case ACTION_CLIENT_INIT: if(module->s_init) { module->s_init(cl); } cl->is_udp = module->type == MOD_CONN_UDP; cl->init_done = 1; break; case ACTION_CLIENT_IDLE: if(module->s_idle) { module->s_idle(cl); } else { cs_log("user %s reached %d sec idle limit.", username(cl), cfg.cmaxidle); cl->kill = 1; } break; case ACTION_CACHE_PUSH_OUT: { #ifdef CS_CACHEEX ECM_REQUEST *er = data->ptr; int32_t res = 0, stats = -1; // cc-nodeid-list-check if(reader) { if(reader->ph.c_cache_push_chk && !reader->ph.c_cache_push_chk(cl, er)) { break; } res = reader->ph.c_cache_push(cl, er); stats = cacheex_add_stats(cl, er->caid, er->srvid, er->prid, 0); } else { if(module->c_cache_push_chk && !module->c_cache_push_chk(cl, er)) { break; } res = module->c_cache_push(cl, er); } debug_ecm(D_CACHEEX, "pushed ECM %s to %s res %d stats %d", buf, username(cl), res, stats); cl->cwcacheexpush++; if(cl->account) { cl->account->cwcacheexpush++; } first_client->cwcacheexpush++; #endif break; } case ACTION_CLIENT_KILL: cl->kill = 1; break; case ACTION_CLIENT_SEND_MSG: { #ifdef MODULE_CCCAM struct s_clientmsg *clientmsg = (struct s_clientmsg *)data->ptr; cc_cmd_send(cl, clientmsg->msg, clientmsg->len, clientmsg->cmd); #endif break; } } // switch __free_job_data(cl, data); } if(thread_pipe[1] && (mbuf[0] != 0x00)) { cs_ddump_mask(D_TRACE, mbuf, 1, "[OSCAM-WORK] Write to pipe:"); if(write(thread_pipe[1], mbuf, 1) == -1) // wakeup client check { cs_debug_mask(D_TRACE, "[OSCAM-WORK] Writing to pipe failed (errno=%d %s)", errno, strerror(errno)); } } // Check for some race condition where while we ended, another thread added a job pthread_mutex_lock(&cl->thread_lock); if(cl->joblist && ll_count(cl->joblist) > 0) { pthread_mutex_unlock(&cl->thread_lock); continue; } else { cl->thread_active = 0; pthread_mutex_unlock(&cl->thread_lock); break; } } cl->thread_active = 0; cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf) NULLFREE(mbuf); pthread_exit(NULL); return NULL; }
bool cardreader_init(struct s_reader *reader) { struct s_client *client = reader->client; client->typ = 'r'; int8_t i = 0; set_localhost_ip(&client->ip); while((cardreader_device_init(reader) == 2) && i < 10) { cs_sleepms(2000); if(!ll_contains(configured_readers, reader) || !is_valid_client(client) || reader->enable != 1) { return false; } i++; } if (i >= 10) { reader->card_status = READER_DEVICE_ERROR; cardreader_close(reader); reader->enable = 0; return false; } else { if((reader->cardmhz > 2000) && (reader->typ != R_SMART)) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f MHz, wanted mhz=%.2f MHz)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], (float)reader->cardmhz / 100, (float)reader->mhz / 100); rdr_log(reader,"Reader sci internal, detected box type: %s", stb_boxtype ? stb_boxtype : "generic"); } else { if ((reader->typ == R_SMART) || (!strcasecmp(reader->crdr.desc, "smargo")) ){ rdr_debug_mask(reader, D_IFD, "clocking for smartreader with smartreader or smargo protocol"); if (reader->cardmhz >= 2000) reader->cardmhz = 369; else if (reader->cardmhz >= 1600) reader->cardmhz = 1600; else if (reader->cardmhz >= 1200) reader->cardmhz = 1200; else if (reader->cardmhz >= 961) reader->cardmhz = 961; else if (reader->cardmhz >= 800) reader->cardmhz = 800; else if (reader->cardmhz >= 686) reader->cardmhz = 686; else if (reader->cardmhz >= 600) reader->cardmhz = 600; else if (reader->cardmhz >= 534) reader->cardmhz = 534; else if (reader->cardmhz >= 480) reader->cardmhz = 480; else if (reader->cardmhz >= 436) reader->cardmhz = 436; else if (reader->cardmhz >= 400) reader->cardmhz = 400; else if (reader->cardmhz >= 369) reader->cardmhz = 369; else if (reader->cardmhz == 357) reader->cardmhz = 369; else // 357 not a default smartreader setting if (reader->cardmhz >= 343) reader->cardmhz = 343; else reader->cardmhz = 320; if (reader->mhz >= 1600) reader->mhz = 1600; else if (reader->mhz >= 1200) reader->mhz = 1200; else if (reader->mhz >= 961) reader->mhz = 961; else if (reader->mhz >= 900) reader->mhz = 900; else if (reader->mhz >= 800) reader->mhz = 800; else if (reader->mhz >= 686) reader->mhz = 686; else if (reader->mhz >= 600) reader->mhz = 600; else if (reader->mhz >= 534) reader->mhz = 534; else if (reader->mhz >= 480) reader->mhz = 480; else if (reader->mhz >= 436) reader->mhz = 436; else if (reader->mhz >= 400) reader->mhz = 369; else if (reader->mhz >= 369) reader->mhz = 369; else if (reader->mhz == 357) reader->mhz = 369; else // 357 not a default smartreader setting if (reader->mhz >= 343) reader->mhz = 343; else reader->mhz = 320; } if (((reader->typ == R_SMART) && (reader->autospeed == 1)) || ((!strcasecmp(reader->crdr.desc, "smargo")) && (reader->autospeed == 1))) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz= AUTO, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->cardmhz); } else { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->mhz, reader->cardmhz); } } return true; } }
bool cardreader_init(struct s_reader *reader) { struct s_client *client = reader->client; client->typ = 'r'; int8_t i = 0; set_localhost_ip(&client->ip); while((cardreader_device_init(reader) == 2) && i < 10) { cs_sleepms(2000); if(!ll_contains(configured_readers, reader) || !is_valid_client(client) || reader->enable != 1) { return false; } i++; } if (i >= 10) { reader->card_status = READER_DEVICE_ERROR; cardreader_close(reader); reader->enable = 0; return false; } else { if(reader->typ == R_INTERNAL) { if(boxtype_is("dm8000") || boxtype_is("dm800") || boxtype_is("dm800se")) {reader->cardmhz = 2700;} if(boxtype_is("dm500") || boxtype_is("dm600pvr")) {reader->cardmhz = 3150;} if(boxtype_is("dm7025")) {reader->cardmhz = 8300;} if((!strncmp(boxtype_get(), "vu", 2 ))||(boxtype_is("ini-8000am"))) {reader->cardmhz = 2700; reader->mhz = 450;} // only one speed for vu+ and Atemio Nemesis due to usage of TDA8024 } if((reader->cardmhz > 2000) && (reader->typ != R_SMART)) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f MHz, wanted mhz=%.2f MHz)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], (float)reader->cardmhz / 100, (float)reader->mhz / 100); rdr_log(reader,"Reader sci internal, detected box type: %s", boxtype_get()); } else { if (reader->typ == R_SMART || is_smargo_reader(reader)) { rdr_log_dbg(reader, D_IFD, "clocking for smartreader with smartreader or smargo protocol"); if (reader->cardmhz >= 2000) reader->cardmhz = 369; else if (reader->cardmhz >= 1600) reader->cardmhz = 1600; else if (reader->cardmhz >= 1200) reader->cardmhz = 1200; else if (reader->cardmhz >= 961) reader->cardmhz = 961; else if (reader->cardmhz >= 800) reader->cardmhz = 800; else if (reader->cardmhz >= 686) reader->cardmhz = 686; else if (reader->cardmhz >= 600) reader->cardmhz = 600; else if (reader->cardmhz >= 534) reader->cardmhz = 534; else if (reader->cardmhz >= 480) reader->cardmhz = 480; else if (reader->cardmhz >= 436) reader->cardmhz = 436; else if (reader->cardmhz >= 400) reader->cardmhz = 400; else if (reader->cardmhz >= 369) reader->cardmhz = 369; else if (reader->cardmhz == 357) reader->cardmhz = 369; else // 357 not a default smartreader setting if (reader->cardmhz >= 343) reader->cardmhz = 343; else reader->cardmhz = 320; if (reader->mhz >= 1600) reader->mhz = 1600; else if (reader->mhz >= 1200) reader->mhz = 1200; else if (reader->mhz >= 961) reader->mhz = 961; else if (reader->mhz >= 900) reader->mhz = 900; else if (reader->mhz >= 800) reader->mhz = 800; else if (reader->mhz >= 686) reader->mhz = 686; else if (reader->mhz >= 600) reader->mhz = 600; else if (reader->mhz >= 534) reader->mhz = 534; else if (reader->mhz >= 480) reader->mhz = 480; else if (reader->mhz >= 436) reader->mhz = 436; else if (reader->mhz >= 400) reader->mhz = 369; else if (reader->mhz >= 369) reader->mhz = 369; else if (reader->mhz == 357) reader->mhz = 369; else // 357 not a default smartreader setting if (reader->mhz >= 343) reader->mhz = 343; else reader->mhz = 320; } if ((reader->typ == R_SMART || is_smargo_reader(reader)) && reader->autospeed == 1) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz= AUTO, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->cardmhz); } else { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->mhz, reader->cardmhz); if (reader->typ == R_INTERNAL && !(reader->cardmhz > 2000)) rdr_log(reader,"Reader sci internal, detected box type: %s", boxtype_get()); } } return true; } }