- fixed dvb scan
[enigma2.git] / lib / dvb / demux.cpp
1 #include <config.h>
2 #include <stdio.h>
3 #include <fcntl.h>
4 #include <sys/ioctl.h>
5 #include <errno.h>
6 #include <unistd.h>
7
8 #if HAVE_DVB_API_VERSION < 3
9 #include <ost/dmx.h>
10 #else
11 #include <linux/dvb/dmx.h>
12 #endif
13
14 #include "crc32.h"
15
16 #include <lib/base/eerror.h>
17 #include <lib/dvb/idvb.h>
18 #include <lib/dvb/demux.h>
19 #include <lib/dvb/esection.h>
20 #include <lib/dvb/decoder.h>
21
22 eDVBDemux::eDVBDemux(int adapter, int demux): adapter(adapter), demux(demux)
23 {
24 }
25
26 eDVBDemux::~eDVBDemux()
27 {
28 }
29
30 DEFINE_REF(eDVBDemux)
31
32 RESULT eDVBDemux::createSectionReader(eMainloop *context, ePtr<iDVBSectionReader> &reader)
33 {
34         RESULT res;
35         reader = new eDVBSectionReader(this, context, res);
36         if (res)
37                 reader = 0;
38         return res;
39 }
40
41 RESULT eDVBDemux::getMPEGDecoder(ePtr<iTSMPEGDecoder> &decoder)
42 {
43         decoder = new eTSMPEGDecoder(this, 0);
44         return 0;
45 }
46
47 void eDVBSectionReader::data(int)
48 {
49         __u8 data[4096]; // max. section size
50         int r;
51         r = ::read(fd, data, 4096);
52         if(r < 0)
53         {
54                 eWarning("ERROR reading section - %m\n");
55                 return;
56         }
57         if (checkcrc)
58         {
59                         // this check should never happen unless the driver is crappy!
60                 unsigned int c;
61                 if ((c = crc32((unsigned)-1, data, r)))
62                         eFatal("crc32 failed! is %x\n", c);
63         }
64         read(data);
65 }
66
67 eDVBSectionReader::eDVBSectionReader(eDVBDemux *demux, eMainloop *context, RESULT &res): demux(demux)
68 {
69         char filename[128];
70 #if HAVE_DVB_API_VERSION < 3
71         sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
72 #else
73         sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
74 #endif
75         fd = ::open(filename, O_RDWR);
76         
77         eDebug("eDVBSectionReader has fd %d", fd);
78         
79         if (fd >= 0)
80         {
81                 notifier=new eSocketNotifier(context, fd, eSocketNotifier::Read);
82                 CONNECT(notifier->activated, eDVBSectionReader::data);
83                 res = 0;
84         } else
85         {
86                 perror(filename);
87                 res = errno;
88         }
89 }
90
91 DEFINE_REF(eDVBSectionReader)
92
93 eDVBSectionReader::~eDVBSectionReader()
94 {
95         if (notifier)
96                 delete notifier;
97         if (fd >= 0)
98                 ::close(fd);
99 }
100
101 RESULT eDVBSectionReader::start(const eDVBSectionFilterMask &mask)
102 {
103         RESULT res;
104         if (fd < 0)
105                 return -ENODEV;
106
107 #if HAVE_DVB_API_VERSION < 3
108         dmxSctFilterParams sct;
109 #else
110         dmx_sct_filter_params sct;
111 #endif
112         sct.pid     = mask.pid;
113         sct.timeout = 0;
114 #if HAVE_DVB_API_VERSION < 3
115         sct.flags   = 0;
116 #else
117         sct.flags   = DMX_IMMEDIATE_START;
118 #endif
119         if (mask.flags & eDVBSectionFilterMask::rfCRC)
120         {
121                 sct.flags |= DMX_CHECK_CRC;
122                 checkcrc = 1;
123         } else
124                 checkcrc = 0;
125         
126         memcpy(sct.filter.filter, mask.data, DMX_FILTER_SIZE);
127         memcpy(sct.filter.mask, mask.mask, DMX_FILTER_SIZE);
128 #if HAVE_DVB_API_VERSION >= 3
129         memcpy(sct.filter.mode, mask.mode, DMX_FILTER_SIZE);
130 #endif
131         
132         res = ::ioctl(fd, DMX_SET_FILTER, &sct);
133         if (!res)
134         {
135 #if HAVE_DVB_API_VERSION < 3
136                 res = ::ioctl(fd, DMX_SET_NEGFILTER_MASK, mask.mode);
137                 if (!res)
138                 {
139                         res = ::ioctl(fd, DMX_START, 0);
140                         if (!res)
141                                 active = 1;
142                 }
143 #else
144                 active = 1;
145 #endif
146         }
147         return res;
148 }
149
150 RESULT eDVBSectionReader::stop()
151 {
152         if (!active)
153                 return -1;
154         
155         ::ioctl(fd, DMX_STOP);
156         
157         return 0;
158 }
159
160 RESULT eDVBSectionReader::connectRead(const Slot1<void,const __u8*> &r, ePtr<eConnection> &conn)
161 {
162         conn = new eConnection(this, read.connect(r));
163         return 0;
164 }