ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Linux-DVB/DVB.xs
Revision: 1.7
Committed: Mon Feb 25 04:53:35 2008 UTC (16 years, 2 months ago) by root
Branch: MAIN
CVS Tags: rel-1_0
Changes since 1.6: +36 -33 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.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 root 1.6 typedef int FE_fd;
13    
14 root 1.1 enum {
15 root 1.4 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 root 1.1 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 root 1.4 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 root 1.1 };
42    
43     enum {
44 root 1.4 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 root 1.1 };
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 root 1.7 //CONST (DMX_SCRAMBLING_EV),
188     //CONST (DMX_FRONTEND_EV),
189 root 1.1
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 root 1.7 //CONST (DMX_SCRAMBLING_OFF),
206     //CONST (DMX_SCRAMBLING_ON),
207 root 1.1
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 root 1.2
236 root 1.4 CONST (DT_network_name),
237     CONST (DT_service_list),
238     CONST (DT_satellite_delivery_system),
239     CONST (DT_cable_delivery_system),
240 root 1.2 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 root 1.4 CONST (DT_terrestrial_delivery_system),
248 root 1.2 CONST (DT_private_data_specifier),
249     CONST (DT_short_smoothing_buffer),
250     CONST (DT_scrambling_indicator),
251     CONST (DT_PDC),
252 root 1.1 };
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 root 1.2 #define HVS(hv,name,sv) hv_store (hv, #name, sizeof (#name) - 1, (sv), 0)
257 root 1.1
258     static void
259 root 1.3 get_parameters (HV *hv, struct dvb_frontend_parameters *p, fe_type_t type)
260 root 1.1 {
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 root 1.3 #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 root 1.1 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 root 1.5 dec_data = (u8 *)SvPVbyte (dec_sv, dec_len);
342 root 1.1 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 root 1.3 U32
380     clamp (U32 len)
381     {
382 root 1.4 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 root 1.3 }
412    
413 root 1.2 static SV *
414     text2sv (u8 *data, U32 len)
415     {
416     dSP;
417 root 1.5 SV *sv = newSVpvn ((char *)data, clamp (len));
418 root 1.2
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 root 1.3 #define DEC_T(hv, bytes, name) HVS (hv, name, text2sv (dec_data + (dec_ofs >> 3), clamp (bytes))), dec_ofs += clamp (bytes) << 3
429 root 1.5 #define DEC_S(hv, bytes, name) HVS (hv, name, newSVpvn ((char *)dec_data + (dec_ofs >> 3), clamp (bytes))), dec_ofs += clamp (bytes) << 3
430 root 1.1
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 root 1.2 U8 type, len, len2;
440     AV *av2;
441     long end, end2;
442 root 1.1
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 root 1.4 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 root 1.2 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 root 1.1 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 root 1.2 DEC_T (hv, (end - dec_ofs) >> 3, text);
559 root 1.1 break;
560    
561     case DT_short_event:
562     DEC_S (hv, 3, ISO_639_language_code);
563 root 1.2 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 root 1.1 break;
587    
588     case DT_content:
589 root 1.3 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 root 1.1 break;
605    
606 root 1.4 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 root 1.1 case DT_private_data_specifier:
635     DEC_I (hv, 32, private_data_specifier);
636     break;
637 root 1.2
638 root 1.1 default:
639 root 1.3 //fprintf (stderr, "UNKXXX %x\n", type);//D
640    
641 root 1.1 case 0:
642     case 0x80:
643     case 0x81:
644     case 0x82:
645 root 1.2 case 0x83:
646 root 1.1 case 0x84:
647     case 0x85:
648 root 1.2 case 0x8d:
649     case 0x8e:
650     case 0xb2:
651 root 1.1 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 root 1.6 frontend_info (FE_fd fd)
681 root 1.1 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 root 1.6 read_status (FE_fd fd)
708 root 1.1 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 root 1.6 read_ber (FE_fd fd)
720 root 1.1 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 root 1.6 read_snr (FE_fd fd)
731 root 1.1 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 root 1.6 signal_strength (FE_fd fd)
743 root 1.1 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 root 1.6 uncorrected_blocks (FE_fd fd)
755 root 1.1 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 root 1.3 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 root 1.1 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 root 1.3 get_parameters (hv, &p, type);
792 root 1.1 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 root 1.3 get_parameters (hv, &e.parameters, type);
808 root 1.1 RETVAL = (SV *)newRV_noinc ((SV *)hv);
809     OUTPUT:
810     RETVAL
811    
812 root 1.6 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 root 1.1 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 root 1.5 decode_set (SV *data)
939 root 1.1 CODE:
940    
941     int
942 root 1.5 decode_len ()
943 root 1.1 CODE:
944     RETVAL = (dec_ofs + 7) >> 3;
945     OUTPUT:
946     RETVAL
947    
948     U32
949 root 1.5 decode_field (int bits)
950 root 1.1
951     SV *
952 root 1.5 decode_si (SV *stream)
953 root 1.1 CODE:
954     HV *hv = newHV ();
955    
956 root 1.4 int syntax_indicator;
957 root 1.1 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 root 1.4 syntax_indicator = decode_field (1);
969     HVS (hv, section_syntax_indicator, newSViv (syntax_indicator));
970    
971 root 1.1 decode_field (1);
972     decode_field (2);
973    
974     length = decode_field (12);
975     end = dec_ofs + (length << 3);
976    
977 root 1.4 if (syntax_indicator)
978     {
979     switch (table_id)
980     {
981     case SCT_NIT:
982 root 1.7 case SCT_NIT_OTHER:
983 root 1.4 {
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 root 1.7 {
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 root 1.4
1040 root 1.7 AV *events = newAV ();
1041     HVS (hv, events, newRV_noinc ((SV *)events));
1042 root 1.4
1043 root 1.7 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 root 1.4
1050 root 1.7 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 root 1.4
1057 root 1.7 dll = dec_ofs + (decode_field (12) << 3);
1058 root 1.4
1059 root 1.7 desc = decode_descriptors (dll);
1060     HVS (ev, descriptors, newRV_noinc ((SV *)desc));
1061     }
1062 root 1.4
1063 root 1.7 decode_field (32); // skip CRC
1064     }
1065 root 1.4
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 root 1.1
1110 root 1.4 if (decode_overflow)
1111     {
1112     SvREFCNT_dec (hv);
1113     safe_sv_chop (stream, (end + 7) >> 3);
1114     XSRETURN_UNDEF;
1115     }
1116 root 1.1
1117 root 1.4 safe_sv_chop (stream, (dec_ofs + 7) >> 3);
1118 root 1.1 }
1119 root 1.4 else
1120 root 1.1 {
1121     SvREFCNT_dec (hv);
1122 root 1.4 safe_sv_chop (stream, (end + 7) >> 3);
1123 root 1.1 XSRETURN_UNDEF;
1124     }
1125    
1126     RETVAL = (SV *)newRV_noinc ((SV *)hv);
1127     OUTPUT:
1128     RETVAL
1129