switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Socket / Protocols / DVB / DVBFrontendHandle.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Thorsten Horstmann <tho@berlios.de>
27 //   Anton Gillert <atx@berlios.de>
28
29 /** \file
30     \brief DVBFrontendHandle non-inline non-template implementation */
31
32 #include "DVBFrontendHandle.hh"
33 //#include "DVBFrontendHandle.ih"
34
35 // Custom includes
36 #include <boost/format.hpp>
37 #include <sys/socket.h>
38 #include <senf/Utils/Exception.hh>
39 #include <sys/ioctl.h>
40
41
42 //#include "DVBFrontendHandle.mpp"
43 #define prefix_
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45
46 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47 // senf::DVBFrontendHandle
48 using namespace std;
49
50 prefix_ void senf::DVBFrontendSocketProtocol::init_client(unsigned short adapter, unsigned short device, int flags)
51     const
52 {
53     string devFrontend = str( boost::format("/dev/dvb/adapter%d/frontend%d") % adapter % device);
54     int f = open(devFrontend.c_str(), flags);
55     if (f < 0)
56         SENF_THROW_SYSTEM_EXCEPTION("")<< "Could not open frontend device of DVB adapter " << devFrontend << ".";
57     fd(f);
58 }
59
60 prefix_ unsigned senf::DVBFrontendSocketProtocol::available()
61     const
62 {
63     return 0;
64 }
65
66 prefix_ bool senf::DVBFrontendSocketProtocol::eof()
67     const
68 {
69     return false;
70 }
71
72 prefix_ void senf::DVBFrontendSocketProtocol::tune(const struct dvb_frontend_parameters & frontend)
73     const
74 {
75     // tuning
76     if (::ioctl(fd(), FE_SET_FRONTEND, &frontend) )
77         SENF_THROW_SYSTEM_EXCEPTION("") << "ioctl FE_SET_FRONTEND failed. Socket should initialized with r/w permissions.";;
78 }
79
80 prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_T(unsigned int frequency,
81         fe_spectral_inversion_t inversion,
82         fe_bandwidth_t bandwidth,
83         fe_code_rate_t code_rate_HP, /* high priority stream code rate */
84         fe_code_rate_t code_rate_LP, /* low priority stream code rate */
85         fe_modulation_t constellation, /* modulation type */
86         fe_transmit_mode_t transmission_mode,
87         fe_guard_interval_t guard_interval,
88         fe_hierarchy_t hierarchy_information
89         )
90     const
91 {
92     struct dvb_ofdm_parameters ofdm; /* DVB-T Parameters */
93     struct dvb_frontend_parameters frontend;
94
95     ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
96     ::memset(&ofdm, 0, sizeof(struct dvb_ofdm_parameters));
97
98     ofdm.bandwidth = bandwidth;
99     ofdm.code_rate_HP = code_rate_HP;
100     ofdm.code_rate_LP = code_rate_LP;
101     ofdm.constellation = constellation;
102     ofdm.guard_interval = guard_interval;
103     ofdm.hierarchy_information = hierarchy_information;
104
105     frontend.frequency = frequency;
106     frontend.inversion = inversion;
107     frontend.u.ofdm = ofdm;
108
109     tune(frontend);
110
111 }
112 prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_S(unsigned int frequency,
113         fe_spectral_inversion_t inversion,
114         unsigned int symbole_rate, /* symbol rate in Symbols per second */
115         fe_code_rate_t fec_inner /* forward error correction (see above) */
116     )
117     const
118 {
119     struct dvb_qpsk_parameters qpsk; /* DVB-S Parameters*/
120     struct dvb_frontend_parameters frontend;
121
122     ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
123     ::memset(&qpsk, 0, sizeof(struct dvb_qpsk_parameters));
124
125     qpsk.symbol_rate = symbole_rate;
126     qpsk.fec_inner = fec_inner;
127
128     frontend.frequency = frequency;
129     frontend.inversion = inversion;
130     frontend.u.qpsk = qpsk;
131
132     tune(frontend);
133 }
134
135 prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_C(unsigned int frequency,
136         fe_spectral_inversion_t inversion,
137         unsigned int symbol_rate,
138         fe_code_rate_t fec_inner,
139         fe_modulation_t modulation
140         )
141 const
142 {
143     struct dvb_qam_parameters qam; /* DVB-C Parameters*/
144     struct dvb_frontend_parameters frontend;
145
146     ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
147     ::memset(&qam, 0, sizeof(struct dvb_qam_parameters));
148
149     qam.symbol_rate = symbol_rate;
150     qam.fec_inner = fec_inner;
151     qam.modulation = modulation;
152
153
154     frontend.frequency = frequency;
155     frontend.inversion = inversion;
156     frontend.u.qam = qam;
157
158     tune(frontend);
159 }
160 prefix_ void senf::DVBFrontendSocketProtocol::setNonBlock(bool on)
161     const
162 {
163    if (on)
164        ::fcntl(fd(), F_SETFL, ::fcntl(fd(), F_GETFL) | O_NONBLOCK);
165    else
166        ::fcntl(fd(), F_SETFL, ::fcntl(fd(), F_GETFL) & ~O_NONBLOCK);
167
168 }
169 prefix_ dvb_frontend_info senf::DVBFrontendSocketProtocol::getInfo()
170     const
171 {
172     struct dvb_frontend_info info;
173     ::memset(&info, 0, sizeof(struct dvb_frontend_info));
174
175     if (::ioctl(fd(), FE_GET_INFO, &info)) {
176         SENF_THROW_SYSTEM_EXCEPTION("") << "Could not read on fildescriptor.";
177     }
178     return info;
179 }
180
181 prefix_ dvb_frontend_parameters senf::DVBFrontendSocketProtocol::getFrontendParam() const {
182     struct dvb_frontend_parameters frontend_;
183
184     ::memset(&frontend_, 0, sizeof(struct dvb_frontend_parameters));
185
186     if (::ioctl(fd(), FE_GET_FRONTEND, &frontend_)) {
187         switch(errno) {
188             case EBADF:
189                 SENF_THROW_SYSTEM_EXCEPTION("fd is not a valid open file descriptor.");
190                 break;
191             case EFAULT:
192                 SENF_THROW_SYSTEM_EXCEPTION( "frontend_ points to invalid address." );
193                 break;
194             case EINVAL:
195                 SENF_THROW_SYSTEM_EXCEPTION( "Maximum supported symbol rate reached. This call may not be implemented by kernel driver!" );
196                 break;
197             default:
198                 SENF_THROW_SYSTEM_EXCEPTION("Errno: ") << errno;
199         }
200     }
201     return frontend_;
202 }
203
204 prefix_ dvb_frontend_event senf::DVBFrontendSocketProtocol::getEvent() const{
205     struct dvb_frontend_event ev ;
206
207     ::memset(&ev, 0, sizeof(struct dvb_frontend_event));
208 std::cerr<<"DVBFrontendSocketProtocol::getEvent\n";
209     if (::ioctl(fd(), FE_GET_EVENT, &ev)) {
210         switch(errno) {
211             case EBADF:
212                 SENF_THROW_SYSTEM_EXCEPTION("Could not read from frontend device, read-only access to the device is sufficient.");
213                 break;
214             case EWOULDBLOCK:
215                 SENF_THROW_SYSTEM_EXCEPTION( "No event pending and device is in nonblocking mode." );
216                 break;
217             case EINTR:
218                 // TODO: ignore EINTR. which might be caused by watchdog signals. This is possibly not the solution, but should work
219                 break;
220             default:
221                 SENF_THROW_SYSTEM_EXCEPTION("Errno: ") << errno;
222         }
223     }
224     return ev;
225 }
226
227 prefix_ int16_t senf::DVBFrontendSocketProtocol::signalStrength()
228     const
229 {
230     int16_t strength;
231     if (::ioctl(fd(), FE_READ_SIGNAL_STRENGTH, &strength) < 0)
232         SENF_THROW_SYSTEM_EXCEPTION("Could not get signal strength of DVB adapter.");
233     return strength;
234 }
235
236 prefix_ int16_t senf::DVBFrontendSocketProtocol::signalNoiseRatio()
237     const
238 {
239     int16_t snr;
240     if (::ioctl(fd(), FE_READ_SNR, &snr) < 0)
241         SENF_THROW_SYSTEM_EXCEPTION("Could not get signal-to-noise ratio of DVB adapter.");
242     return snr;
243 }
244
245 prefix_ uint32_t senf::DVBFrontendSocketProtocol::bitErrorRate()
246     const
247 {
248     uint32_t ber;
249     if (::ioctl(fd(), FE_READ_BER, &ber) < 0)
250         SENF_THROW_SYSTEM_EXCEPTION("Could not get bit error rate of DVB adapter.");
251     return ber;
252 }
253
254 prefix_ uint32_t senf::DVBFrontendSocketProtocol::uncorrectedBlocks()
255     const
256 {
257     uint32_t uncorrected_blocks;
258     if (::ioctl(fd(), FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks) < 0)
259         SENF_THROW_SYSTEM_EXCEPTION("Could not get bit error rate of DVB adapter.");
260     return uncorrected_blocks;
261 }
262
263
264 prefix_ fe_status_t senf::DVBFrontendSocketProtocol::status()
265     const
266 {
267     fe_status_t status;
268     if (::ioctl(fd(), FE_READ_STATUS, &status) < 0)
269         SENF_THROW_SYSTEM_EXCEPTION("Could not get bit error rate of DVB adapter.");
270     return status;
271 }
272
273
274 //-/////////////////////////////////////////////////////////////////////////////////////////////////
275 #undef prefix_
276 //#include "DVBFrontendHandle.mpp"
277
278 \f
279 // Local Variables:
280 // mode: c++
281 // fill-column: 100
282 // c-file-style: "senf"
283 // indent-tabs-mode: nil
284 // ispell-local-dictionary: "american"
285 // compile-command: "scons -u test"
286 // comment-column: 40
287 // End: