ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Linux-DVB/DVB.xs
Revision: 1.8
Committed: Mon May 24 01:52:59 2010 UTC (13 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-1_02, rel-1_03, rel-1_01, HEAD
Changes since 1.7: +1 -1 lines
Log Message:
1.01

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <string.h>
6
7 #include <linux/dvb/frontend.h>
8 #include <linux/dvb/dmx.h>
9
10 #define CONST(name) { #name, name }
11
12 typedef int FE_fd;
13
14 enum {
15 SCT_PAT = 0x00,
16 SCT_CAT = 0x01,
17 SCT_PMT = 0x02,
18 SCT_TSDT = 0x03,
19 SCT_NIT = 0x40,//TODO
20 SCT_NIT_OTHER = 0x41,
21 SCT_SDT = 0x42,
22 SCT_SDT_OTHER = 0x46,
23 SCT_BAT = 0x4a,//TODO
24 SCT_EIT_PRESENT = 0x4e,
25 SCT_EIT_PRESENT_OTHER = 0x4f,
26 SCT_EIT_SCHEDULE0 = 0x50,
27 SCT_EIT_SCHEDULE15 = 0x5f,
28 SCT_EIT_SCHEDULE_OTHER0 = 0x60,
29 SCT_EIT_SCHEDULE_OTHER15 = 0x6f,
30 SCT_TDT = 0x70,
31 SCT_RST = 0x71,
32 SCT_ST = 0x72,
33 SCT_TOT = 0x73,
34 SCT_RNT = 0x74,
35 SCT_CST = 0x75,
36 SCT_RCT = 0x76,
37 SCT_CIT = 0x77,
38 SCT_MPE = 0x78,
39 SCT_DIT = 0x7e,
40 SCT_SIT = 0x7f,
41 };
42
43 enum {
44 DT_network_name = 0x40,
45 DT_service_list = 0x41,
46 DT_satellite_delivery_system = 0x43,
47 DT_cable_delivery_system = 0x44,
48 DT_service = 0x48,
49 DT_country_availability = 0x49,
50 DT_linkage = 0x4a,
51 DT_short_event = 0x4d,
52 DT_extended_event = 0x4e, //NYI
53 DT_component = 0x50,
54 DT_content = 0x54,
55 DT_terrestrial_delivery_system = 0x5A,
56 DT_private_data_specifier = 0x5f,
57 DT_short_smoothing_buffer = 0x61, //NYI
58 DT_scrambling_indicator = 0x65, //NYI
59 DT_PDC = 0x69,
60 };
61
62 static const struct consts {
63 const char *name;
64 const long value;
65 } consts [] = {
66 CONST (FE_QPSK),
67 CONST (FE_QAM),
68 CONST (FE_OFDM),
69
70 CONST (FE_IS_STUPID),
71 CONST (FE_CAN_INVERSION_AUTO),
72 CONST (FE_CAN_FEC_1_2),
73 CONST (FE_CAN_FEC_2_3),
74 CONST (FE_CAN_FEC_3_4),
75 CONST (FE_CAN_FEC_4_5),
76 CONST (FE_CAN_FEC_5_6),
77 CONST (FE_CAN_FEC_6_7),
78 CONST (FE_CAN_FEC_7_8),
79 CONST (FE_CAN_FEC_8_9),
80 CONST (FE_CAN_FEC_AUTO),
81 CONST (FE_CAN_QPSK),
82 CONST (FE_CAN_QAM_16),
83 CONST (FE_CAN_QAM_32),
84 CONST (FE_CAN_QAM_64),
85 CONST (FE_CAN_QAM_128),
86 CONST (FE_CAN_QAM_256),
87 CONST (FE_CAN_QAM_AUTO),
88 CONST (FE_CAN_TRANSMISSION_MODE_AUTO),
89 CONST (FE_CAN_BANDWIDTH_AUTO),
90 CONST (FE_CAN_GUARD_INTERVAL_AUTO),
91 CONST (FE_CAN_HIERARCHY_AUTO),
92 CONST (FE_NEEDS_BENDING),
93 CONST (FE_CAN_RECOVER),
94 CONST (FE_CAN_MUTE_TS),
95
96 CONST (FE_HAS_SIGNAL),
97 CONST (FE_HAS_CARRIER),
98 CONST (FE_HAS_VITERBI),
99 CONST (FE_HAS_SYNC),
100 CONST (FE_HAS_LOCK),
101 CONST (FE_TIMEDOUT),
102 CONST (FE_REINIT),
103
104 CONST (INVERSION_OFF),
105 CONST (INVERSION_ON),
106 CONST (INVERSION_AUTO),
107
108 CONST (FEC_NONE),
109 CONST (FEC_1_2),
110 CONST (FEC_2_3),
111 CONST (FEC_3_4),
112 CONST (FEC_4_5),
113 CONST (FEC_5_6),
114 CONST (FEC_6_7),
115 CONST (FEC_7_8),
116 CONST (FEC_8_9),
117 CONST (FEC_AUTO),
118
119 CONST (QPSK),
120 CONST (QAM_16),
121 CONST (QAM_32),
122 CONST (QAM_64),
123 CONST (QAM_128),
124 CONST (QAM_256),
125 CONST (QAM_AUTO),
126
127 CONST (TRANSMISSION_MODE_2K),
128 CONST (TRANSMISSION_MODE_8K),
129 CONST (TRANSMISSION_MODE_AUTO),
130
131 CONST (BANDWIDTH_8_MHZ),
132 CONST (BANDWIDTH_7_MHZ),
133 CONST (BANDWIDTH_6_MHZ),
134 CONST (BANDWIDTH_AUTO),
135
136 CONST (GUARD_INTERVAL_1_32),
137 CONST (GUARD_INTERVAL_1_16),
138 CONST (GUARD_INTERVAL_1_8),
139 CONST (GUARD_INTERVAL_1_4),
140 CONST (GUARD_INTERVAL_AUTO),
141
142 CONST (HIERARCHY_NONE),
143 CONST (HIERARCHY_1),
144 CONST (HIERARCHY_2),
145 CONST (HIERARCHY_4),
146 CONST (HIERARCHY_AUTO),
147
148 CONST (DMX_OUT_DECODER),
149 CONST (DMX_OUT_TAP),
150 CONST (DMX_OUT_TS_TAP),
151
152 CONST (DMX_IN_FRONTEND),
153 CONST (DMX_IN_DVR),
154
155 CONST (DMX_PES_AUDIO0),
156 CONST (DMX_PES_VIDEO0),
157 CONST (DMX_PES_TELETEXT0),
158 CONST (DMX_PES_SUBTITLE0),
159 CONST (DMX_PES_PCR0),
160
161 CONST (DMX_PES_AUDIO1),
162 CONST (DMX_PES_VIDEO1),
163 CONST (DMX_PES_TELETEXT1),
164 CONST (DMX_PES_SUBTITLE1),
165 CONST (DMX_PES_PCR1),
166
167 CONST (DMX_PES_AUDIO2),
168 CONST (DMX_PES_VIDEO2),
169 CONST (DMX_PES_TELETEXT2),
170 CONST (DMX_PES_SUBTITLE2),
171 CONST (DMX_PES_PCR2),
172
173 CONST (DMX_PES_AUDIO3),
174 CONST (DMX_PES_VIDEO3),
175 CONST (DMX_PES_TELETEXT3),
176 CONST (DMX_PES_SUBTITLE3),
177 CONST (DMX_PES_PCR3),
178
179 CONST (DMX_PES_OTHER),
180
181 CONST (DMX_PES_AUDIO),
182 CONST (DMX_PES_VIDEO),
183 CONST (DMX_PES_TELETEXT),
184 CONST (DMX_PES_SUBTITLE),
185 CONST (DMX_PES_PCR),
186
187 //CONST (DMX_SCRAMBLING_EV),
188 //CONST (DMX_FRONTEND_EV),
189
190 CONST (DMX_CHECK_CRC),
191 CONST (DMX_ONESHOT),
192 CONST (DMX_IMMEDIATE_START),
193 CONST (DMX_KERNEL_CLIENT),
194
195 CONST (DMX_SOURCE_FRONT0),
196 CONST (DMX_SOURCE_FRONT1),
197 CONST (DMX_SOURCE_FRONT2),
198 CONST (DMX_SOURCE_FRONT3),
199
200 CONST (DMX_SOURCE_DVR0),
201 CONST (DMX_SOURCE_DVR1),
202 CONST (DMX_SOURCE_DVR2),
203 CONST (DMX_SOURCE_DVR3),
204
205 //CONST (DMX_SCRAMBLING_OFF),
206 //CONST (DMX_SCRAMBLING_ON),
207
208 // constants defined by this file
209 CONST (SCT_PAT),
210 CONST (SCT_CAT),
211 CONST (SCT_PMT),
212 CONST (SCT_TSDT),
213 CONST (SCT_NIT),
214 CONST (SCT_NIT_OTHER),
215 CONST (SCT_SDT),
216 CONST (SCT_SDT_OTHER),
217 CONST (SCT_BAT),
218 CONST (SCT_EIT_PRESENT),
219 CONST (SCT_EIT_PRESENT_OTHER),
220 CONST (SCT_EIT_SCHEDULE0),
221 CONST (SCT_EIT_SCHEDULE15),
222 CONST (SCT_EIT_SCHEDULE_OTHER0),
223 CONST (SCT_EIT_SCHEDULE_OTHER15),
224 CONST (SCT_TDT),
225 CONST (SCT_RST),
226 CONST (SCT_ST),
227 CONST (SCT_TOT),
228 CONST (SCT_RNT),
229 CONST (SCT_CST),
230 CONST (SCT_RCT),
231 CONST (SCT_CIT),
232 CONST (SCT_MPE),
233 CONST (SCT_DIT),
234 CONST (SCT_SIT),
235
236 CONST (DT_network_name),
237 CONST (DT_service_list),
238 CONST (DT_satellite_delivery_system),
239 CONST (DT_cable_delivery_system),
240 CONST (DT_service),
241 CONST (DT_country_availability),
242 CONST (DT_linkage),
243 CONST (DT_short_event),
244 CONST (DT_extended_event),
245 CONST (DT_component),
246 CONST (DT_content),
247 CONST (DT_terrestrial_delivery_system),
248 CONST (DT_private_data_specifier),
249 CONST (DT_short_smoothing_buffer),
250 CONST (DT_scrambling_indicator),
251 CONST (DT_PDC),
252 };
253
254 #define HVS_S(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSVpv (struct.member, 0), 0)
255 #define HVS_I(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSViv (struct.member), 0)
256 #define HVS(hv,name,sv) hv_store (hv, #name, sizeof (#name) - 1, (sv), 0)
257
258 static void
259 get_parameters (HV *hv, struct dvb_frontend_parameters *p, fe_type_t type)
260 {
261 HVS_I (hv, (*p), frequency);
262 HVS_I (hv, (*p), inversion);
263
264 switch (type)
265 {
266 case FE_QPSK:
267 HVS_I (hv, (*p).u.qpsk, symbol_rate);
268 HVS_I (hv, (*p).u.qpsk, fec_inner);
269 break;
270
271 case FE_QAM:
272 HVS_I (hv, (*p).u.qam, symbol_rate);
273 HVS_I (hv, (*p).u.qam, fec_inner);
274 HVS_I (hv, (*p).u.qam, modulation);
275 break;
276
277 case FE_OFDM:
278 HVS_I (hv, (*p).u.ofdm, bandwidth);
279 HVS_I (hv, (*p).u.ofdm, code_rate_HP);
280 HVS_I (hv, (*p).u.ofdm, code_rate_LP);
281 HVS_I (hv, (*p).u.ofdm, constellation);
282 HVS_I (hv, (*p).u.ofdm, transmission_mode);
283 break;
284 }
285 }
286
287 #define HVF_I(hv,struct,member) \
288 if (v = hv_fetch (hv, #member, sizeof (#member) - 1, 0)) \
289 struct.member = SvIV (*v); \
290 else \
291 croak ("required hash key '%s' not specified", #member);
292
293 static void
294 set_parameters (HV *hv, struct dvb_frontend_parameters *p, fe_type_t type)
295 {
296 SV **v;
297
298 HVF_I (hv, (*p), frequency);
299 HVF_I (hv, (*p), inversion);
300
301 switch (type)
302 {
303 case FE_QPSK:
304 HVF_I (hv, (*p).u.qpsk, symbol_rate);
305 HVF_I (hv, (*p).u.qpsk, fec_inner);
306 break;
307
308 case FE_QAM:
309 HVF_I (hv, (*p).u.qam, symbol_rate);
310 HVF_I (hv, (*p).u.qam, fec_inner);
311 HVF_I (hv, (*p).u.qam, modulation);
312 break;
313
314 case FE_OFDM:
315 HVF_I (hv, (*p).u.ofdm, bandwidth);
316 HVF_I (hv, (*p).u.ofdm, code_rate_HP);
317 HVF_I (hv, (*p).u.ofdm, code_rate_LP);
318 HVF_I (hv, (*p).u.ofdm, constellation);
319 HVF_I (hv, (*p).u.ofdm, transmission_mode);
320 break;
321 }
322 }
323
324 typedef unsigned char u8;
325
326 static SV *dec_sv;
327 static u8 *dec_data;
328 static long dec_ofs, dec_len8;
329 static U32 dec_field;
330 STRLEN dec_len;
331
332 #define decode_overflow (dec_ofs > dec_len8)
333
334 static void
335 decode_set (SV *data)
336 {
337 if (dec_sv)
338 SvREFCNT_dec (dec_sv);
339
340 dec_sv = newSVsv (data);
341 dec_data = (u8 *)SvPVbyte (dec_sv, dec_len);
342 dec_ofs = 0;
343 dec_len8 = dec_len << 3;
344 }
345
346 static U32
347 decode_field (int bits)
348 {
349 u8 *p = dec_data + (dec_ofs >> 3);
350 int frac = 8 - (dec_ofs & 7);
351 dec_ofs += bits;
352
353 if (decode_overflow)
354 return dec_field = 0;
355
356 U32 r = *p++;
357
358 r &= (1UL << frac) - 1;
359
360 if (bits < frac)
361 r >>= (frac - bits);
362 else
363 {
364 bits -= frac;
365
366 while (bits >= 8)
367 {
368 r = (r << 8) | *p++;
369 bits -= 8;
370 }
371
372 if (bits > 0)
373 r = (r << bits) | (*p >> (8 - bits));
374 }
375
376 return dec_field = r;
377 }
378
379 U32
380 clamp (U32 len)
381 {
382 return len < 4096
383 && len <= dec_len8 - (dec_ofs >> 3) + 1 /* +1 to detect overflows */
384 ? len : 0;
385 }
386
387 /* works on SvPOK strings ONLY */
388 void
389 safe_sv_chop (SV *sv, STRLEN count)
390 {
391 if ((U32)count >= (U32)SvCUR (sv))
392 SvCUR_set (sv, 0);
393 else
394 sv_chop (sv, SvPVX (sv) + count);
395 }
396
397 U32
398 bcd_to_int (U32 bcd_number)
399 {
400 U32 result = 0;
401 U32 multiplicator = 1;
402
403 while (bcd_number != 0)
404 {
405 result += (bcd_number & 0x0f) * multiplicator;
406 bcd_number >>= 4;
407 multiplicator *= 10;
408 }
409
410 return result;
411 }
412
413 static SV *
414 text2sv (u8 *data, U32 len)
415 {
416 dSP;
417 SV *sv = newSVpvn ((char *)data, clamp (len));
418
419 PUSHMARK (SP);
420 XPUSHs (sv);
421 PUTBACK;
422 call_pv ("Linux::DVB::Decode::text", G_VOID);
423
424 return sv;
425 }
426
427 #define DEC_I(hv, bits, name) HVS (hv, name, newSViv (decode_field (bits)))
428 #define DEC_T(hv, bytes, name) HVS (hv, name, text2sv (dec_data + (dec_ofs >> 3), clamp (bytes))), dec_ofs += clamp (bytes) << 3
429 #define DEC_S(hv, bytes, name) HVS (hv, name, newSVpvn ((char *)dec_data + (dec_ofs >> 3), clamp (bytes))), dec_ofs += clamp (bytes) << 3
430
431 static AV *
432 decode_descriptors (long end)
433 {
434 AV *av = newAV ();
435
436 while (dec_ofs < end)
437 {
438 HV *hv = newHV ();
439 U8 type, len, len2;
440 AV *av2;
441 long end, end2;
442
443 av_push (av, newRV_noinc ((SV *)hv));
444
445 DEC_I (hv, 8, type);
446 type = dec_field;
447 len = decode_field (8);
448 end = dec_ofs + (len << 3);
449
450 if (end > dec_len8)
451 return av;
452
453 switch (type)
454 {
455 case DT_network_name:
456 DEC_T (hv, (end - dec_ofs) >> 3, network_name);
457 break;
458
459 case DT_service_list:
460 {
461 AV *services = newAV ();
462 HVS (hv, services, newRV_noinc ((SV *)services));
463
464 while (dec_ofs < end)
465 {
466 HV *sv = newHV ();
467 av_push (services, newRV_noinc ((SV *)sv));
468
469 DEC_I (sv, 16, service_id);
470 DEC_I (sv, 8, service_type);
471
472 }
473 }
474
475 break;
476
477 case DT_satellite_delivery_system:
478 HVS (hv, frequency, newSVuv (bcd_to_int (decode_field (32))));
479 HVS (hv, orbital_position, newSVnv (bcd_to_int (decode_field (32)) / 10));
480 DEC_I (hv, 1, west_east_flag);
481 DEC_I (hv, 2, polarization);
482 DEC_I (hv, 5, modulation);
483 HVS (hv, symbol_rate, newSVuv (bcd_to_int (decode_field (28))));
484 DEC_I (hv, 4, fec_inner);
485 break;
486
487 case DT_cable_delivery_system:
488 {
489 I16 qam_modulation = -1;
490
491 HVS (hv, frequency, newSVuv (bcd_to_int (decode_field (32))));
492 decode_field (12); // reserved
493 DEC_I (hv, 4, fec_outer);
494
495 DEC_I (hv, 8, modulation);
496
497 if (dec_field >= 1 && dec_field <= 5)
498 qam_modulation = 1 << dec_field + 3;
499
500 HVS (hv, modulation_qam, newSViv (qam_modulation));
501
502 HVS (hv, symbol_rate, newSVuv (bcd_to_int (decode_field (28))));
503 DEC_I (hv, 4, fec_inner);
504
505 break;
506 }
507
508 case DT_service:
509 DEC_I (hv, 8, service_type);
510 len2 = decode_field (8); DEC_T (hv, len2, service_provider_name);
511 len2 = decode_field (8); DEC_T (hv, len2, service_name);
512 break;
513
514 case DT_country_availability:
515 DEC_I (hv, 1, country_availability_flag);
516 decode_field (7);
517
518 DEC_S (hv, (end - dec_ofs) >> 3, private_data);
519 //while (dec_ofs + 24 <= end)
520 // av_push (av,
521 break;
522
523 case DT_linkage:
524 DEC_I (hv, 16, transport_stream_id);
525 DEC_I (hv, 16, original_network_id);
526 DEC_I (hv, 16, service_id);
527 DEC_I (hv, 8, linkage_type);
528
529 if (dec_field == 8)
530 {
531 U32 hot, org;
532
533 DEC_I (hv, 8, hand_over_type); hot = dec_field;
534 decode_field (3);
535 DEC_I (hv, 1, origin_type); org = dec_field;
536
537 if (hot > 0x00 && hot < 0x04)
538 DEC_I (hv, 16, network_id);
539
540 if (org == 0)
541 DEC_I (hv, 16, initial_service_id);
542 }
543
544 DEC_S (hv, (end - dec_ofs) >> 3, private_data);
545 break;
546
547 case DT_PDC:
548 decode_field (4);
549 DEC_I (hv, 20, programme_identification_label);
550 break;
551
552 case DT_component:
553 decode_field (4);
554 DEC_I (hv, 4, stream_content);
555 DEC_I (hv, 8, component_type);
556 DEC_I (hv, 8, component_tag);
557 DEC_S (hv, 3, ISO_639_language_code);
558 DEC_T (hv, (end - dec_ofs) >> 3, text);
559 break;
560
561 case DT_short_event:
562 DEC_S (hv, 3, ISO_639_language_code);
563 len2 = decode_field (8); DEC_T (hv, len2, event_name);
564 len2 = decode_field (8); DEC_T (hv, len2, text);
565 break;
566
567 case DT_extended_event:
568 DEC_I (hv, 4, descriptor_number);
569 DEC_I (hv, 4, last_descriptor_number);
570 DEC_S (hv, 3, ISO_639_language_code);
571
572 len2 = decode_field (8); end2 = dec_ofs + (len2 << 3);
573 av2 = newAV ();
574 HVS (hv, items, newRV_noinc ((SV *)av2));
575
576 while (dec_ofs < end2)
577 {
578 AV *av3 = newAV ();
579 len2 = decode_field (8); av_push (av3, text2sv (dec_data + (dec_ofs >> 3), len2)), dec_ofs += len << 3;
580 len2 = decode_field (8); av_push (av3, text2sv (dec_data + (dec_ofs >> 3), len2)), dec_ofs += len << 3;
581
582 av_push (av2, newRV_noinc ((SV *)av3));
583 }
584
585 len2 = decode_field (8); DEC_T (hv, len2, text);
586 break;
587
588 case DT_content:
589 av2 = newAV ();
590 HVS (hv, items, newRV_noinc ((SV *)av2));
591
592 while (dec_ofs < end)
593 {
594 HV *ev = newHV ();
595
596 DEC_I (ev, 4, content_nibble_level_1);
597 DEC_I (ev, 4, content_nibble_level_2);
598 DEC_I (ev, 4, user_nibble_1);
599 DEC_I (ev, 4, user_nibble_2);
600
601 av_push (av2, newRV_noinc ((SV *)ev));
602 }
603
604 break;
605
606 case DT_terrestrial_delivery_system:
607 {
608 I8 bandwidth_mhz = -1;
609
610 HVS (hv, centre_frequency, newSVuv (decode_field (32) * 10));
611
612 DEC_I (hv, 3, bandwidth);
613
614 if (dec_field <= 3)
615 bandwidth_mhz = 8 - dec_field;
616
617 HVS (hv, bandwidth_mhz, newSViv (bandwidth_mhz));
618
619 DEC_I (hv, 1, priority);
620 DEC_I (hv, 1, time_slicing_indicator);
621 DEC_I (hv, 1, mpe_fec_indicator);
622 decode_field (2); // reserved
623 DEC_I (hv, 2, constellation);
624 DEC_I (hv, 3, hierarchy_information);
625 DEC_I (hv, 3, code_rate_hp_stream);
626 DEC_I (hv, 3, code_rate_lp_stream);
627 DEC_I (hv, 2, guard_interval);
628 DEC_I (hv, 2, transmission_mode);
629 DEC_I (hv, 1, other_frequency_use);
630 decode_field (32);
631 }
632 break;
633
634 case DT_private_data_specifier:
635 DEC_I (hv, 32, private_data_specifier);
636 break;
637
638 default:
639 //fprintf (stderr, "UNKXXX %x\n", type);//D
640
641 case 0:
642 case 0x80:
643 case 0x81:
644 case 0x82:
645 case 0x83:
646 case 0x84:
647 case 0x85:
648 case 0x8d:
649 case 0x8e:
650 case 0xb2:
651 DEC_S (hv, len, raw_data);
652 break;
653 }
654
655 dec_ofs = end; // re-sync, in case of problems
656 }
657
658 return av;
659 }
660
661 MODULE = Linux::DVB PACKAGE = Linux::DVB
662
663 PROTOTYPES: DISABLE
664
665 void
666 _consts ()
667 PPCODE:
668 const struct consts *c;
669 for (c = consts;
670 c < consts + sizeof (consts) / sizeof (consts[0]);
671 c++)
672 {
673 XPUSHs (sv_2mortal (newSVpv (c->name, 0)));
674 XPUSHs (sv_2mortal (newSViv (c->value)));
675 }
676
677 MODULE = Linux::DVB PACKAGE = Linux::DVB::Frontend
678
679 SV *
680 frontend_info (FE_fd fd)
681 CODE:
682 struct dvb_frontend_info fi;
683 HV *hv;
684
685 if (ioctl (fd, FE_GET_INFO, &fi) < 0)
686 XSRETURN_UNDEF;
687
688 hv = newHV ();
689 HVS_S (hv, fi, name);
690 HVS_I (hv, fi, type);
691 HVS_I (hv, fi, type);
692 HVS_I (hv, fi, frequency_min);
693 HVS_I (hv, fi, frequency_max);
694 HVS_I (hv, fi, frequency_stepsize);
695 HVS_I (hv, fi, frequency_tolerance);
696 HVS_I (hv, fi, symbol_rate_min);
697 HVS_I (hv, fi, symbol_rate_max);
698 HVS_I (hv, fi, symbol_rate_tolerance);
699 HVS_I (hv, fi, notifier_delay);
700 HVS_I (hv, fi, caps);
701
702 RETVAL = (SV *)newRV_noinc ((SV *)hv);
703 OUTPUT:
704 RETVAL
705
706 long
707 read_status (FE_fd fd)
708 CODE:
709 fe_status_t st;
710
711 if (ioctl (fd, FE_READ_STATUS, &st) < 0)
712 XSRETURN_UNDEF;
713
714 RETVAL = st;
715 OUTPUT:
716 RETVAL
717
718 U32
719 read_ber (FE_fd fd)
720 CODE:
721 uint32_t ber;
722 if (ioctl (fd, FE_READ_BER, &ber) < 0)
723 XSRETURN_UNDEF;
724
725 RETVAL = ber;
726 OUTPUT:
727 RETVAL
728
729 U32
730 read_snr (FE_fd fd)
731 CODE:
732 uint32_t ber;
733 if (ioctl (fd, FE_READ_SNR, &ber) < 0)
734 XSRETURN_UNDEF;
735
736 RETVAL = ber;
737 OUTPUT:
738 RETVAL
739
740
741 I16
742 signal_strength (FE_fd fd)
743 CODE:
744 int16_t st;
745 if (ioctl (fd, FE_READ_SIGNAL_STRENGTH, &st) < 0)
746 XSRETURN_UNDEF;
747
748 RETVAL = st;
749 OUTPUT:
750 RETVAL
751
752
753 U32
754 uncorrected_blocks (FE_fd fd)
755 CODE:
756 uint32_t ubl;
757 if (ioctl (fd, FE_READ_UNCORRECTED_BLOCKS, &ubl) < 0)
758 XSRETURN_UNDEF;
759
760 RETVAL = ubl;
761 OUTPUT:
762 RETVAL
763
764 int
765 _set (int fd, SV *parameters, int type)
766 CODE:
767 struct dvb_frontend_parameters p;
768
769 if (!SvROK (parameters) || SvTYPE (SvRV (parameters)) != SVt_PVHV)
770 croak ("Linux::DVB::Frontend::set requires a hash as argument");
771
772 set_parameters ((HV *)SvRV (parameters), &p, type);
773
774 if (ioctl (fd, FE_SET_FRONTEND, &p) < 0)
775 XSRETURN_UNDEF;
776
777 RETVAL = 1;
778 OUTPUT:
779 RETVAL
780
781 SV *
782 _get (int fd, int type)
783 CODE:
784 struct dvb_frontend_parameters p;
785 HV *hv;
786
787 if (ioctl (fd, FE_GET_FRONTEND, &p) < 0)
788 XSRETURN_UNDEF;
789
790 hv = newHV ();
791 get_parameters (hv, &p, type);
792 RETVAL = (SV *)newRV_noinc ((SV *)hv);
793 OUTPUT:
794 RETVAL
795
796 SV *
797 _event (int fd, int type)
798 CODE:
799 struct dvb_frontend_event e;
800 HV *hv;
801
802 if (ioctl (fd, FE_GET_EVENT, &e) < 0)
803 XSRETURN_UNDEF;
804
805 hv = newHV ();
806 HVS_I (hv, e, status);
807 get_parameters (hv, &e.parameters, type);
808 RETVAL = (SV *)newRV_noinc ((SV *)hv);
809 OUTPUT:
810 RETVAL
811
812 int
813 diseqc_reset_overload (FE_fd fd)
814 CODE:
815 RETVAL = !!ioctl (fd, FE_DISEQC_RESET_OVERLOAD);
816 OUTPUT:
817 RETVAL
818
819 int
820 diseqc_voltage (FE_fd fd, int volts)
821 CODE:
822 RETVAL = !!ioctl (fd, FE_SET_VOLTAGE, volts == 18
823 ? SEC_VOLTAGE_18
824 : SEC_VOLTAGE_13);
825 OUTPUT:
826 RETVAL
827
828 int
829 diseqc_tone (FE_fd fd, int on)
830 CODE:
831 RETVAL = !!ioctl (fd, FE_SET_TONE, on ? SEC_TONE_ON : SEC_TONE_OFF);
832 OUTPUT:
833 RETVAL
834
835 int
836 diseqc_send_burst (FE_fd fd, int type)
837 CODE:
838 RETVAL = !!ioctl (fd, FE_DISEQC_SEND_BURST, type ? SEC_MINI_B : SEC_MINI_A);
839 OUTPUT:
840 RETVAL
841
842 int
843 diseqc_cmd (FE_fd fd, SV *command_)
844 CODE:
845 {
846 STRLEN len;
847 char *command = SvPVbyte (command_, len);
848 struct dvb_diseqc_master_cmd cmd;
849
850 memcpy (cmd.msg, command, len);
851 cmd.msg_len = len;
852 RETVAL = !!ioctl (fd, FE_DISEQC_SEND_MASTER_CMD, &cmd);
853 }
854 OUTPUT:
855 RETVAL
856
857 SV *
858 diseqc_reply (FE_fd fd, int timeout_ms)
859 CODE:
860 {
861 struct dvb_diseqc_slave_reply rep;
862 rep.timeout = timeout_ms;
863
864 if (!!ioctl (fd, FE_DISEQC_RECV_SLAVE_REPLY, &rep))
865 RETVAL = newSVpvn ((char *)rep.msg, rep.msg_len);
866 else
867 RETVAL = &PL_sv_undef;
868 }
869 OUTPUT:
870 RETVAL
871
872 MODULE = Linux::DVB PACKAGE = Linux::DVB::Demux
873
874 int
875 _start (int fd)
876 ALIAS:
877 _stop = 1
878 CODE:
879 if (ioctl (fd, ix ? DMX_STOP : DMX_START, 0) < 0)
880 XSRETURN_UNDEF;
881
882 RETVAL = 1;
883 OUTPUT:
884 RETVAL
885
886 int
887 _filter (int fd, U16 pid, SV *filter, SV *mask, U32 timeout = 0, U32 flags = DMX_CHECK_CRC)
888 CODE:
889 struct dmx_sct_filter_params p;
890 STRLEN l;
891 char *s;
892
893 memset (&p.filter, 0, sizeof (p.filter));
894
895 p.pid = pid;
896 s = SvPVbyte (filter, l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.filter, s, l);
897 s = SvPVbyte (mask , l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.mask , s, l);
898 p.timeout = timeout;
899 p.flags = flags;
900 if (ioctl (fd, DMX_SET_FILTER, &p) < 0)
901 XSRETURN_UNDEF;
902
903 RETVAL = 1;
904 OUTPUT:
905 RETVAL
906
907 int
908 _pes_filter (int fd, U16 pid, long input, long output, long type, U32 flags = 0)
909 CODE:
910 struct dmx_pes_filter_params p;
911
912 p.pid = pid;
913 p.input = input;
914 p.output = output;
915 p.pes_type = type;
916 p.flags = flags;
917 if (ioctl (fd, DMX_SET_PES_FILTER, &p) < 0)
918 XSRETURN_UNDEF;
919
920 RETVAL = 1;
921 OUTPUT:
922 RETVAL
923
924 int
925 _buffer (int fd, unsigned long size)
926 CODE:
927
928 if (ioctl (fd, DMX_SET_BUFFER_SIZE, size) < 0)
929 XSRETURN_UNDEF;
930
931 RETVAL = 1;
932 OUTPUT:
933 RETVAL
934
935 MODULE = Linux::DVB PACKAGE = Linux::DVB::Decode PREFIX = decode_
936
937 void
938 decode_set (SV *data)
939 CODE:
940
941 int
942 decode_len ()
943 CODE:
944 RETVAL = (dec_ofs + 7) >> 3;
945 OUTPUT:
946 RETVAL
947
948 U32
949 decode_field (int bits)
950
951 SV *
952 decode_si (SV *stream)
953 CODE:
954 HV *hv = newHV ();
955
956 int syntax_indicator;
957 U8 table_id;
958 U16 length;
959 long end;
960
961 decode_set (stream);
962
963 do {
964 DEC_I (hv, 8, table_id);
965 table_id = dec_field;
966 } while (table_id == 0xff);
967
968 syntax_indicator = decode_field (1);
969 HVS (hv, section_syntax_indicator, newSViv (syntax_indicator));
970
971 decode_field (1);
972 decode_field (2);
973
974 length = decode_field (12);
975 end = dec_ofs + (length << 3);
976
977 if (syntax_indicator)
978 {
979 switch (table_id)
980 {
981 case SCT_NIT:
982 case SCT_NIT_OTHER:
983 {
984 U16 descriptor_end_offset;
985
986 DEC_I (hv, 16, network_id);
987 decode_field (2); // reserved
988 DEC_I (hv, 5, version_number);
989 DEC_I (hv, 1, current_next_indicator);
990 DEC_I (hv, 8, section_number);
991 DEC_I (hv, 8, last_section_number);
992 decode_field (4); // reserved
993
994 AV *desc;
995 descriptor_end_offset = dec_ofs + (decode_field (12) << 3);
996 desc = decode_descriptors (descriptor_end_offset);
997 HVS (hv,network_descriptors, newRV_noinc ((SV *)desc));
998
999 decode_field (4); //reserved
1000 decode_field (12); // Skip length, we read until the end
1001
1002 AV *events = newAV ();
1003 HVS (hv, events, newRV_noinc ((SV *)events));
1004 while (end - dec_ofs > 32)
1005 {
1006 long dll;
1007 HV *ev = newHV ();
1008 av_push (events, newRV_noinc ((SV *)ev));
1009
1010 DEC_I (ev, 16, transport_stream_id);
1011 DEC_I (ev, 16, original_network_id);
1012 decode_field (4);
1013
1014 dll = dec_ofs + (decode_field (12) << 3);
1015 desc = decode_descriptors (dll);
1016 HVS (ev, descriptors, newRV_noinc ((SV *)desc));
1017 }
1018
1019 decode_field (32); // skip CRC
1020 }
1021
1022 break;
1023
1024 case SCT_EIT_PRESENT:
1025 case SCT_EIT_PRESENT_OTHER:
1026 case SCT_EIT_SCHEDULE0...SCT_EIT_SCHEDULE15: //GCC
1027 case SCT_EIT_SCHEDULE_OTHER0...SCT_EIT_SCHEDULE_OTHER15: //GCC
1028 {
1029 DEC_I (hv, 16, service_id);
1030 decode_field (2);
1031 DEC_I (hv, 5, version_number);
1032 DEC_I (hv, 1, current_next_indicator);
1033 DEC_I (hv, 8, section_number);
1034 DEC_I (hv, 8, last_section_number);
1035 DEC_I (hv, 16, transport_stream_id);
1036 DEC_I (hv, 16, original_network_id);
1037 DEC_I (hv, 8, segment_last_section_number);
1038 DEC_I (hv, 8, last_table_id);
1039
1040 AV *events = newAV ();
1041 HVS (hv, events, newRV_noinc ((SV *)events));
1042
1043 while (end - dec_ofs > 32)
1044 {
1045 long dll;
1046 AV *desc;
1047 HV *ev = newHV ();
1048 av_push (events, newRV_noinc ((SV *)ev));
1049
1050 DEC_I (ev, 16, event_id);
1051 DEC_I (ev, 16, start_time_mjd);
1052 DEC_I (ev, 24, start_time_hms);
1053 DEC_I (ev, 24, duration);
1054 DEC_I (ev, 3, running_status);
1055 DEC_I (ev, 1, free_CA_mode);
1056
1057 dll = dec_ofs + (decode_field (12) << 3);
1058
1059 desc = decode_descriptors (dll);
1060 HVS (ev, descriptors, newRV_noinc ((SV *)desc));
1061 }
1062
1063 decode_field (32); // skip CRC
1064 }
1065
1066 break;
1067
1068 case SCT_SDT:
1069 case SCT_SDT_OTHER:
1070 DEC_I (hv, 16, transport_stream_id);
1071 decode_field (2);
1072 DEC_I (hv, 5, version_number);
1073 DEC_I (hv, 1, current_next_indicator);
1074 DEC_I (hv, 8, section_number);
1075 DEC_I (hv, 8, last_section_number);
1076 DEC_I (hv, 16, original_network_id);
1077 decode_field (8);
1078
1079 AV *services = newAV ();
1080 HVS (hv, services, newRV_noinc ((SV *)services));
1081
1082 while (end - dec_ofs > 32)
1083 {
1084 HV *ev = newHV ();
1085 U32 dll;
1086 AV *desc;
1087 av_push (services, newRV_noinc ((SV *)ev));
1088
1089 DEC_I (ev, 16, service_id);
1090 decode_field (6);
1091 DEC_I (ev, 1, EIT_schedule_flags);
1092 DEC_I (ev, 1, EIT_present_following_flag);
1093 DEC_I (ev, 3, running_status);
1094 DEC_I (ev, 1, free_CA_mode);
1095
1096 dll = dec_ofs + (decode_field (12) << 3);
1097
1098 desc = decode_descriptors (dll);
1099 HVS (ev, descriptors, newRV_noinc ((SV *)desc));
1100 }
1101
1102 decode_field (32); // skip CRC
1103 break;
1104
1105 default:
1106 DEC_S (hv, length, raw_data);
1107 break;
1108 }
1109
1110 if (decode_overflow)
1111 {
1112 SvREFCNT_dec (hv);
1113 safe_sv_chop (stream, (end + 7) >> 3);
1114 XSRETURN_UNDEF;
1115 }
1116
1117 safe_sv_chop (stream, (dec_ofs + 7) >> 3);
1118 }
1119 else
1120 {
1121 SvREFCNT_dec (hv);
1122 safe_sv_chop (stream, (end + 7) >> 3);
1123 XSRETURN_UNDEF;
1124 }
1125
1126 RETVAL = (SV *)newRV_noinc ((SV *)hv);
1127 OUTPUT:
1128 RETVAL
1129