source: titan/titan/frontenddev.h @ 39653

Last change on this file since 39653 was 39653, checked in by gost, 6 years ago

[titan] dm900 fix second tuner

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