1 /*
2 * Copyright (c) 2016 - Mauro Carvalho Chehab
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation version 2.1 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
17 */
18
19 #include <libudev.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <locale.h>
23 #include <unistd.h>
24 #include <string.h>
25
26 #include <config.h>
27
28 #include "dvb-fe-priv.h"
29 #include "dvb-dev-priv.h"
30
31 #ifdef ENABLE_NLS
32 # include <stdio.h>
33 # include <libintl.h>
34 # define _(string) dgettext(LIBDVBV5_DOMAIN, string)
35 #else
36 # define _(string) string
37 #endif
38
39 const char * const dev_type_names[] = {
40 "frontend", "demux", "dvr", "net", "ca", "sec", "video", "audio"
41 };
42
43 const unsigned int
44 dev_type_names_size = sizeof(dev_type_names)/sizeof(*dev_type_names);
45
free_dvb_dev(struct dvb_dev_list * dvb_dev)46 void free_dvb_dev(struct dvb_dev_list *dvb_dev)
47 {
48 if (dvb_dev->path)
49 free(dvb_dev->path);
50 if (dvb_dev->syspath)
51 free(dvb_dev->syspath);
52 if (dvb_dev->sysname)
53 free(dvb_dev->sysname);
54 if (dvb_dev->bus_addr)
55 free(dvb_dev->bus_addr);
56 if (dvb_dev->bus_id)
57 free(dvb_dev->bus_id);
58 if (dvb_dev->manufacturer)
59 free(dvb_dev->manufacturer);
60 if (dvb_dev->product)
61 free(dvb_dev->product);
62 if (dvb_dev->serial)
63 free(dvb_dev->serial);
64 }
65
dvb_dev_alloc(void)66 struct dvb_device *dvb_dev_alloc(void)
67 {
68 struct dvb_device_priv *dvb;
69 struct dvb_v5_fe_parms_priv *parms;
70
71 dvb = calloc(1, sizeof(struct dvb_device_priv));
72 if (!dvb)
73 return NULL;
74
75 dvb->d.fe_parms = dvb_fe_dummy();
76 if (!dvb->d.fe_parms) {
77 dvb_dev_free(&dvb->d);
78 return NULL;
79 }
80 parms = (void *)dvb->d.fe_parms;
81 parms->dvb = dvb;
82
83 /* Initialize it to use the local DVB devices */
84 dvb_dev_local_init(dvb);
85
86 return &dvb->d;
87 }
88
dvb_dev_free_devices(struct dvb_device_priv * dvb)89 void dvb_dev_free_devices(struct dvb_device_priv *dvb)
90 {
91 int i;
92
93 for (i = 0; i < dvb->d.num_devices; i++)
94 free_dvb_dev(&dvb->d.devices[i]);
95 free(dvb->d.devices);
96
97 dvb->d.devices = NULL;
98 dvb->d.num_devices = 0;
99 }
100
dvb_dev_free(struct dvb_device * d)101 void dvb_dev_free(struct dvb_device *d)
102 {
103 struct dvb_device_priv *dvb = (void *)d;
104 struct dvb_open_descriptor *cur, *next;
105 struct dvb_dev_ops *ops = &dvb->ops;
106
107 /* Close all devices */
108 cur = dvb->open_list.next;
109 while (cur) {
110 next = cur->next;
111 dvb_dev_close(cur);
112 cur = next;
113 }
114
115 /* Call an implementation-specific free method, if defined */
116 if (ops->free)
117 ops->free(dvb);
118
119 dvb_fe_close(dvb->d.fe_parms);
120
121 dvb_dev_free_devices(dvb);
122
123 free(dvb);
124 }
125
dvb_dev_dump_device(char * msg,struct dvb_v5_fe_parms_priv * parms,struct dvb_dev_list * dev)126 void dvb_dev_dump_device(char *msg,
127 struct dvb_v5_fe_parms_priv *parms,
128 struct dvb_dev_list *dev)
129 {
130 if (parms->p.verbose < 2)
131 return;
132
133 dvb_log(msg, dev_type_names[dev->dvb_type], dev->sysname);
134
135 if (dev->path)
136 dvb_log(_(" path: %s"), dev->path);
137 if (dev->syspath)
138 dvb_log(_(" sysfs path: %s"), dev->syspath);
139 if (dev->bus_addr)
140 dvb_log(_(" bus addr: %s"), dev->bus_addr);
141 if (dev->bus_id)
142 dvb_log(_(" bus ID: %s"), dev->bus_id);
143 if (dev->manufacturer)
144 dvb_log(_(" manufacturer: %s"), dev->manufacturer);
145 if (dev->product)
146 dvb_log(_(" product: %s"), dev->product);
147 if (dev->serial)
148 dvb_log(_(" serial: %s"), dev->serial);
149 }
150
dvb_dev_seek_by_adapter(struct dvb_device * d,unsigned int adapter,unsigned int num,enum dvb_dev_type type)151 struct dvb_dev_list *dvb_dev_seek_by_adapter(struct dvb_device *d,
152 unsigned int adapter,
153 unsigned int num,
154 enum dvb_dev_type type)
155 {
156 struct dvb_device_priv *dvb = (void *)d;
157 struct dvb_dev_ops *ops = &dvb->ops;
158
159 if (!ops->seek_by_adapter)
160 return NULL;
161
162 return ops->seek_by_adapter(dvb, adapter, num, type);
163 }
164
dvb_dev_set_logpriv(struct dvb_device * dvb,unsigned verbose,dvb_logfunc_priv logfunc_priv,void * logpriv)165 void dvb_dev_set_logpriv(struct dvb_device *dvb, unsigned verbose,
166 dvb_logfunc_priv logfunc_priv, void *logpriv)
167 {
168 struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
169
170 /* FIXME: how to get remote logs and set verbosity? */
171 parms->p.verbose = verbose;
172 parms->logpriv = logpriv;
173
174 if (logfunc_priv != NULL)
175 parms->logfunc_priv = logfunc_priv;
176 }
177
dvb_dev_set_log(struct dvb_device * dvb,unsigned verbose,dvb_logfunc logfunc)178 void dvb_dev_set_log(struct dvb_device *dvb, unsigned verbose,
179 dvb_logfunc logfunc)
180 {
181 struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
182
183 /* FIXME: how to get remote logs and set verbosity? */
184 parms->p.verbose = verbose;
185
186 if (logfunc != NULL)
187 parms->p.logfunc = logfunc;
188 }
189
dvb_dev_find(struct dvb_device * d,dvb_dev_change_t handler,void * user_priv)190 int dvb_dev_find(struct dvb_device *d, dvb_dev_change_t handler, void *user_priv)
191 {
192 struct dvb_device_priv *dvb = (void *)d;
193 struct dvb_dev_ops *ops = &dvb->ops;
194
195 if (!ops->find)
196 return -1;
197
198 return ops->find(dvb, handler, user_priv);
199 }
200
dvb_dev_stop_monitor(struct dvb_device * d)201 void dvb_dev_stop_monitor(struct dvb_device *d)
202 {
203 struct dvb_device_priv *dvb = (void *)d;
204 struct dvb_dev_ops *ops = &dvb->ops;
205
206 if (ops->stop_monitor)
207 ops->stop_monitor(dvb);
208 }
209
dvb_get_dev_info(struct dvb_device * d,const char * sysname)210 struct dvb_dev_list *dvb_get_dev_info(struct dvb_device *d,
211 const char *sysname)
212 {
213 struct dvb_device_priv *dvb = (void *)d;
214 struct dvb_dev_ops *ops = &dvb->ops;
215
216 if (!ops->get_dev_info)
217 return NULL;
218
219 return ops->get_dev_info(dvb, sysname);
220 }
221
dvb_dev_open(struct dvb_device * d,const char * sysname,int flags)222 struct dvb_open_descriptor *dvb_dev_open(struct dvb_device *d,
223 const char *sysname, int flags)
224 {
225 struct dvb_device_priv *dvb = (void *)d;
226 struct dvb_dev_ops *ops = &dvb->ops;
227
228 if (!ops->open)
229 return NULL;
230
231 return ops->open(dvb, sysname, flags);
232 }
233
dvb_dev_get_fd(struct dvb_open_descriptor * open_dev)234 int dvb_dev_get_fd(struct dvb_open_descriptor *open_dev)
235 {
236 struct dvb_device_priv *dvb = open_dev->dvb;
237 struct dvb_dev_ops *ops = &dvb->ops;
238
239 if (!ops->get_fd)
240 return -1;
241
242 return ops->get_fd(open_dev);
243 }
244
dvb_dev_close(struct dvb_open_descriptor * open_dev)245 void dvb_dev_close(struct dvb_open_descriptor *open_dev)
246 {
247 struct dvb_device_priv *dvb = open_dev->dvb;
248 struct dvb_dev_ops *ops = &dvb->ops;
249
250 if (ops->close)
251 ops->close(open_dev);
252 }
253
dvb_dev_dmx_stop(struct dvb_open_descriptor * open_dev)254 void dvb_dev_dmx_stop(struct dvb_open_descriptor *open_dev)
255 {
256 struct dvb_device_priv *dvb = open_dev->dvb;
257 struct dvb_dev_ops *ops = &dvb->ops;
258
259 if (ops->dmx_stop)
260 ops->dmx_stop(open_dev);
261 }
262
dvb_dev_set_bufsize(struct dvb_open_descriptor * open_dev,int buffersize)263 int dvb_dev_set_bufsize(struct dvb_open_descriptor *open_dev,
264 int buffersize)
265 {
266 struct dvb_device_priv *dvb = open_dev->dvb;
267 struct dvb_dev_ops *ops = &dvb->ops;
268
269 if (!ops->set_bufsize)
270 return -1;
271
272 return ops->set_bufsize(open_dev, buffersize);
273 }
274
dvb_dev_read(struct dvb_open_descriptor * open_dev,void * buf,size_t count)275 ssize_t dvb_dev_read(struct dvb_open_descriptor *open_dev,
276 void *buf, size_t count)
277 {
278 struct dvb_device_priv *dvb = open_dev->dvb;
279 struct dvb_dev_ops *ops = &dvb->ops;
280
281 if (!ops->read)
282 return -1;
283
284 return ops->read(open_dev, buf, count);
285 }
286
dvb_dev_dmx_set_pesfilter(struct dvb_open_descriptor * open_dev,int pid,dmx_pes_type_t type,dmx_output_t output,int bufsize)287 int dvb_dev_dmx_set_pesfilter(struct dvb_open_descriptor *open_dev,
288 int pid, dmx_pes_type_t type,
289 dmx_output_t output, int bufsize)
290 {
291 struct dvb_device_priv *dvb = open_dev->dvb;
292 struct dvb_dev_ops *ops = &dvb->ops;
293
294 if (!ops->dmx_set_pesfilter)
295 return -1;
296
297 return ops->dmx_set_pesfilter(open_dev, pid, type, output, bufsize);
298 }
299
dvb_dev_dmx_set_section_filter(struct dvb_open_descriptor * open_dev,int pid,unsigned filtsize,unsigned char * filter,unsigned char * mask,unsigned char * mode,unsigned int flags)300 int dvb_dev_dmx_set_section_filter(struct dvb_open_descriptor *open_dev,
301 int pid, unsigned filtsize,
302 unsigned char *filter,
303 unsigned char *mask,
304 unsigned char *mode,
305 unsigned int flags)
306 {
307 struct dvb_device_priv *dvb = open_dev->dvb;
308 struct dvb_dev_ops *ops = &dvb->ops;
309
310 if (!ops->dmx_set_section_filter)
311 return -1;
312
313 return ops->dmx_set_section_filter(open_dev, pid, filtsize, filter,
314 mask, mode, flags);
315 }
316
dvb_dev_dmx_get_pmt_pid(struct dvb_open_descriptor * open_dev,int sid)317 int dvb_dev_dmx_get_pmt_pid(struct dvb_open_descriptor *open_dev, int sid)
318 {
319 struct dvb_device_priv *dvb = open_dev->dvb;
320 struct dvb_dev_ops *ops = &dvb->ops;
321
322 if (!ops->dmx_get_pmt_pid)
323 return -1;
324
325 return ops->dmx_get_pmt_pid(open_dev, sid);
326 }
327
dvb_dev_scan(struct dvb_open_descriptor * open_dev,struct dvb_entry * entry,check_frontend_t * check_frontend,void * args,unsigned other_nit,unsigned timeout_multiply)328 struct dvb_v5_descriptors *dvb_dev_scan(struct dvb_open_descriptor *open_dev,
329 struct dvb_entry *entry,
330 check_frontend_t *check_frontend,
331 void *args,
332 unsigned other_nit,
333 unsigned timeout_multiply)
334 {
335 struct dvb_device_priv *dvb = open_dev->dvb;
336 struct dvb_dev_ops *ops = &dvb->ops;
337
338 if (!ops->scan)
339 return NULL;
340
341 return ops->scan(open_dev, entry, check_frontend, args, other_nit,
342 timeout_multiply);
343 }
344
345 /* Frontend functions that can be overriden */
346
dvb_set_sys(struct dvb_v5_fe_parms * p,fe_delivery_system_t sys)347 int dvb_set_sys(struct dvb_v5_fe_parms *p, fe_delivery_system_t sys)
348 {
349 struct dvb_v5_fe_parms_priv *parms = (void *)p;
350 struct dvb_device_priv *dvb = parms->dvb;
351
352 if (!dvb || !dvb->ops.fe_set_sys)
353 return __dvb_set_sys(p, sys);
354
355 return dvb->ops.fe_set_sys(p, sys);
356 }
357
dvb_fe_get_parms(struct dvb_v5_fe_parms * p)358 int dvb_fe_get_parms(struct dvb_v5_fe_parms *p)
359 {
360 struct dvb_v5_fe_parms_priv *parms = (void *)p;
361 struct dvb_device_priv *dvb = parms->dvb;
362
363 if (!dvb || !dvb->ops.fe_get_parms)
364 return __dvb_fe_get_parms(p);
365
366 return dvb->ops.fe_get_parms(p);
367 }
368
dvb_fe_set_parms(struct dvb_v5_fe_parms * p)369 int dvb_fe_set_parms(struct dvb_v5_fe_parms *p)
370 {
371 struct dvb_v5_fe_parms_priv *parms = (void *)p;
372 struct dvb_device_priv *dvb = parms->dvb;
373
374 if (!dvb || !dvb->ops.fe_set_parms)
375 return __dvb_fe_set_parms(p);
376
377 return dvb->ops.fe_set_parms(p);
378 }
379
dvb_fe_get_stats(struct dvb_v5_fe_parms * p)380 int dvb_fe_get_stats(struct dvb_v5_fe_parms *p)
381 {
382 struct dvb_v5_fe_parms_priv *parms = (void *)p;
383 struct dvb_device_priv *dvb = parms->dvb;
384
385 if (!dvb || !dvb->ops.fe_get_stats)
386 return __dvb_fe_get_stats(p);
387
388 return dvb->ops.fe_get_stats(p);
389 }
390