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