/************************************************************************* * Copyright 2009/2010/2011 Ralph Spitzner (rasp@spitzner.org) * * This file is part of v2Yahdr. * * v2Yahdr is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Yahdr is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with v2Yahdr. If not, see . **************************************************************************/ #warning clean up sqlite selects atoi stuff here #include "ydefs.h" #define MAXT 60 //bool setup_frontend (int fe_fd, struct dvb_frontend_parameters *frontend); //bool tune(); static int frontend_fd,demux_fd; static struct dvb_frontend_parameters fe_parm; static uint8_t sections[255]; #define CLBOT 113000000 #define CLTOP 185000000 #define CHBOT 306000000 #define CHTOP 862000000 /*** set transponder/pids ***/ static bool setup_frontend (int fe_fd, struct dvb_frontend_parameters *frontend) { struct dvb_frontend_info fe_info; if (ioctl(fe_fd, FE_GET_INFO, &fe_info) < 0) { perror("ioctl FE_GET_INFO failed"); return false; } /// just for info, will go away /* if (fe_info.type != FE_QAM) { printf("frontend device is not a (DVB-C) device\n"); }*/ //printf ("tuning to %i Hz\n", frontend->frequency); if (ioctl(fe_fd, FE_SET_FRONTEND, frontend) < 0) { perror("ioctl FE_SET_FRONTEND failed"); return false; } /* dump info */ /* printf("device caps:\n"); printf("type:\t %d\n",fe_info.type); printf("freqmin:\t%d\n",fe_info.frequency_min); printf("freqmax:\t%d\n",fe_info.frequency_max); printf("freqstep:\t%d\n",fe_info.frequency_stepsize); printf("caps:\t%x\n",fe_info.caps); */ return true; } bool check_frontend (int fe_fd,uint16_t maxtry) { fe_status_t status; uint16_t snr, signal; uint32_t ber, uncorrected_blocks; uint16_t tries; tries = 0; do { ioctl(fe_fd, FE_READ_STATUS, &status); ioctl(fe_fd, FE_READ_SIGNAL_STRENGTH, &signal); ioctl(fe_fd, FE_READ_SNR, &snr); ioctl(fe_fd, FE_READ_BER, &ber); ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks); printf ("."); INFO("sig %04x snr %04x ber %04x unc %04x stat %x\n",signal,snr,ber,uncorrected_blocks,status); fflush(stdout); if (status & FE_HAS_LOCK) { return true; } else tries ++; if (tries == maxtry) { return false; } usleep(1000000); } while (1); return false; } /* fill in some defaults */ static void fill_parms(char c,struct dvb_frontend_parameters *fe_parm) { memset(fe_parm, 0, sizeof(struct dvb_frontend_parameters)); switch(c) { case 'T': /***** DVB-T ********/ fe_parm->inversion = INVERSION_AUTO; fe_parm->u.ofdm.code_rate_HP =FEC_3_4; fe_parm->u.ofdm.code_rate_LP = FEC_AUTO; fe_parm->u.ofdm.constellation = QAM_AUTO; //16; // ?? fe_parm->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;//8K; fe_parm->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;//1_8; fe_parm->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; break; case 'C': fe_parm->inversion = INVERSION_AUTO; fe_parm->u.qam.fec_inner = FEC_AUTO; fe_parm->u.qam.symbol_rate = 6900000; fe_parm->u.qam.modulation = QAM_64; break; } } static uint8_t checksec(uint8_t have,uint8_t want) { uint8_t i; if(sections[have] == 1) return S_HAVE; sections[have] = 1; for(i = 0; i != want; i++) { if(sections[i] == 0) return S_WANT; } return S_DONE; } static void do_services(SERVICE *services) { uint16_t sarr[255]; // ?? uint16_t count,i,seen; char charbuf[255]; bzero(&sarr,sizeof(sarr)); i = count = seen = 0; sprintf(charbuf,"select s_id from serv where tsid='%d'",services->tsid); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return ; } else { cols = sqlite3_column_count(stmt); // execute the statement do { rc = sqlite3_step(stmt); switch( rc ) { case SQLITE_DONE: break; case SQLITE_ROW: // print results for this row txt = (const char*)sqlite3_column_text(stmt,0); sarr[count++] = atoi(txt); break; default: fprintf(stderr, "Error: %d : %s\n", rc, sqlite3_errmsg(db)); break; } } while( rc==SQLITE_ROW ); // finalize the statement to release resources sqlite3_finalize(stmt); } while(services) { seen = 0; for(i = 0 ; i != count; i++) { if(services->s_id == sarr[i]) { seen = 1; break; // from for } } if((seen == 0) && (services->running != 1) && ((services->type == 1) || (services->type == 25) || (services->type == 2))) // just care about video/radio { printf("Found Service: %s / %s\n",services->provider,services->name); sprintf(charbuf,"insert into serv values ('%d','%d','%d',\"%s\",\"%s\",\"%d\")", services->type, services->tsid, services->s_id, services->provider, services->name, services->ca); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return ; } rc = sqlite3_step(stmt); sqlite3_finalize(stmt); } else { printf("Already have or don't want Service: %s / %s\n",services->provider,services->name); } services = services->next; } } static void do_programs(PRG *programs) { uint16_t parr[255]; // ?? uint16_t count,i,seen; char charbuf[255]; bzero(&parr,sizeof(parr)); i = count = seen = 0; sprintf(charbuf,"select s_id from prg where tsid='%d'",programs->tsid); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return ; } else { cols = sqlite3_column_count(stmt); // execute the statement do { rc = sqlite3_step(stmt); switch( rc ) { case SQLITE_DONE: break; case SQLITE_ROW: // print results for this row txt = (const char*)sqlite3_column_text(stmt,0); parr[count++] = atoi(txt); break; default: fprintf(stderr, "Error: %d : %s\n", rc, sqlite3_errmsg(db)); break; } } while( rc==SQLITE_ROW ); // finalize the statement to release resources sqlite3_finalize(stmt); } while(programs) { seen = 0; for(i = 0 ; i != count; i++) { if(programs->s_id == parr[i]) { seen = 1; break; // from for } } if(seen == 0) { sprintf(charbuf,"insert into prg values ('%d','%d','%d','%d','%d','%d','%d','0')", programs->s_id,programs->service_type,programs->eit,programs->pf,programs->ppid,programs->tsid,programs->vpid); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return ; } rc = sqlite3_step(stmt); sqlite3_finalize(stmt); } programs = programs->next; } } static void do_apids(APID *apids) { uint16_t aarr[255]; // ?? uint16_t count,i,seen; char charbuf[255]; bzero(&aarr,sizeof(aarr)); i = count = seen = 0; sprintf(charbuf,"select ppid from apid where tsid='%d'",apids->tsid); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return ; } else { cols = sqlite3_column_count(stmt); // execute the statement do { rc = sqlite3_step(stmt); switch( rc ) { case SQLITE_DONE: break; case SQLITE_ROW: // print results for this row txt = (const char*)sqlite3_column_text(stmt,0); aarr[count++] = atoi(txt); break; default: fprintf(stderr, "Error: %d : %s\n", rc, sqlite3_errmsg(db)); break; } } while( rc==SQLITE_ROW ); // finalize the statement to release resources sqlite3_finalize(stmt); } while(apids) { seen = 0; for(i = 0 ; i != count; i++) { if(apids->ppid == aarr[i]) { seen = 1; break; // from for } } if(seen == 0) { sprintf(charbuf,"insert into apid values ('%d','%d','%d','%d','%d',\"%s\")", apids->ppid,apids->tsid,apids->pid,apids->type,apids->ac3,apids->lang); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return ; } rc = sqlite3_step(stmt); sqlite3_finalize(stmt); } apids = apids->next; } } static bool read_tpinfo(TRANSPORT *ts) { uint8_t buffer[4096],*p; char charbuf[255]; struct dmx_sct_filter_params sctFilterParams; uint16_t seclen,tsid,i,program_number,map_pid, service_id,dlooplen,ci,infolen,epid; uint8_t secnum,lastsec,stype,isac3,haslang,isaudio,effect; uint16_t nbytes; bool happy; PRG *programs,*pptr; SERVICE *services,*sptr; APID *apids,*aptr; programs = pptr = NULL; services = sptr = NULL; apids = aptr = NULL; effect = 0; /* read PAT (PID 0) */ memset(&sctFilterParams, 0, sizeof(sctFilterParams)); sctFilterParams.pid = 0x0; sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC; sctFilterParams.filter.filter[0] = 0x0; sctFilterParams.filter.mask[0] = 0xff; if (ioctl(demux_fd, DMX_SET_FILTER, &sctFilterParams) < 0) { printf("DMX filter set failed in read_tpinfo ! (fd = %d) %s,%d\n",demux_fd,__FILE__,__LINE__); return false; } happy = false; bzero(sections,255); while(happy != S_DONE) { while (1) { bzero(buffer,4096); nbytes = time_read(demux_fd,MAXT,buffer,4096); if (nbytes <= 0) { perror("### no data from demux for pid 0"); return false; } if (buffer[0] == 0) /// PAT table, just in case they also send other stuff { printf("read %d bytes for table %d\n",nbytes,buffer[0]); break; } } p = &buffer[0]; p++; // table_id seclen = (*p & 0xf) << 8; p++; seclen |= *p; p++; //now pointing to tsid tsid = *p << 8; p++; tsid |= *p; ts->tsid = tsid; p++; //reserverd/version/cur-next p++; // secnum secnum = *p; p++; lastsec = *p; happy = checksec(secnum,lastsec); if(happy == S_HAVE) continue; INFO("sec %d lastsec %d happy %s\n",secnum,lastsec,happy == S_DONE ? ":-)" : ":-("); p++; i = seclen - 9; //sub crc, position while(i != 0) { program_number = *p << 8; p++; program_number |= *p; p++; map_pid = (*p & 0x1f) << 8; p++; map_pid |= *p; p++; if(program_number == 0) printf("Network PID\n"); else { if(programs == NULL) { if(!(programs = malloc(sizeof(PRG)))) { perror("out of mem"); exit(0); } bzero(programs,sizeof(PRG)); programs->next = NULL; pptr = programs; } else { if(!(pptr->next = malloc(sizeof(PRG)))) { perror("out of mem"); exit(0); } pptr = pptr->next; bzero(pptr,sizeof(PRG)); pptr->next = NULL; } pptr->s_id = program_number; pptr->tsid = tsid; pptr->ppid = map_pid; INFO("number %d map_pid %d\n",program_number,map_pid); } i -= 4; } } /// elementary pids found, read audio PIDS /// set video pid in pptr pptr = programs; while(pptr) { memset(&sctFilterParams, 0, sizeof(sctFilterParams)); INFO("###########Scan PID %d\n",pptr->ppid); sctFilterParams.pid = pptr->ppid; sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC; sctFilterParams.filter.filter[0] = 0x02; sctFilterParams.filter.mask[0] = 0xff; if (ioctl(demux_fd, DMX_SET_FILTER, &sctFilterParams) < 0) { printf("DMX filter set failed in read_tpinfo ! (fd = %d) %s,%d",demux_fd,__FILE__,__LINE__); perror(""); return false; } happy = false; bzero(sections,255); while(happy != S_DONE) { bzero(buffer,4096); nbytes = time_read(demux_fd,MAXT,buffer,4096); if ( nbytes <= 0) { sprintf((char *)buffer,"### no data from demux PID #%d (%s,%d)",pptr->ppid,__FILE__,__LINE__); perror((char *)buffer); pptr = pptr->next; happy = S_DONE; continue; //return false; } p = &buffer[0]; p++; //table id seclen = (*p & 0xf) << 8; p++; seclen |= *p; i = seclen - 4 ; p++; p++; //program # i--; p++; // reserved / version / cur-next i--; p++; secnum = *p; i--; p++; lastsec = *p; happy = checksec(secnum,lastsec); if(happy == S_HAVE) continue; INFO("sec %d lastsec %d happy %s\n",secnum,lastsec,happy == S_DONE ? ":-)" : ":-("); i--; p++; i--; p++; i--; p++; i--; // PCR pid infolen = (*p & 0x0f) << 8; p++; i--; infolen |= *p; p++; i--; p += infolen; i -= infolen; //skip info while(i != 0) // read stream type loop { stype = *p; p++; i--; epid = (*p & 0x1f) << 8; p++; i--; epid |= *p; p++; i--; infolen = (*p & 0x0f) << 8; p++; i--; infolen |= *p; p++; i--; isac3 = haslang = isaudio = 0; INFO("---------Stype = %d service %d\n",stype,pptr->s_id); switch(stype) { case 2: case 27: // video p += infolen; i -= infolen; pptr->vpid = epid; //p++ ; i--; break; case 6: // audio if ac3 descr (0x6a) case 3 ... 4: // audio while(infolen != 0) // loop over descriptors find 0xa { if(*p == 0x6a) /// ac3 descr { isac3 = 1; infolen--; p++; i--; i -= *p; infolen -= *p; p += *p; p++; i--; infolen--; } else if(*p == 0xa) { haslang = 1; if((stype == 3) || (stype == 4) ) isaudio = 1; p++; infolen--; i--; bzero(charbuf,4); //*p+1); memcpy(charbuf,p+1,3);//*p); // 4th byte -> audio type effect = *(p + 4); i -= *p; infolen -= *p; p += *p; p++; i--; infolen--; } else { infolen--; p++; i--; i -= *p; infolen -= *p; p += *p; p++; i--; infolen--; } } if((haslang && isac3) || (haslang && isaudio)) { if(aptr == NULL) { if(!(aptr = apids = malloc(sizeof(APID)))) { perror("audio"); exit(0); } bzero(aptr,sizeof(APID)); } else { if(!(aptr->next = malloc(sizeof(APID)))) { perror("audio 2"); exit(0); } aptr = aptr->next; bzero(aptr,sizeof(APID)); aptr->next = NULL; } aptr->pid = epid; aptr->ppid = pptr->ppid; aptr->tsid = pptr->tsid; aptr->type = stype; aptr->ac3 = isac3; strcpy((char *)aptr->lang,(char *)charbuf); INFO("found pid %d for %d type %d lang %s effect %d ac3=%d\n", aptr->pid,aptr->ppid,aptr->type,aptr->lang,effect,aptr->ac3); } break; default: // teletext, data, .... p += infolen; i -= infolen; //p++ ; i--; break; } } pptr = pptr->next; } } /// read provider/channelinfo memset(&sctFilterParams, 0, sizeof(sctFilterParams)); sctFilterParams.pid = 0x11; sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC; sctFilterParams.filter.filter[0] = 0x42; sctFilterParams.filter.mask[0] = 0xff; if (ioctl(demux_fd, DMX_SET_FILTER, &sctFilterParams) < 0) { printf("DMX filter set failed in read_tpinfo ! (fd = %d) %s,%d\n",demux_fd,__FILE__,__LINE__); return false; } bzero(sections,255); happy = false; while(happy != S_DONE) { while (1) { bzero(buffer,4096); nbytes = time_read(demux_fd,MAXT,buffer,4096); if (nbytes <= 0) { printf("nbytes = %d --",nbytes); perror("### no data from demux PID 0x11 !"); return false; // WERK DVB-T sometimes takes ages !! } if (buffer[0] == 0x42) /// SDT actual { printf("read %d bytes for table 0x%x\n",nbytes,buffer[0]); break; } } p = &buffer[0]; p++; //table id seclen = (*p & 0xf) << 8; p++; seclen |= *p; // printf("secl %d\n",seclen); p++; i = seclen - 4 ; //sub 4 for CRC tsid = *p << 8; p++; i--; tsid |= *p; p++; i--; p++; secnum = *p; i--; p++; lastsec = *p; happy = checksec(secnum,lastsec); if(happy == S_HAVE) continue; INFO("sec %d lastsec %d len %d happy %s\n",secnum,lastsec,i,happy == S_DONE ? ":-)" : ":-("); i--; p++; i--; p++; i--; p++; i--; p++; i--; do { //printf("i %d\n",i); if(sptr == NULL) { if(!(services = sptr = malloc(sizeof(SERVICE)))) { printf("out of mem %d %s\n",__LINE__,__FILE__); exit(0); } bzero(sptr,sizeof(SERVICE)); sptr->next = NULL; } else { if(!(sptr->next = malloc(sizeof(SERVICE)))) { printf("out of mem %d %s\n",__LINE__,__FILE__); exit(0); } sptr = sptr->next; bzero(sptr,sizeof(SERVICE)); sptr->next = NULL; } service_id = *p <<8; p++; i--; service_id |= *p; sptr->s_id = service_id; sptr->tsid = tsid; //printf("sid %d\n",service_id); p++; i--; pptr = programs; while(pptr) { if(pptr->s_id == service_id) break; pptr = pptr->next; } if(pptr) { pptr->eit = (*p & 2) ? 1 : 0; pptr->pf = *p & 1; } p++; i--; sptr->running = (*p & 0xe0) >> 5; //upper 3 bits give status 0 -7 sptr->ca = (*p & 0x10) >> 4; dlooplen = (*p & 0xf) << 8; p++; i--; dlooplen |= *p; p++; i--; do { if(*p == 0x48) //service_descr { p++; i--; dlooplen--; dlooplen -= *p; // sub descr. len i -= *p; p++; sptr->type = *p; p++; nbytes = *p; p++; bzero(sptr->provider,255); bzero(sptr->name,255); for(ci = 0; ci != nbytes; ci++) { sptr->provider[ci] = *(p++); } sptr->provider[nbytes + 1 ] = '\0'; nbytes = *p; p++; for(ci = 0; ci != nbytes; ci++) { sptr->name[ci] = *(p++); } specialchars((uint8_t *)&sptr->name[0],255); specialchars((uint8_t *)&sptr->provider[0],255); sptr->name[nbytes + 1 ] = '\0'; INFO("prov >%s<, name >%s< rstatus %d service %d on ts %d\n", sptr->provider,sptr->name,sptr->running,sptr->s_id,tsid); i--; dlooplen--; // last increment of p in loop } else { p++; i--; dlooplen--;//just forget this descr dlooplen -= *p; i -= *p; // sub descr. len p = p + *p; p++; i--; dlooplen--; } } while(dlooplen != 0); } while(i != 0); } /*** now, stick everything we don't already have there into db ***/ /// first check if we know the transport / transponder we're on sprintf(charbuf,"select count(*) from ts where tsid='%d' and adapter='%d'",programs->tsid,ts->adapter); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return false; } else { cols = sqlite3_column_count(stmt); // execute the statement do { rc = sqlite3_step(stmt); switch( rc ) { case SQLITE_DONE: break; case SQLITE_ROW: // print results for this row txt = (const char*)sqlite3_column_text(stmt, 0); INFO("tsa %d txt %s\n",ts->adapter,txt); if(atoi(txt) == 0) { sprintf(charbuf,"insert into ts values ('%d','%d','%d','%d','%d')", programs->tsid,ts->freq,ts->qam,ts->bw,ts->adapter); rc = sqlite3_prepare_v2(db, charbuf, -1, &stmt, 0); if( rc ) { fprintf(stderr, "SQL error: %d : %s @ %s %d\n", rc, sqlite3_errmsg(db),__FILE__,__LINE__); return false; } rc = sqlite3_step(stmt); sqlite3_finalize(stmt); } else INFO("found adapter in db\n"); //rc = SQLITE_DONE; break; default: fprintf(stderr, "Error: %d : %s\n", rc, sqlite3_errmsg(db)); break; } } while( rc==SQLITE_ROW ); // finalize the statement to release resources sqlite3_finalize(stmt); } do_services(services); do_programs(programs); do_apids(apids); while(services) { sptr = services->next; free(services); services = sptr; } while(programs) { pptr = programs->next; free(programs); programs = pptr; } while(apids) { aptr = apids->next; free(apids); apids = aptr; } // sqlite3_close(db); return true; } #if 1 int scan(ADAPTER *ad) { char buf[255]; TRANSPORT transp; unsigned long sfreq; uint8_t step; uint8_t haslock; uint32_t lstart,lend,hstart,hend; uint8_t lstep,hstep; switch(ad->type) { case CABLE: fill_parms('C',&fe_parm); lstart = 113000000; lend = 185000000; lstep = 8; step = 8; hstart = 306000000; hend = 862000000; hstep = 8; break; case TERR: fill_parms('T',&fe_parm); lstart = 177500000; lend = 226500000; lstep = 7; step = 7; hstart = 474000000; hend = 858000000; hstep = 8; break; case SAT: default: printf("Adapter type not implemented!\n"); return false; } sprintf(buf,"/dev/dvb/adapter%d/frontend0",ad->number); if(!(frontend_fd = open(buf, O_RDWR))) { printf("frontend open #%d",ad->number); perror(""); return false; } sprintf(buf,"/dev/dvb/adapter%d/demux0",ad->demux); if(!(demux_fd = open(buf, O_RDWR))) { printf("demux #%d",ad->number); perror(""); if(frontend_fd) close(frontend_fd); return false; } fe_parm.frequency = 177500000; //FREQ; /*** terr freqs: 177500000 - 226500000 step 7 vhf band III (nothing on band I, here) 474000000 - 858000000 step 8 uhf ***/ for(sfreq = lstart; sfreq <= hend; sfreq += (step * 1000000)) // for(sfreq = 177500000; sfreq <= 858000000; sfreq += (step * 1000000)) { haslock = 0; bzero(&transp,sizeof(TRANSPORT)); if(sfreq == lend) // switch to different band { sfreq = hstart; step = hstep; if(ad->type == TERR) fe_parm.u.ofdm.bandwidth = step == 7 ? BANDWIDTH_7_MHZ : BANDWIDTH_8_MHZ; //fe_parm.u.ofdm.bandwidth = BANDWIDTH_8_MHZ; } transp.freq = sfreq; transp.bw = step; ///DVBT differs ! transp.adapter = ad->number; /// make dynamic if(ad->type != TERR) fe_parm.u.qam.modulation = QAM_64; fe_parm.frequency = sfreq; //FREQ; setup_frontend(frontend_fd,&fe_parm); if( false == check_frontend(frontend_fd,8)) { fe_parm.u.qam.modulation = QAM_256; setup_frontend(frontend_fd,&fe_parm); if(false == check_frontend(frontend_fd,4)) printf("No lock on %ld\n",sfreq); //} else { printf("Lock on %ld\n",sfreq); haslock = 1; } } else { printf("Lock on %ld\n",sfreq); haslock = 1; }/**/ if(haslock == 1) { fflush(stdout); //getchar(); transp.qam = fe_parm.u.qam.modulation; read_tpinfo(&transp); //getchar(); } //break; } close(frontend_fd); close(demux_fd); return 0; } #endif