source: titan/titan/frontenddev.h @ 38592

Last change on this file since 38592 was 35283, checked in by gost, 9 years ago

[titan] new skinfunction gettunerlock

File size: 43.2 KB
Line 
1#ifndef FRONTENDDEV_H
2#define FRONTENDDEV_H
3
4int calclof(struct dvbdev* node, struct transponder* tpnode, char* feaktnr, int flag)
5{
6        int loftype = 0;
7        int lofl, lofh, lofthreshold;
8        int satcrfrequ = 0;
9        char* tmpstr = NULL;
10
11        if(node == NULL || tpnode == NULL)
12        {
13                err("NULL detect");
14                return -1;
15        }
16
17        if(node->feinfo->type != FE_QPSK)
18                return 0;
19
20        unsigned int frequency = tpnode->frequency;
21        node->feunicable = 0;
22
23        if(feaktnr == NULL) feaktnr = node->feaktnr;
24
25        tmpstr = ostrcat(node->feshortname, "_lnb_loftype", 0, 0);
26        loftype = getconfigint(tmpstr, feaktnr);
27        free(tmpstr); tmpstr = NULL;
28        switch(loftype)
29        {
30                case 1: //c-band
31                        lofl = 5150 * 1000;
32                        lofh = 5150 * 1000;
33                        lofthreshold = 5150 * 1000;
34                        break;
35                case 2: //user
36                        tmpstr = ostrcat(node->feshortname, "_lnb_lofl", 0, 0);
37                        lofl = getconfigint(tmpstr, feaktnr) * 1000;
38                        free(tmpstr); tmpstr = NULL;
39                        tmpstr = ostrcat(node->feshortname, "_lnb_lofh", 0, 0);
40                        lofh = getconfigint(tmpstr, feaktnr) * 1000;
41                        free(tmpstr); tmpstr = NULL;
42                        tmpstr = ostrcat(node->feshortname, "_lnb_lofthreshold", 0, 0);
43                        lofthreshold = getconfigint(tmpstr, feaktnr) * 1000;
44                        free(tmpstr); tmpstr = NULL;
45                        break;
46                case 3: //unicable
47                case 4: //user unicable
48                        tmpstr = ostrcat(node->feshortname, "_lnb_lofl", 0, 0);
49                        lofl = getconfigint(tmpstr, feaktnr) * 1000;
50                        free(tmpstr); tmpstr = NULL;
51                        if(lofl == 0) lofl = 9750 * 1000;
52                        tmpstr = ostrcat(node->feshortname, "_lnb_lofh", 0, 0);
53                        lofh = getconfigint(tmpstr, feaktnr) * 1000;
54                        free(tmpstr); tmpstr = NULL;
55                        if(lofh == 0) lofh = 10600 * 1000;
56                        tmpstr = ostrcat(node->feshortname, "_lnb_lofthreshold", 0, 0);
57                        lofthreshold = getconfigint(tmpstr, feaktnr) * 1000;
58                        free(tmpstr); tmpstr = NULL;
59                        if(lofthreshold == 0) lofthreshold = 11700 * 1000;
60                        tmpstr = ostrcat(node->feshortname, "_lnb_satcrfrequ", 0, 0);
61                        satcrfrequ = getconfigint(tmpstr, feaktnr) * 1000;
62                        free(tmpstr); tmpstr = NULL;
63                        break;
64                default: //standard lnb
65                        lofl = 9750 * 1000;
66                        lofh = 10600 * 1000;
67                        lofthreshold = 11700 * 1000;
68        }
69
70        if(lofthreshold && lofh && frequency >= lofthreshold)
71        {
72                if(flag == 1) return 1;
73                node->feaktband = 1;
74        }
75        else
76        {
77                if(flag == 1) return 0;
78                node->feaktband = 0;
79        }
80
81        if(satcrfrequ == 0)
82        {
83                if(node->feaktband)
84                        node->feloffrequency = frequency - lofh;
85                else
86                {
87                        if(frequency < lofl)
88                                node->feloffrequency = lofl - frequency;
89                        else
90                                node->feloffrequency = frequency - lofl;
91                }
92        }
93        else
94        {
95                int lof = (node->feaktband & 1) ? lofh : lofl;
96                unsigned int tmp = (frequency - lof) + satcrfrequ;
97                node->feloffrequency = (tmp / 4) - 350000;
98                node->feunicable = 1;
99        }
100
101        debug(200, "tuning to freq %d (befor lof %d), band=%d, unicable=%d", node->feloffrequency, frequency, node->feaktband, node->feunicable);
102        return node->feaktband;
103}
104
105char* fegettypestr(struct dvbdev* dvbnode)
106{
107        char* text = NULL;
108
109        if(dvbnode == NULL)
110        {
111                err("NULL detect");
112                return NULL;
113        }
114
115        switch(dvbnode->feinfo->type)
116        {
117                case FE_QPSK: text = ostrcat(text, "DVB-S", 1, 0); break;
118                case FE_QAM: text = ostrcat(text, "DVB-C", 1, 0); break;
119                case FE_OFDM: text = ostrcat(text, "DVB-T", 1, 0); break;
120                default: text = ostrcat(text, "unknown", 1, 0);
121        }
122
123        return text;
124}
125
126struct dvbdev* fegetbyshortname(char* feshortname)
127{
128        struct dvbdev* dvbnode = dvbdev;
129       
130        while(dvbnode != NULL)
131        {
132                if(dvbnode->type == FRONTENDDEV && ostrcmp(dvbnode->feshortname, feshortname) == 0)
133                        return dvbnode;
134                dvbnode = dvbnode->next;
135        }
136        return NULL;
137}
138
139void fegetconfig(struct dvbdev *dvbnode, struct transponder *tpnode, char** aktnr, char* tmpnr)
140{
141        char* tmpstr = NULL;
142
143        if(dvbnode == NULL || tpnode == NULL)
144        {
145                err("NULL detect");
146                return;
147        }
148
149        tmpstr = ostrcat(dvbnode->feshortname, "_satnr", 0, 0);
150        *aktnr = getconfig(tmpstr, tmpnr);
151        free(tmpstr); tmpstr = NULL;
152}
153
154struct dvbdev* fegetdummy()
155{
156        struct dvbdev* dvbnode = dvbdev;
157
158        while(dvbnode != NULL)
159        {
160                if(dvbnode->type == FRONTENDDEVDUMMY)
161                        return dvbnode;
162                dvbnode = dvbnode->next;
163        }
164        return NULL;
165}
166
167void settunerstatus()
168{
169        struct dvbdev* dvbnode = dvbdev;
170
171        while(dvbnode != NULL)
172        {
173                //FRONTENDDEV first in the list
174                if(dvbnode->type != FRONTENDDEV) break;
175
176                //check if tuner is deactivate
177                if(ostrcmp("x", getconfig(dvbnode->feshortname, NULL)) == 0)
178                        dvbnode->deactive = 1;
179                else
180                        dvbnode->deactive = 0;
181
182                dvbnode = dvbnode->next;
183        }
184}
185
186//flag 0 = normal
187//flag 1 = check only
188//flag 2 = from record
189//flag 3 = from rectimer
190struct dvbdev* fegetfree(struct transponder* tpnode, int flag, struct dvbdev* dvbfirst)
191{
192        struct dvbdev* dvbnode = NULL;
193        struct dvbdev* tmpdvbnode = NULL;
194        char* tmpstr = NULL, *tmpnr = NULL, *aktnr = NULL;
195        int i, orbitalpos = 0, band = 0;
196
197        if(dvbfirst != NULL)
198                dvbnode = dvbfirst;
199        else
200                dvbnode = dvbdev;
201
202        if(tpnode == NULL)
203        {
204                err("NULL detect");
205                return NULL;
206        }
207
208        //suche tuner der auf der gleichen orbitalpos/frequency/pol/band ist
209        while(dvbnode != NULL)
210        {
211                //FRONTENDDEV first in the list
212                if(dvbnode->type != FRONTENDDEV) break;
213
214                //check if tuner is deactivate
215                if(dvbnode->deactive == 1)
216                {
217                        dvbnode = dvbnode->next;
218                        continue;
219                }
220
221                if(dvbnode->type == FRONTENDDEV && dvbnode->feinfo->type == tpnode->fetype)
222                {
223                        if(dvbnode->feakttransponder != NULL && dvbnode->feakttransponder->orbitalpos == tpnode->orbitalpos && dvbnode->feakttransponder->frequency == tpnode->frequency && dvbnode->feaktpolarization == tpnode->polarization)
224                        {
225                                band = calclof(dvbnode, tpnode, dvbnode->feaktnr, 1);
226                                if(dvbnode->feaktband != band)
227                                {
228                                        dvbnode = dvbnode->next;
229                                        continue;
230                                }
231                                dvbnode->felasttransponder = dvbnode->feakttransponder;
232                                dvbnode->feakttransponder = tpnode;
233                                if(flag != 1) debug(200, "found tuner with same orbitalpos/frequency/pol/band %s", dvbnode->feshortname);
234                                return(dvbnode);
235                        }
236                }
237                dvbnode = dvbnode->next;
238        }
239        if(dvbfirst != NULL)
240                dvbnode = dvbfirst;
241        else
242                dvbnode = dvbdev;
243
244        //suche tuner der die gewuenschte orbitalpos kann und nicht belegt ist
245        while(dvbnode != NULL)
246        {
247                //FRONTENDDEV first in the list
248                if(dvbnode->type != FRONTENDDEV) break;
249
250                //check if tuner is deactivate
251                if(dvbnode->deactive == 1)
252                {
253                        dvbnode = dvbnode->next;
254                        continue;
255                }
256
257                if(dvbnode->type == FRONTENDDEV && dvbnode->feinfo->type == tpnode->fetype && dvbnode->felock == 0)
258                {
259                        if(flag == 2 && status.aktservice->fedev == dvbnode)
260                        {
261                                dvbnode = dvbnode->next;
262                                continue;
263                        }
264
265                        //check if tuner is loop and looptuner is locked
266                        tmpstr = getconfigbyval(dvbnode->feshortname, NULL);
267                        if(tmpstr != NULL) //found loop tuner
268                        {
269                                tmpdvbnode = fegetbyshortname(tmpstr);
270                                if(tmpdvbnode != NULL && tmpdvbnode->feakttransponder != NULL && tmpdvbnode->feaktpolarization != tpnode->polarization && (tmpdvbnode->felock != 0 || (flag == 2 && tmpdvbnode->felock == 0)))
271                                {
272                                        dvbnode = dvbnode->next;
273                                        continue;
274                                }
275                        }
276
277                        tmpstr = ostrcat(dvbnode->feshortname, "_sat", 0, 0);
278                        for(i = 1; i <= getmaxsat(dvbnode->feshortname); i++)
279                        {
280                                tmpnr = oitoa(i);
281
282                                orbitalpos = getconfigint(tmpstr, tmpnr);
283                                if(orbitalpos == tpnode->orbitalpos)
284                                {
285                                        fegetconfig(dvbnode, tpnode, &aktnr, tmpnr);
286                                        if(flag == 3)
287                                                band = calclof(dvbnode, tpnode, aktnr, 0);
288                                        else
289                                                band = calclof(dvbnode, tpnode, aktnr, 1);
290                                        if(tmpdvbnode != NULL && tmpdvbnode->feaktband != band && (tmpdvbnode->felock != 0 || (flag == 2 && tmpdvbnode->felock == 0)))
291                                        {
292                                                free(tmpnr); tmpnr = NULL;
293                                                continue;
294                                        }
295                                        if(flag == 1)
296                                        {
297                                                free(tmpstr); tmpstr = NULL;
298                                                free(tmpnr); tmpnr = NULL;
299                                                return dvbnode;
300                                        }
301                                        if(tmpdvbnode != NULL)
302                                        {
303                                                tmpdvbnode->feaktband = band;
304                                                tmpdvbnode->feaktpolarization = tpnode->polarization;
305                                        }
306                                        dvbnode->felasttransponder = dvbnode->feakttransponder;
307                                        dvbnode->feakttransponder = tpnode;
308                                        dvbnode->feaktpolarization = tpnode->polarization;
309                                        free(dvbnode->feaktnr);
310                                        if(aktnr != NULL)
311                                                dvbnode->feaktnr = ostrcat(aktnr, NULL, 0, 0);
312                                        else
313                                                dvbnode->feaktnr = NULL;
314
315                                        free(tmpstr); tmpstr = NULL;
316                                        free(tmpnr); tmpnr = NULL;
317                                        if(flag != 1) debug(200, "found free tuner witch same orbitalpos %s", dvbnode->feshortname);
318                                        return dvbnode;
319                                }
320                                free(tmpnr); tmpnr = NULL;
321                        }
322                        free(tmpstr); tmpstr = NULL;
323                }
324                dvbnode = dvbnode->next;
325        }
326        if(dvbfirst != NULL)
327                dvbnode = dvbfirst;
328        else
329                dvbnode = dvbdev;
330
331        //suche loop tuner, wo der haupttuner
332        //die gewuenschte orbitalpos kann, nicht belegt ist
333        //und auf der gleichen poarization/band ist, wo wir hintunen wollen
334        while(dvbnode != NULL)
335        {
336                //FRONTENDDEV first in the list
337                if(dvbnode->type != FRONTENDDEV) break;
338
339                //check if tuner is deactivate
340                if(dvbnode->deactive == 1)
341                {
342                        dvbnode = dvbnode->next;
343                        continue;
344                }
345
346                if(dvbnode->type == FRONTENDDEV && dvbnode->feinfo->type == tpnode->fetype && dvbnode->felock == 0)
347                {
348                        if(flag == 2 && status.aktservice->fedev == dvbnode)
349                        {
350                                dvbnode = dvbnode->next;
351                                continue;
352                        }
353
354                        //check if tuner is loop an looptuner is locked
355                        tmpstr = getconfig(dvbnode->feshortname, NULL);
356                        if(tmpstr != NULL) //found loop tuner
357                        {
358                                tmpdvbnode = fegetbyshortname(tmpstr);
359                                if(tmpdvbnode != NULL && tmpdvbnode->feakttransponder != NULL && tmpdvbnode->feaktpolarization != tpnode->polarization && (tmpdvbnode->felock != 0 || (flag == 2 && tmpdvbnode->felock == 0)))
360                                {
361                                        dvbnode = dvbnode->next;
362                                        continue;
363                                }
364                        }
365                        else
366                        {
367                                dvbnode = dvbnode->next;
368                                continue;
369                        }
370
371                        tmpstr = ostrcat(tmpdvbnode->feshortname, "_sat", 0, 0);
372                        for(i = 1; i <= getmaxsat(tmpdvbnode->feshortname); i++)
373                        {
374                                tmpnr = oitoa(i);
375                                orbitalpos = getconfigint(tmpstr, tmpnr);
376                                if(orbitalpos == tpnode->orbitalpos)
377                                {
378                                        fegetconfig(tmpdvbnode, tpnode, &aktnr, tmpnr);
379                                        if(flag == 3)
380                                                band = calclof(dvbnode, tpnode, aktnr, 0);
381                                        else
382                                                band = calclof(dvbnode, tpnode, aktnr, 1);
383                                        if(tmpdvbnode != NULL && tmpdvbnode->feaktband != band && (tmpdvbnode->felock != 0 || (flag >= 2 && tmpdvbnode->felock == 0)))
384                                        {
385                                                free(tmpnr); tmpnr = NULL;
386                                                continue;
387                                        }
388                                        if(flag == 1)
389                                        {
390                                                free(tmpstr); tmpstr = NULL;
391                                                free(tmpnr); tmpnr = NULL;
392                                                return dvbnode;
393                                        }
394                                        if(tmpdvbnode != NULL)
395                                        {
396                                                tmpdvbnode->feaktband = band;
397                                                tmpdvbnode->feaktpolarization = tpnode->polarization;
398                                        }
399                                        dvbnode->felasttransponder = dvbnode->feakttransponder;
400                                        dvbnode->feakttransponder = tpnode;
401                                        dvbnode->feaktpolarization = tpnode->polarization;
402                                        free(dvbnode->feaktnr);
403                                        if(aktnr != NULL)
404                                                dvbnode->feaktnr = ostrcat(aktnr, NULL, 0, 0);
405                                        else
406                                                dvbnode->feaktnr = NULL;
407                                        free(tmpstr); tmpstr = NULL;
408                                        free(tmpnr); tmpnr = NULL;
409                                        if(flag != 1) debug(200, "found free looptuner witch same orbitalpos/polarization/band %s", dvbnode->feshortname);
410                                        return dvbnode;
411                                }
412                                free(tmpnr); tmpnr = NULL;
413                        }
414                        free(tmpstr); tmpstr = NULL;
415                }
416                dvbnode = dvbnode->next;
417        }
418
419        return NULL;
420}
421
422int feopen(struct dvbdev* node, char *fedev)
423{
424        int fd = -1;
425
426        if(node != NULL)
427        {       
428                if((fd = open(node->dev, O_RDWR | O_NONBLOCK)) < 0)
429                        debug(200, "open frontend failed %s", node->dev);
430                node->fd = fd;
431        }
432        else
433        {
434                if((fd = open(fedev, O_RDWR | O_NONBLOCK)) < 0)
435                        debug(200, "open frontend failed %s", fedev);
436        }
437
438        closeonexec(fd);
439        return fd;
440}
441
442void feclose(struct dvbdev* node, int fd)
443{
444        if(node != NULL)
445        {
446                close(node->fd);
447                node->fd = -1;
448        }
449        else
450                close(fd);
451}
452
453int fegetunlock(struct dvbdev* node)
454{
455        fe_status_t status;
456
457        if(node == NULL)
458        {
459                err("NULL detect");
460                return 1;
461        }
462
463#ifdef SIMULATE
464        return 0;
465#endif
466
467        if(ioctl(node->fd, FE_READ_STATUS, &status) == -1)
468                perr("FE_READ_STATUS");
469
470        if(status & FE_HAS_LOCK)
471                return 0;
472        else
473                return 1;
474}
475
476int fewait(struct dvbdev* node)
477{
478        //struct dvb_frontend_event ev;
479        fe_status_t status;
480
481        int count = 0;
482
483        if(node == NULL)
484        {
485                err("NULL detect");
486                return 1;
487        }
488
489#ifdef SIMULATE
490        return 0;
491#endif
492
493        int timer = 500;
494
495#ifdef MIPSEL
496        timer = 2000;
497#endif
498
499        //wait for tuner ready
500        debug(200, "wait for tuner");
501        while(count <= timer)
502        {
503                count++;
504                //ioctl(node->fd, FE_GET_EVENT, &ev);
505                //if(ev.status & FE_HAS_LOCK)
506                //      return 0;
507                ioctl(node->fd, FE_READ_STATUS, &status);
508                if(status != 0)
509                        debug(200, "status=%d, fe_lock=%d", status, FE_HAS_LOCK);
510
511                if(errno == ERANGE)
512                {
513                        usleep(1000);
514                        continue;
515                }
516
517                if(status & FE_HAS_LOCK)
518//              if(FE_HAS_SYNC | FE_HAS_LOCK)
519                        return 0;
520                usleep(1000);
521        }
522
523        //if(ev.status & FE_HAS_LOCK)
524        //      return 0;
525        if(status & FE_HAS_LOCK)
526//      if(FE_HAS_SYNC | FE_HAS_LOCK)
527                return 0;
528        else
529                return 1;
530}
531
532void fegetfrontend(struct dvbdev* node)
533{
534        if(node == NULL)
535        {
536                err("NULL detect");
537                return;
538        }
539
540#if DVB_API_VERSION >= 5
541        struct dtv_property p[8];
542        struct dtv_properties cmdseq;
543        cmdseq.props = p;
544
545        p[0].cmd = DTV_DELIVERY_SYSTEM;
546        p[1].cmd = DTV_FREQUENCY;
547        p[2].cmd = DTV_MODULATION;
548        p[3].cmd = DTV_SYMBOL_RATE;
549        p[4].cmd = DTV_INNER_FEC;
550        p[5].cmd = DTV_INVERSION;
551        p[6].cmd = DTV_ROLLOFF;
552        p[7].cmd = DTV_PILOT;
553        cmdseq.num = 8;
554       
555        if(ioctl(node->fd, FE_GET_PROPERTY, &cmdseq) < 0)
556        {
557                perr("FE_GET_PROPERTY");
558        }
559        else
560        {
561                debug(200, "frontend akt delivery system = %d", p[0].u.data);
562                debug(200, "frontend akt frequency = %d", p[1].u.data);
563                debug(200, "frontend akt inversion = %d", p[5].u.data);
564                debug(200, "frontend akt symbol_rate = %d", p[3].u.data);
565                debug(200, "frontend akt fec_inner = %d", p[4].u.data);
566                debug(200, "frontend akt modulation = %d", p[2].u.data);
567                debug(200, "frontend akt rolloff = %d", p[6].u.data);
568                debug(200, "frontend akt pilot = %d", p[7].u.data);
569        }
570#else
571        struct dvb_frontend_parameters fe_param;
572
573        if(ioctl(node->fd, FE_GET_FRONTEND, &fe_param) < 0)
574        {
575                perr("FE_GET_FRONTEND");
576        }
577        else
578        {
579                debug(200, "frontend akt frequency = %d", fe_param.frequency);
580                debug(200, "frontend akt inversion = %d", fe_param.inversion);
581                debug(200, "frontend akt u.qpsk.symbol_rate = %d", fe_param.u.qpsk.symbol_rate);
582                debug(200, "frontend akt u.qam.symbol_rate = %d", fe_param.u.qam.symbol_rate);
583                debug(200, "frontend akt u.qpsk.fec_inner = %d", fe_param.u.qpsk.fec_inner);
584                debug(200, "frontend akt u.qam.fec_inner = %d", fe_param.u.qam.fec_inner);
585                debug(200, "frontend akt u.qam.modulation = %d", fe_param.u.qam.modulation);
586        }
587#endif
588}
589
590int fesettone(struct dvbdev* node, fe_sec_tone_mode_t tone, int wait)
591{
592        int ret = 0;
593       
594        if(node == NULL)
595        {
596                err("NULL detect");
597                return 1;
598        }
599
600        debug(200, "FE_SET_TONE: %d (%s)", tone, node->feshortname);
601        if(ioctl(node->fd, FE_SET_TONE, tone) == -1)
602        {
603                perr("FE_SET_TONE");
604                ret = 1;
605        }
606        else
607        {
608                node->feakttone = tone;
609                usleep(wait * 1000);
610        }
611       
612        return ret;
613}
614
615//flag 0: reset tuner params on volt off
616//flag 1: don't reset tuner params on volt off
617int fesetvoltage(struct dvbdev* node, fe_sec_voltage_t volt, int wait)
618{
619        int ret = 0;
620       
621        if(node == NULL)
622        {
623                err("NULL detect");
624                return 1;
625        }
626
627        debug(200, "FE_SET_VOLT: %d (%s)", volt, node->feshortname);
628        if(ioctl(node->fd, FE_SET_VOLTAGE, volt) == -1)
629        {
630                perr("FE_SET_VOLTAGE");
631                ret = 1;
632        }
633        else
634        {
635                node->feaktvolt = volt;
636                if(wait > 0) usleep(wait * 1000);
637
638                if(volt == SEC_VOLTAGE_OFF)
639                {
640                        node->feakttransponder = NULL;
641                        node->felasttransponder = NULL;
642                        node->feunicable = 0;
643                        node->feloffrequency = 0;
644                        node->feaktband = 0;
645                        node->feaktpolarization = 0;
646                        node->feakttone = 0;
647                }
648        }
649
650        return ret;
651}
652
653void fediseqcsendburst(struct dvbdev* node, fe_sec_mini_cmd_t burst, int wait)
654{
655        if(node == NULL)
656        {
657                err("NULL detect");
658                return;
659        }
660
661        debug(200, "FE_DISEQC_SEND_BURST: %d (%s)", burst, node->feshortname);
662        if(ioctl(node->fd, FE_DISEQC_SEND_BURST, burst) == -1)
663                perr("FE_DISEQC_SEND_BURST");
664        usleep(wait * 1000);
665}
666
667void fediseqcsendmastercmd(struct dvbdev* node, struct dvb_diseqc_master_cmd *cmd, int wait)
668{
669        int i, repeat = 0, imsg = 0;
670        char* tmpstr = NULL;
671
672        if(node == NULL)
673        {
674                err("NULL detect");
675                return;
676        }
677       
678        if(cmd == NULL) return;
679        if(cmd->msg_len == 0) return;
680
681        tmpstr = ostrcat(node->feshortname, "_diseqc_repeat", 0, 0);
682        repeat = getconfigint(tmpstr, node->feaktnr);
683        free(tmpstr); tmpstr = NULL;
684        if(repeat < 1) repeat = 1;
685
686        for(i = 0; i < repeat; i++)
687        {
688                if(ioctl(node->fd, FE_DISEQC_SEND_MASTER_CMD, cmd) == -1)
689                {
690                        perr("FE_DISEQC_SEND_MASTER_CMD");
691                }
692                usleep(wait * 1000);
693        }
694        imsg = (cmd->msg[0] << 24) | (cmd->msg[1] << 16) | (cmd->msg[2] << 8) | cmd->msg[3];
695        debug(200, "DISEQC Master cmd (%s -> %04X)", node->feshortname, imsg);
696}
697
698void fesdiseqcpoweron(struct dvbdev* node)
699{
700        struct dvb_diseqc_master_cmd cmd = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0};
701
702        if(node == NULL)
703        {
704                err("NULL detect");
705                return;
706        }
707
708        cmd.msg[0] = 0xE0;
709        cmd.msg[1] = 0x00;
710        cmd.msg[2] = 0x03;
711        cmd.msg_len = 3;
712
713        debug(200, "DISEQC Power on (%s)", node->feshortname);
714        fediseqcsendmastercmd(node, &cmd, 100);
715}
716
717void fesdiseqcreset(struct dvbdev* node)
718{
719        struct dvb_diseqc_master_cmd cmd = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0};
720       
721        if(node == NULL)
722        {
723                err("NULL detect");
724                return;
725        }
726
727        cmd.msg[0] = 0xE0;
728        cmd.msg[1] = 0x00;
729        cmd.msg[2] = 0x00;
730        cmd.msg_len = 3;
731
732        debug(200, "DISEQC Reset (%s)", node->feshortname);
733        fediseqcsendmastercmd(node, &cmd, 100);
734}
735
736void fesdiseqcstandby(struct dvbdev* node)
737{
738        struct dvb_diseqc_master_cmd cmd = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0};
739       
740        if(node == NULL)
741        {
742                err("NULL detect");
743                return;
744        }
745       
746        cmd.msg[0] = 0xE0;
747        cmd.msg[1] = 0x00;
748        cmd.msg[2] = 0x02;
749        cmd.msg_len = 3;
750
751        debug(200, "DISEQC Standby (%s)", node->feshortname);
752        fediseqcsendmastercmd(node, &cmd, 100);
753}
754
755void fediseqcrotor(struct dvbdev* node, struct transponder* tpnode, int pos, int flag)
756{
757        int orbitalpos = 0;
758        fe_sec_voltage_t oldvolt = 0;
759        fe_sec_tone_mode_t oldtone = 0;
760        struct dvb_diseqc_master_cmd cmd = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0};
761       
762        if(node == NULL)
763        {
764                err("NULL detect");
765                return;
766        }
767       
768        fesdiseqcpoweron(node);
769       
770        oldvolt = node->feaktvolt;
771        oldtone = node->feakttone;
772
773        if(tpnode == NULL)
774                orbitalpos = 0;
775        else
776                orbitalpos = tpnode->orbitalpos;
777       
778        //float speed13V = 1.5; //1.5 Grad pro sec
779        float speed18V = 1; //2.4 Grad pro sek
780        float degreesmov, waittime;
781       
782        switch(flag)
783        {
784                case 0: //stop move
785                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x60; cmd.msg_len = 3;
786                        debug(200, "DISEQC Rotorpos stop move (%s)", node->feshortname);
787                        break;
788                case 1: //disable limits
789                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x63; cmd.msg_len = 3;
790                        debug(200, "DISEQC Rotorpos disable limits (%s)", node->feshortname);
791                        break;
792                case 2: //enable limits
793                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x6A; cmd.msg[3] = 0x00; cmd.msg_len = 4;
794                        debug(200, "DISEQC Rotorpos enable limits (%s)", node->feshortname);
795                        break;
796                case 3: //set east limit
797                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x66; cmd.msg_len = 3;
798                        debug(200, "DISEQC Rotorpos set east limit (%s)", node->feshortname);
799                        break;
800                case 4: //set west limit
801                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x67; cmd.msg_len = 3;
802                        debug(200, "DISEQC Rotorpos set west limit (%s)", node->feshortname);
803                        break;
804                case 5: //move east cont.
805                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x68; cmd.msg[3] = 0x00; cmd.msg_len = 4;
806                        debug(200, "DISEQC Rotorpos move east cont. (%s)", node->feshortname);
807                        break;
808                case 6: //move west cont.
809                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x69; cmd.msg[3] = 0x00; cmd.msg_len = 4;
810                        debug(200, "DISEQC Rotorpos move west cont. (%s)", node->feshortname);
811                        break;
812                case 7: //store pos
813                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x6A; cmd.msg[3] = pos; cmd.msg_len = 4;
814                        debug(200, "DISEQC Rotorpos store pos=%d (%s)", pos, node->feshortname);
815                        break;
816                case 8: //goto pos
817                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x6B; cmd.msg[3] = pos; cmd.msg_len = 4;
818                        debug(200, "DISEQC Rotorpos goto pos=%d (%s)", pos, node->feshortname);
819                        break;
820                case 9: //step xx pos east
821                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x68; cmd.msg[3] = 256 - pos; cmd.msg_len = 4;
822                        debug(200, "DISEQC Rotorpos step east pos=%d (%s)", pos, node->feshortname);
823                        break;
824                case 10: //step xx pos west
825                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x69; cmd.msg[3] = 256 - pos; cmd.msg_len = 4;
826                        debug(200, "DISEQC Rotorpos step west pos=%d (%s)", pos, node->feshortname);
827                        break;
828                case 11: //goto xx
829                        cmd.msg[0] = 0xE0; cmd.msg[1] = 0x31; cmd.msg[2] = 0x6E; cmd.msg[3] = (pos >> 8) & 0xff; cmd.msg[4] = pos & 0xff; cmd.msg_len = 5;
830                        debug(200, "DISEQC Rotorpos goto xx pos=%d (%s)", pos, node->feshortname);
831                        break;
832        }
833
834        if(flag >= 0 && flag < 7)
835        {
836                fesetvoltage(node, SEC_VOLTAGE_18, 15);
837                fesettone(node, SEC_TONE_OFF, 15);
838                fediseqcsendmastercmd(node, &cmd, 100);
839        }
840
841        if((flag == 7 || flag == 9 || flag == 10) && pos != 0)
842        {
843                fesetvoltage(node, SEC_VOLTAGE_18, 15);
844                fesettone(node, SEC_TONE_OFF, 15);
845                fediseqcsendmastercmd(node, &cmd, 100);
846        }
847
848        if((flag == 8 || flag == 11) && (orbitalpos == 0 || status.rotoroldorbitalpos == 0 || orbitalpos != status.rotoroldorbitalpos))
849        {
850                fesetvoltage(node, SEC_VOLTAGE_18, 15);
851                fesettone(node, SEC_TONE_OFF, 15);
852                fediseqcsendmastercmd(node, &cmd, 100);
853
854                if(status.rotoroldorbitalpos == 0 || orbitalpos == 0)
855                        waittime = 15;
856                else
857                {
858                        degreesmov = abs(orbitalpos - status.rotoroldorbitalpos) / 10;
859                        waittime = (int)ceil((float)degreesmov / (float)speed18V);
860                }
861
862                status.rotoroldorbitalpos = orbitalpos;
863                sleep(waittime);
864        }
865       
866        fesetvoltage(node, oldvolt, 15);
867        fesettone(node, oldtone, 15);
868}
869
870void fesetunicable(struct dvbdev* node)
871{
872        int unicabletune = 0;
873        char* tmpstr = NULL;
874        struct dvb_diseqc_master_cmd cmd = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0};
875
876        if(node == NULL)
877        {
878                err("NULL detect");
879                return;
880        }
881
882        tmpstr = ostrcat(node->feshortname, "_lnb_satcr", 0, 0);
883        int satcr = getconfigint(tmpstr, node->feaktnr) - 1;
884        if(satcr < 0) satcr = 0;
885        free(tmpstr); tmpstr = NULL;
886
887        tmpstr = ostrcat(node->feshortname, "_diseqc", 0, 0);
888        int aktdiseqc = getconfigint(tmpstr, node->feaktnr);
889        if(aktdiseqc < 1) aktdiseqc = 1;
890        free(tmpstr); tmpstr = NULL;
891
892        unicabletune |= ((satcr & 0x7) << 13);
893        unicabletune |= (((aktdiseqc - 1) & 0x1) << 12);
894        unicabletune |= (((!node->feaktpolarization) & 0x1) << 11);
895        unicabletune |= ((node->feaktband & 0x1) << 10);
896        unicabletune |= ((node->feloffrequency / 1000) & 0x3ff);
897
898        debug(200, "unicabletune %04X", unicabletune);
899       
900        if(status.firstunicablewait == 0)
901        {
902                status.firstunicablewait = getconfigint("firstunicablewait", NULL);
903                if(status.firstunicablewait == 0)
904                        status.firstunicablewait = 1000;
905        }               
906       
907        if(status.firstunicablewait > 0)
908        {
909                usleep(status.firstunicablewait * 1000);
910                status.firstunicablewait = -1;
911        }
912       
913        fesetvoltage(node, SEC_VOLTAGE_13, 15);
914        fesetvoltage(node, SEC_VOLTAGE_18, 15);
915        fesettone(node, SEC_TONE_OFF, 15);
916
917        //feunicable
918        //byte1 (bit 7/6/5) -> satcr number
919        //byte1 (bit 4/3/2) -> lnb number
920        //byte1 (bit 1/0) -> frequ
921        //byte0 -> frequ
922       
923        cmd.msg[0] = 0xE0;
924        cmd.msg[1] = 0x10;
925        cmd.msg[2] = 0x5A;
926        cmd.msg[3] = (unicabletune >> 8) & 0xff;
927        cmd.msg[4] = unicabletune & 0xff;
928        cmd.msg_len = 5;
929
930        debug(200, "send diseqc unicable cmd (%s)", node->feshortname);
931        fediseqcsendmastercmd(node, &cmd, 100);
932        fesetvoltage(node, SEC_VOLTAGE_13, 15);
933}
934
935void fediseqcset(struct dvbdev* node, struct transponder* tpnode)
936{
937        char* tmpstr = NULL;
938        int toneburst = 0, cmdorder = 0, input = 0, uinput = 0, diseqmode = 0, rotorpos = 0, latpos = 0, longpos = 0;
939        float latitude = 0, longitude = 0;
940        fe_sec_mini_cmd_t mini = -1;
941        struct dvb_diseqc_master_cmd cmd = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0};
942        struct dvb_diseqc_master_cmd ucmd = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0};
943       
944        if(node == NULL) return;
945       
946        tmpstr = ostrcat(node->feshortname, "_diseqc_committedcmd", 0, 0);
947        input = getconfigint(tmpstr, node->feaktnr);
948        free(tmpstr); tmpstr = NULL;
949        tmpstr = ostrcat(node->feshortname, "_diseqc_uncommittedcmd", 0, 0);
950        uinput = getconfigint(tmpstr, node->feaktnr);
951        free(tmpstr); tmpstr = NULL;
952        tmpstr = ostrcat(node->feshortname, "_diseqc_mode", 0, 0);
953        diseqmode = getconfigint(tmpstr, node->feaktnr);
954        free(tmpstr); tmpstr = NULL;
955        tmpstr = ostrcat(node->feshortname, "_diseqc_cmdorder", 0, 0);
956        cmdorder = getconfigint(tmpstr, node->feaktnr);
957        free(tmpstr); tmpstr = NULL;
958        tmpstr = ostrcat(node->feshortname, "_diseqc_toneburst", 0, 0);
959        toneburst = getconfigint(tmpstr, node->feaktnr);
960        free(tmpstr); tmpstr = NULL;
961        tmpstr = ostrcat(node->feshortname, "_diseqc_rotorpos", 0, 0);
962        rotorpos = getconfigint(tmpstr, node->feaktnr);
963        free(tmpstr); tmpstr = NULL;
964       
965        latitude = getconfigfloat("latitude", NULL);
966        longitude = getconfigfloat("longitude", NULL);
967        latpos = getconfigint("latpos", NULL);
968        longpos = getconfigint("longpos", NULL);
969
970        tmpstr = ostrcat(node->feshortname, "_diseqc", 0, 0);
971        int aktdiseqc = getconfigint(tmpstr, node->feaktnr);
972        if(aktdiseqc < 1) aktdiseqc = 1;
973        free(tmpstr); tmpstr = NULL;
974
975        debug(200, "set diseqc: number=%d, band=%d, pol=%d, diseqmode=%d, input=%d, uinput=%d, cmdorder=%d, toneburst=%d (%s)", aktdiseqc, node->feaktband, node->feaktpolarization, diseqmode, input, uinput, cmdorder, toneburst, node->feshortname);
976         
977        switch(toneburst)
978        {
979                case 1: mini = SEC_MINI_A; break;
980                case 2: mini = SEC_MINI_B; break;
981        }
982       
983        if(diseqmode == 100) // Tonburst A/B
984        {
985                debug(200, "set diseqc: Tonburst A/B (%s)", node->feshortname);
986                if(mini == -1)
987                        mini = (aktdiseqc - 1) % 2 ? SEC_MINI_B : SEC_MINI_A;
988                fediseqcsendburst(node, mini, 15);
989                return;
990        }
991               
992        if(diseqmode == 0 || diseqmode == 1) // Diseqc 1.0 + 1.1
993        {
994                debug(200, "set committed switch (%s)", node->feshortname);
995                fesdiseqcpoweron(node);
996                cmd.msg[0] = 0xE0;
997                cmd.msg[1] = 0x10;
998                cmd.msg[2] = 0x38;
999
1000                if(input == 0)
1001                        cmd.msg[3] = 0xF0 | ((((aktdiseqc - 1) * 4) & 0x0F) | (node->feaktband ? 1 : 0) | (node->feaktpolarization ? 0 : 2));
1002                else
1003                        cmd.msg[3] = 0xF0 + ((input - 1) & 0x0F);
1004
1005                cmd.msg_len = 4;
1006        }
1007
1008        if(diseqmode == 1) // Diseqc 1.1
1009        {
1010                if(uinput > 0)
1011                {
1012                        debug(200, "set uncommitted switch (%s)", node->feshortname);
1013                        fesdiseqcpoweron(node);
1014                        ucmd.msg[0] = 0xE0;
1015                        ucmd.msg[1] = 0x10;
1016                        ucmd.msg[2] = 0x39;
1017                        ucmd.msg[3] = 0xF0 + ((uinput - 1) & 0x0F);
1018                        ucmd.msg_len = 4;
1019                }
1020        }
1021                 
1022        switch(cmdorder)
1023        {
1024                case 1:
1025                        if(mini != -1) fediseqcsendburst(node, mini, 15);
1026                        fediseqcsendmastercmd(node, &cmd, 100);
1027                        break;
1028                case 2:
1029                        fediseqcsendmastercmd(node, &cmd, 100);
1030                        if(uinput > 0) fediseqcsendmastercmd(node, &ucmd, 100);
1031                        if(mini != -1) fediseqcsendburst(node, mini, 15);
1032                        break;
1033                case 3:
1034                        if(mini != -1) fediseqcsendburst(node, mini, 15);
1035                        fediseqcsendmastercmd(node, &cmd, 100);
1036                        if(uinput > 0) fediseqcsendmastercmd(node, &ucmd, 100);
1037                        break;
1038                case 4:
1039                        if(uinput > 0) fediseqcsendmastercmd(node, &ucmd, 100);
1040                        fediseqcsendmastercmd(node, &cmd, 100);
1041                        if(mini != -1) fediseqcsendburst(node, mini, 15);
1042                        break;
1043                case 5:
1044                        if(mini != -1) fediseqcsendburst(node, mini, 15);
1045                        if(uinput > 0) fediseqcsendmastercmd(node, &ucmd, 100);
1046                        fediseqcsendmastercmd(node, &cmd, 100);
1047                        break;
1048                default:
1049                        fediseqcsendmastercmd(node, &cmd, 100);
1050                        if(mini != -1) fediseqcsendburst(node, mini, 15);
1051                        break;
1052        }
1053       
1054        if(diseqmode == 2) // Diseqc 1.2
1055        {
1056                fediseqcrotor(node, tpnode, rotorpos, 8);
1057        }
1058       
1059        if(diseqmode == 3) // Diseqc 1.3 (USALS)
1060        {
1061                double orbitalpos = tpnode->orbitalpos / 10.00;
1062
1063                if(latpos == 1) // south
1064                        latitude = -latitude;
1065
1066                if(longpos == 1) // west
1067                        longitude = 360 - longitude;
1068
1069                double satHourAngle = calcSatHourangle(orbitalpos, latitude, longitude);
1070                int gotoXTable[10] = {0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E};
1071
1072                if(latitude >= 0) // Northern Hemisphere
1073                {
1074                        int tmp = (int)round(fabs(180 - satHourAngle) * 10.0);
1075                        rotorpos = (tmp / 10) * 0x10 + gotoXTable[tmp % 10];
1076
1077                        if(satHourAngle < 180) // the east
1078                                rotorpos |= 0xE000;
1079                        else // west
1080                                rotorpos |= 0xD000;
1081                }
1082                else // Southern Hemisphere
1083                {
1084                        if(satHourAngle < 180) // the east
1085                        {
1086                                int tmp = (int)round(fabs(satHourAngle) * 10.0);
1087                                rotorpos = (tmp / 10) * 0x10 + gotoXTable[tmp % 10];
1088                                rotorpos |= 0xD000;
1089                        }
1090                        else // west
1091                        {
1092                                int tmp = (int)round(fabs(360 - satHourAngle) * 10.0);
1093                                rotorpos = (tmp / 10) * 0x10 + gotoXTable[tmp % 10];
1094                                rotorpos |= 0xE000;
1095                        }
1096                }
1097                debug(200, "orbitalpos=%f, latitude=%f, longitude=%f, rotorpos=%04x", orbitalpos, latitude, longitude, rotorpos);
1098
1099                fediseqcrotor(node, tpnode, rotorpos, 11);
1100        }
1101}
1102
1103void feset(struct dvbdev* node, struct transponder* tpnode)
1104{
1105        int voltagemode = 0, tonemode = 0;
1106        fe_sec_tone_mode_t tone;
1107        fe_sec_voltage_t volt;
1108        struct dvbdev* dvbnode = dvbdev;
1109        char* tmpstr = NULL;
1110
1111        if(node == NULL)
1112        {
1113                err("NULL detect");
1114                return;
1115        }
1116
1117        // set volage off from other unused frontend
1118        while(dvbnode != NULL)
1119        {
1120                if(dvbnode->type != FRONTENDDEV) break;
1121                if(dvbnode->type == FRONTENDDEV && dvbnode != node && dvbnode->felock == 0 && dvbnode != status.aktservice->fedev)
1122                {
1123                        fesetvoltage(dvbnode, SEC_VOLTAGE_OFF, 0);
1124                }
1125                dvbnode = dvbnode->next;
1126        }
1127
1128        calclof(node, tpnode, NULL, 0);
1129
1130        tmpstr = ostrcat(node->feshortname, "lnb_voltagemode", 0, 0);
1131        voltagemode = getconfigint(tmpstr, node->feaktnr);
1132        free(tmpstr); tmpstr = NULL;
1133        switch(voltagemode)
1134        {
1135                case 1: volt = SEC_VOLTAGE_13; break;
1136                case 2: volt = SEC_VOLTAGE_18; break;
1137                default: volt = node->feaktpolarization ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
1138                         if(node->feunicable == 1) volt = SEC_VOLTAGE_13;
1139        }
1140        fesetvoltage(node, volt, 15);
1141
1142        tmpstr = ostrcat(node->feshortname, "_diseqc", 0, 0);
1143        if(getconfigint(tmpstr, node->feaktnr) == 0 || node->feunicable == 1)
1144        {
1145                debug(200, "don't use diseqc");
1146        }
1147        else
1148        {
1149                fesettone(node, SEC_TONE_OFF, 15);
1150                fediseqcset(node, tpnode);
1151        }
1152        free(tmpstr); tmpstr = NULL;
1153
1154        tmpstr = ostrcat(node->feshortname, "_lnb_tonemode", 0, 0);
1155        tonemode = getconfigint(tmpstr, node->feaktnr);
1156        free(tmpstr); tmpstr = NULL;
1157        switch(tonemode)
1158        {
1159                case 1: tone = SEC_TONE_ON; break;
1160                case 2: tone = SEC_TONE_OFF; break;
1161                default: tone = node->feaktband ? SEC_TONE_ON : SEC_TONE_OFF;
1162                         if(node->feunicable == 1) tone = SEC_TONE_OFF;
1163        }
1164        fesettone(node, tone, 15);
1165}
1166
1167void fediscard(struct dvbdev* node)
1168{
1169        struct dvb_frontend_event ev;
1170        int count = 0;
1171
1172        if(node == NULL)
1173        {
1174                err("NULL detect");
1175                return;
1176        }
1177
1178        /* discard stale QPSK events */
1179        while(count < 20)
1180        {
1181                count++;
1182                if(ioctl(node->fd, FE_GET_EVENT, &ev) == -1)
1183                        break;
1184        }
1185}
1186
1187uint16_t fereadsnr(struct dvbdev* node)
1188{
1189        uint16_t snr = 0;
1190
1191        if(node == NULL)
1192        {
1193                err("NULL detect");
1194                return 0;
1195        }
1196
1197        ioctl(node->fd, FE_READ_SNR, &snr);
1198        debug(200, "frontend snr = %02x", (snr * 100) / 0xffff);
1199        return snr;
1200}
1201
1202uint16_t fereadsignalstrength(struct dvbdev* node)
1203{
1204        uint16_t signal = 0;
1205
1206        if(node == NULL)
1207        {
1208                err("NULL detect");
1209                return 0;
1210        }
1211
1212        ioctl(node->fd, FE_READ_SIGNAL_STRENGTH, &signal);
1213        debug(200, "frontend signal = %02x", (signal * 100) / 0xffff);
1214        return signal;
1215}
1216
1217uint32_t fereadber(struct dvbdev* node)
1218{
1219        uint32_t ber = 0;
1220
1221        if(node == NULL)
1222        {
1223                err("NULL detect");
1224                return 0;
1225        }
1226
1227        ioctl(node->fd, FE_READ_BER, &ber);
1228        debug(200, "frontend ber = %02x", ber);
1229        return ber;
1230}
1231
1232uint32_t fereaduncorrectedblocks(struct dvbdev* node)
1233{
1234        uint32_t unc = 0;
1235
1236        if(node == NULL)
1237        {
1238                err("NULL detect");
1239                return 0;
1240        }
1241
1242        ioctl(node->fd, FE_READ_UNCORRECTED_BLOCKS, &unc);
1243        debug(200, "frontend unc = %02x", unc);
1244        return unc;
1245}
1246
1247fe_status_t fereadstatus(struct dvbdev* node)
1248{
1249        fe_status_t status;
1250
1251        if(node == NULL)
1252        {
1253                err("NULL detect");
1254                return -1;
1255        }
1256
1257        if(ioctl(node->fd, FE_READ_STATUS, &status) == -1)
1258                perr("FE_READ_STATUS");
1259
1260        debug(200, "frontend status = %02x", status);
1261        if(status & FE_HAS_LOCK) debug(200, "frontend = FE_HAS_LOCK");
1262        if(status & FE_HAS_SIGNAL) debug(200, "frontend = FE_HAS_SIGNAL");
1263        if(status & FE_HAS_CARRIER) debug(200, "frontend = FE_HAS_CARRIER");
1264        if(status & FE_HAS_VITERBI) debug(200, "frontend = FE_HAS_VITERBI");
1265        if(status & FE_HAS_SYNC) debug(200, "frontend = FE_HAS_SYNC");
1266        if(status & FE_TIMEDOUT) debug(200, "frontend = FE_TIMEDOUT");
1267        if(status & FE_REINIT) debug(200, "frontend = FE_REINIT");
1268
1269        return status;
1270}
1271
1272int fetunedvbs(struct dvbdev* node, struct transponder* tpnode)
1273{
1274        if(node == NULL || tpnode == NULL)
1275        {
1276                err("NULL detect");
1277                return 1;
1278        }
1279       
1280        if(node->feunicable == 1)
1281        {
1282                fesetunicable(node);
1283                char* tmpstr = ostrcat(node->feshortname, "_lnb_satcrfrequ", 0, 0);
1284                node->feloffrequency = getconfigint(tmpstr, node->feaktnr) * 1000;
1285                free(tmpstr); tmpstr = NULL;
1286        }
1287
1288#if DVB_API_VERSION >= 5
1289        struct dtv_property p[10];
1290        struct dtv_properties cmdseq;
1291        cmdseq.props = p;
1292
1293        //convert transponderlist for dvbapi5
1294        int system = tpnode->system;
1295        switch(system)
1296        {
1297                case 0: system = SYS_DVBS; break;
1298                case 1: system = SYS_DVBS2; break;
1299                default: system = SYS_DVBS; break;
1300        }
1301
1302        int fec = tpnode->fec;
1303        switch(fec)
1304        {
1305                case 0: fec = FEC_AUTO; break;
1306                case 1: fec = FEC_1_2; break;
1307                case 2: fec = FEC_2_3; break;
1308                case 3: fec = FEC_3_4; break;
1309                case 4: fec = FEC_5_6; break;
1310                case 5: fec = FEC_7_8; break;
1311                case 6: fec = FEC_8_9; break;
1312                case 7: fec = FEC_3_5; break;
1313                case 8: fec = FEC_4_5; break;
1314                case 9: fec = FEC_9_10; break;
1315                case 15: fec = FEC_NONE; break;
1316                default: fec = FEC_AUTO; break;
1317        }
1318       
1319        int pilot = tpnode->pilot;
1320        switch(pilot)
1321        {
1322                case 0: pilot = PILOT_OFF; break;
1323                case 1: pilot = PILOT_ON; break;
1324                case 2: pilot = PILOT_AUTO; break;
1325                default: pilot = PILOT_AUTO; break;
1326        }
1327
1328        int rolloff = tpnode->rolloff;
1329        switch(rolloff)
1330        {
1331                case 0: rolloff = ROLLOFF_35; break;
1332                case 1: rolloff = ROLLOFF_25; break;
1333                case 2: rolloff = ROLLOFF_20; break;
1334                default: rolloff = ROLLOFF_35; break;
1335        }
1336
1337        int modulation = tpnode->modulation;
1338        switch(modulation)
1339        {
1340                case 0: modulation = QPSK; break;
1341                case 1: modulation = QPSK; break;
1342                case 2: modulation = PSK_8; break;
1343                case 3: modulation = QAM_16; break;
1344                default: modulation = QPSK; break;
1345        }
1346
1347        p[0].cmd = DTV_CLEAR;
1348        p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = system;
1349        p[2].cmd = DTV_FREQUENCY,       p[2].u.data = node->feloffrequency;
1350        p[3].cmd = DTV_MODULATION,      p[3].u.data = modulation;
1351        p[4].cmd = DTV_SYMBOL_RATE,     p[4].u.data = tpnode->symbolrate;
1352        p[5].cmd = DTV_INNER_FEC,       p[5].u.data = fec;
1353        p[6].cmd = DTV_INVERSION,       p[6].u.data = (fe_spectral_inversion_t) tpnode->inversion;
1354        if(system == SYS_DVBS2)
1355        {
1356                p[7].cmd = DTV_ROLLOFF,         p[7].u.data = rolloff;
1357                p[8].cmd = DTV_PILOT,           p[8].u.data = pilot;
1358                p[9].cmd = DTV_TUNE;
1359                cmdseq.num = 10;
1360        }
1361        else
1362        {
1363                p[7].cmd = DTV_TUNE;
1364                cmdseq.num = 8;
1365        }
1366
1367        debug(200, "frequ=%d, inversion=%d, pilot=%d, rolloff=%d, fec=%d, sr=%d, modulation=%d, system=%d (%s)", node->feloffrequency, tpnode->inversion, pilot, rolloff, fec, tpnode->symbolrate, modulation, system, node->feshortname);
1368#else
1369        struct dvb_frontend_parameters tuneto;
1370        fe_spectral_inversion_t inversion = tpnode->inversion;
1371
1372        //convert transponderlist for dvbapi3
1373        int fec = tpnode->fec;
1374        if(tpnode->system == 1)
1375        {
1376                if(tpnode->modulation == 1) fec = fec + 9;
1377                if(tpnode->modulation == 2) fec = fec + 18;
1378        }
1379
1380        inversion |= (tpnode->rolloff << 2) | inversion; // use bit 2..3 of inversion for rolloff
1381        inversion |= (tpnode->pilot << 4) | inversion; // use bit 4..5 of inversion for pilot
1382
1383        tuneto.frequency = node->feloffrequency;
1384        tuneto.inversion = inversion;
1385        tuneto.u.qpsk.symbol_rate = tpnode->symbolrate;
1386        tuneto.u.qpsk.fec_inner = fec;
1387
1388        debug(200, "frequ=%d, inversion=%d, pilot=%d, rolloff=%d, fec=%d, sr=%d modulation=%d, system=%d (%s)", node->feloffrequency, inversion, tpnode->pilot, tpnode->rolloff, fec, tpnode->symbolrate, tpnode->modulation, tpnode->system, node->feshortname);
1389#endif
1390
1391        fediscard(node);
1392
1393#if DVB_API_VERSION >= 5
1394        if((ioctl(node->fd, FE_SET_PROPERTY, &cmdseq)) == -1)
1395        {
1396                perr("FE_SET_PROPERTY");
1397                return 1;
1398        }
1399#else
1400        if(ioctl(node->fd, FE_SET_FRONTEND, &tuneto) == -1)
1401        {
1402                perr("FE_SET_FRONTEND");
1403                return 1;
1404        }
1405#endif
1406
1407        return 0;
1408}
1409
1410int fetunedvbc(struct dvbdev* node, struct transponder* tpnode)
1411{
1412        if(node == NULL || tpnode == NULL)
1413        {
1414                err("NULL detect");
1415                return 1;
1416        }
1417       
1418        int fec = tpnode->fec;
1419        switch(fec)
1420        {
1421                case 0: fec = FEC_AUTO; break;
1422                case 1: fec = FEC_1_2; break;
1423                case 2: fec = FEC_2_3; break;
1424                case 3: fec = FEC_3_4; break;
1425                case 4: fec = FEC_5_6; break;
1426                case 5: fec = FEC_7_8; break;
1427                case 6: fec = FEC_8_9; break;
1428                case 7: fec = FEC_3_5; break;
1429                case 8: fec = FEC_4_5; break;
1430                case 9: fec = FEC_9_10; break;
1431                case 15: fec = FEC_NONE; break;
1432                default: fec = FEC_AUTO; break;
1433        }
1434
1435        int modulation = tpnode->modulation;
1436        switch(modulation)
1437        {
1438                case 0: modulation = QAM_AUTO; break;
1439                case 1: modulation = QAM_16; break;
1440                case 2: modulation = QAM_32; break;
1441                case 3: modulation = QAM_64; break;
1442                case 4: modulation = QAM_128; break;
1443                case 5: modulation = QAM_256; break;
1444                default: modulation = QAM_AUTO; break;
1445        }
1446
1447#if DVB_API_VERSION >= 5
1448        struct dtv_property p[8];
1449        struct dtv_properties cmdseq;
1450        cmdseq.props = p;
1451
1452        p[0].cmd = DTV_CLEAR;
1453        p[1].cmd = DTV_DELIVERY_SYSTEM, p[1].u.data = tpnode->system;
1454        p[2].cmd = DTV_FREQUENCY,       p[2].u.data = tpnode->frequency;
1455        p[3].cmd = DTV_MODULATION,      p[3].u.data = modulation;
1456        p[4].cmd = DTV_SYMBOL_RATE,     p[4].u.data = tpnode->symbolrate;
1457        p[5].cmd = DTV_INVERSION,       p[5].u.data = (fe_spectral_inversion_t) tpnode->inversion;
1458        p[6].cmd = DTV_INNER_FEC,       p[6].u.data = fec;
1459        p[7].cmd = DTV_TUNE;
1460        cmdseq.num = 8;
1461
1462        debug(200, "frequ=%d, inversion=%d, fec=%d, sr=%d, modulation=%d, system=%d (%s)", tpnode->frequency, tpnode->inversion, fec, tpnode->symbolrate, modulation, tpnode->system, node->feshortname);
1463#else
1464        struct dvb_frontend_parameters tuneto;
1465
1466        tuneto.frequency = tpnode->frequency;
1467        tuneto.inversion = tpnode->inversion;
1468        tuneto.u.qam.symbol_rate = tpnode->symbolrate;
1469        tuneto.u.qam.fec_inner = tpnode->fec;
1470        tuneto.u.qam.modulation = tpnode->modulation;
1471
1472        debug(200, "frequ=%d, inversion=%d, fec=%d, sr=%d, modulation=%d (%s)", tpnode->frequency, tpnode->inversion, fec, tpnode->symbolrate, modulation, node->feshortname);
1473#endif
1474
1475        fediscard(node);
1476
1477#if DVB_API_VERSION >= 5
1478        if((ioctl(node->fd, FE_SET_PROPERTY, &cmdseq)) == -1)
1479        {
1480                perr("FE_SET_PROPERTY");
1481                return 1;
1482        }
1483#else
1484        if(ioctl(node->fd, FE_SET_FRONTEND, &tuneto) == -1)
1485        {
1486                perr("FE_SET_FRONTEND");
1487                return 1;
1488        }
1489#endif
1490
1491        return 0;
1492}
1493
1494int fetunedvbt(struct dvbdev* node, struct transponder* tpnode)
1495{
1496        struct dvb_frontend_parameters tuneto;
1497
1498        if(node == NULL || tpnode == NULL)
1499        {
1500                err("NULL detect");
1501                return 1;
1502        }
1503       
1504        int hp = tpnode->fec; //fec = hp on DVBT
1505        switch(hp)
1506        {
1507                case 0: hp = FEC_1_2; break;
1508                case 1: hp = FEC_2_3; break;
1509                case 2: hp = FEC_3_4; break;
1510                case 3: hp = FEC_5_6; break;
1511                case 4: hp = FEC_7_8; break;
1512                case 5: hp = FEC_AUTO; break;
1513                default: hp = FEC_AUTO; break;
1514        }
1515
1516        int lp = tpnode->polarization; //polarization = lp on DVBT
1517        switch(lp)
1518        {
1519                case 0: lp = FEC_1_2; break;
1520                case 1: lp = FEC_2_3; break;
1521                case 2: lp = FEC_3_4; break;
1522                case 3: lp = FEC_5_6; break;
1523                case 4: lp = FEC_7_8; break;
1524                case 5: lp = FEC_AUTO; break;
1525                default: lp = FEC_AUTO; break;
1526        }
1527       
1528        int modulation = tpnode->modulation;
1529        switch(modulation)
1530        {
1531                case 0: modulation = QPSK; break;
1532                case 1: modulation = QAM_16; break;
1533                case 2: modulation = QAM_64; break;
1534                case 3: modulation = QAM_AUTO; break;
1535                default: modulation = QAM_AUTO; break;
1536        }
1537       
1538        int bandwidth = tpnode->symbolrate; //symbolrate = bandwidth on DVBT
1539        switch(bandwidth)
1540        {
1541                case 0: bandwidth = BANDWIDTH_8_MHZ; break;
1542                case 1: bandwidth = BANDWIDTH_7_MHZ; break;
1543                case 2: bandwidth = BANDWIDTH_6_MHZ; break;
1544                case 3: bandwidth = BANDWIDTH_AUTO; break;
1545                default: bandwidth = BANDWIDTH_AUTO; break;
1546        }
1547       
1548        int transmission = tpnode->pilot; //pilot = transmission on DVBT
1549        switch(transmission)
1550        {
1551                case 0: transmission = TRANSMISSION_MODE_2K; break;
1552                case 1: transmission = TRANSMISSION_MODE_8K; break;
1553                case 2: transmission = TRANSMISSION_MODE_AUTO; break;
1554                default: transmission = TRANSMISSION_MODE_AUTO; break;
1555        }
1556       
1557        int guardinterval = tpnode->rolloff; //rolloff = guardinterval on DVBT
1558        switch(guardinterval)
1559        {
1560                case 0: guardinterval = GUARD_INTERVAL_1_32; break;
1561                case 1: guardinterval = GUARD_INTERVAL_1_16; break;
1562                case 2: guardinterval = GUARD_INTERVAL_1_8; break;
1563                case 3: guardinterval = GUARD_INTERVAL_1_4; break;
1564                case 4: guardinterval = GUARD_INTERVAL_AUTO; break;
1565                default: guardinterval = GUARD_INTERVAL_AUTO; break;
1566        }
1567       
1568        int hierarchy = tpnode->system; //system = hierarchy on DVBT
1569        switch(guardinterval)
1570        {
1571                case 0: hierarchy = HIERARCHY_NONE;
1572                case 1: hierarchy = HIERARCHY_1;
1573                case 2: hierarchy = HIERARCHY_2;
1574                case 3: hierarchy = HIERARCHY_4;
1575                case 4: hierarchy = HIERARCHY_AUTO;
1576                default: hierarchy = HIERARCHY_AUTO; break;
1577        }
1578
1579        tuneto.frequency = tpnode->frequency;
1580        tuneto.inversion = tpnode->inversion;
1581        tuneto.u.ofdm.bandwidth = bandwidth;
1582        tuneto.u.ofdm.code_rate_HP = hp;
1583        tuneto.u.ofdm.code_rate_LP = lp;
1584        tuneto.u.ofdm.constellation = modulation;
1585        tuneto.u.ofdm.transmission_mode = transmission;
1586        tuneto.u.ofdm.guard_interval = guardinterval;
1587        tuneto.u.ofdm.hierarchy_information = hierarchy;
1588
1589        fediscard(node);
1590
1591        if(ioctl(node->fd, FE_SET_FRONTEND, &tuneto) == -1)
1592        {
1593                perr("FE_SET_FRONTEND");
1594                return 1;
1595        }
1596       
1597        return 0;
1598}
1599
1600#ifdef SIMULATE
1601int tunercount = 0;
1602#endif
1603struct dvb_frontend_info* fegetinfo(struct dvbdev* node, int fd)
1604{
1605        struct dvb_frontend_info* feinfo = NULL;
1606        int tmpfd = -1;
1607
1608        if(node != NULL)
1609                tmpfd = node->fd;
1610        else
1611                tmpfd = fd;
1612
1613        feinfo = (struct dvb_frontend_info*)malloc(sizeof(struct dvb_frontend_info));
1614        if(feinfo == NULL)
1615        {
1616                err("no mem");
1617                return NULL;
1618        }
1619
1620#ifndef SIMULATE
1621        if(ioctl(tmpfd, FE_GET_INFO, feinfo) < 0)
1622        {
1623                perr("FE_GET_INFO");
1624                free(feinfo);
1625                return NULL;
1626        }
1627#else
1628        tunercount++;
1629        if(tunercount == 1)
1630        {
1631                sprintf(feinfo->name, "%s", "Conax 7500 DVB-C");
1632                feinfo->type = FE_QAM;
1633        }
1634        else
1635        {
1636                sprintf(feinfo->name, "%s", "Conax 7500 DVB-S");
1637                feinfo->type = FE_QPSK;
1638                //feinfo->type = FE_QAM;
1639        }
1640#endif
1641        return feinfo;
1642}
1643
1644int fegetdev()
1645{
1646        int i, y, fd = -1, count = 0;
1647        char *buf = NULL, *frontenddev = NULL, *fehyprid = NULL, *tmpstr = NULL;
1648        struct dvb_frontend_info* feinfo = NULL;
1649        struct dvbdev* dvbnode = NULL;
1650
1651        frontenddev = getconfig("frontenddev", NULL);
1652        if(frontenddev == NULL)
1653        {
1654                err("NULL detect");
1655                return count;
1656        }
1657
1658        buf = malloc(MINMALLOC);
1659        if(buf == NULL)
1660        {
1661                err("no memory");
1662                return count;
1663        }
1664
1665        for(i = 0; i < MAXDVBADAPTER; i++)
1666        {
1667                for(y = 0; y < MAXFRONTENDDEV; y++)
1668                {
1669                        sprintf(buf, frontenddev, i, y);
1670                        fd = feopen(NULL, buf);
1671                        if(fd >= 0)
1672                        {
1673                                fehyprid = gethypridtunerchoicesvalue(y);
1674                                if(fehyprid != NULL)
1675                                {
1676                                        if(y < 10)
1677                                                tmpstr = ostrcat(tmpstr, "fe_0", 1, 0);
1678                                        else
1679                                                tmpstr = ostrcat(tmpstr, "fe_1", 1, 0);
1680
1681                                        tmpstr = ostrcat(tmpstr, oitoa(y), 1, 1);
1682                                        tmpstr = ostrcat(tmpstr, "_hyprid", 1, 0);
1683                                        if(getconfig(tmpstr, NULL) != NULL)
1684                                                sethypridtuner(y, getconfig(tmpstr, NULL));
1685                                        free(tmpstr), tmpstr = NULL;
1686                                }
1687                               
1688                                feinfo = fegetinfo(NULL, fd);
1689                                if(feinfo != NULL)
1690                                {
1691                                        count++;
1692                                        dvbnode = adddvbdev(buf, i, y, fd, FRONTENDDEV, feinfo, NULL, fehyprid, 0);
1693                                        if(dvbnode->feinfo->type == FE_QPSK)
1694                                                fesetvoltage(dvbnode, SEC_VOLTAGE_OFF, 15);
1695                                }
1696                        }
1697                }
1698        }
1699
1700        free(buf);
1701        return count;
1702}
1703
1704int fecreatedummy()
1705{
1706        //create dummy frontend for playback
1707        char *buf = NULL, *frontenddev = NULL;
1708        struct dvbdev* dvbnode = NULL;
1709
1710        frontenddev = getconfig("frontenddev", NULL);
1711        if(frontenddev == NULL)
1712        {
1713                err("NULL detect");
1714                return 1;
1715        }
1716
1717        buf = malloc(MINMALLOC);
1718        if(buf == NULL)
1719        {
1720                err("no memory");
1721                return 1;
1722        }
1723
1724        dvbnode = dmxgetlast(0);
1725        if(dvbnode != NULL)
1726        {
1727                sprintf(buf, frontenddev, 0, dvbnode->devnr);
1728                adddvbdev(buf, 0, dvbnode->devnr, -1, FRONTENDDEVDUMMY, NULL, NULL, NULL, 0);
1729        }
1730
1731        free(buf);
1732        return 0;
1733}
1734
1735int fegetlock(int tunernr)
1736{
1737        struct dvbdev* dvbnode = NULL;
1738        dvbnode = dvbdev;
1739
1740        while(dvbnode != NULL)
1741        {
1742                if(dvbnode->deactive == 1)
1743                {
1744                        dvbnode = dvbnode->next;
1745                        continue;
1746                }
1747                if(dvbnode->type == FRONTENDDEV && dvbnode->devnr == tunernr)
1748                {
1749                        return dvbnode->felock;
1750                }
1751                dvbnode = dvbnode->next;
1752        }
1753        return -1;
1754}
1755
1756#endif
Note: See TracBrowser for help on using the repository browser.