ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Linux-DVB/DVB.xs
Revision: 1.1
Committed: Mon Sep 6 06:25:12 2004 UTC (19 years, 8 months ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

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 enum {
13 SCT_PAT = 0x00,
14 SCT_CAT = 0x01,
15 SCT_PMT = 0x02,
16 SCT_TSDT = 0x03,
17 SCT_NIT = 0x40,
18 SCT_NIT_OTHER = 0x41,
19 SCT_SDT = 0x42,
20 SCT_SDT_OTHER = 0x46,
21 SCT_BAT = 0x4a,
22 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 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 };
40
41 enum {
42 DT_short_event = 0x4d,
43 DT_extended_event = 0x4e,
44 DT_component = 0x50,
45 DT_content = 0x54,
46 DT_private_data_specifier = 0x5f,
47 DT_short_smoothing_buffer = 0x61, //NYI
48 DT_scrambling_indicator = 0x65, //NYI
49 DT_PDC = 0x69,
50 };
51
52 static const struct consts {
53 const char *name;
54 const long value;
55 } consts [] = {
56 CONST (FE_QPSK),
57 CONST (FE_QAM),
58 CONST (FE_OFDM),
59
60 CONST (FE_IS_STUPID),
61 CONST (FE_CAN_INVERSION_AUTO),
62 CONST (FE_CAN_FEC_1_2),
63 CONST (FE_CAN_FEC_2_3),
64 CONST (FE_CAN_FEC_3_4),
65 CONST (FE_CAN_FEC_4_5),
66 CONST (FE_CAN_FEC_5_6),
67 CONST (FE_CAN_FEC_6_7),
68 CONST (FE_CAN_FEC_7_8),
69 CONST (FE_CAN_FEC_8_9),
70 CONST (FE_CAN_FEC_AUTO),
71 CONST (FE_CAN_QPSK),
72 CONST (FE_CAN_QAM_16),
73 CONST (FE_CAN_QAM_32),
74 CONST (FE_CAN_QAM_64),
75 CONST (FE_CAN_QAM_128),
76 CONST (FE_CAN_QAM_256),
77 CONST (FE_CAN_QAM_AUTO),
78 CONST (FE_CAN_TRANSMISSION_MODE_AUTO),
79 CONST (FE_CAN_BANDWIDTH_AUTO),
80 CONST (FE_CAN_GUARD_INTERVAL_AUTO),
81 CONST (FE_CAN_HIERARCHY_AUTO),
82 CONST (FE_NEEDS_BENDING),
83 CONST (FE_CAN_RECOVER),
84 CONST (FE_CAN_MUTE_TS),
85
86 CONST (FE_HAS_SIGNAL),
87 CONST (FE_HAS_CARRIER),
88 CONST (FE_HAS_VITERBI),
89 CONST (FE_HAS_SYNC),
90 CONST (FE_HAS_LOCK),
91 CONST (FE_TIMEDOUT),
92 CONST (FE_REINIT),
93
94 CONST (INVERSION_OFF),
95 CONST (INVERSION_ON),
96 CONST (INVERSION_AUTO),
97
98 CONST (FEC_NONE),
99 CONST (FEC_1_2),
100 CONST (FEC_2_3),
101 CONST (FEC_3_4),
102 CONST (FEC_4_5),
103 CONST (FEC_5_6),
104 CONST (FEC_6_7),
105 CONST (FEC_7_8),
106 CONST (FEC_8_9),
107 CONST (FEC_AUTO),
108
109 CONST (QPSK),
110 CONST (QAM_16),
111 CONST (QAM_32),
112 CONST (QAM_64),
113 CONST (QAM_128),
114 CONST (QAM_256),
115 CONST (QAM_AUTO),
116
117 CONST (TRANSMISSION_MODE_2K),
118 CONST (TRANSMISSION_MODE_8K),
119 CONST (TRANSMISSION_MODE_AUTO),
120
121 CONST (BANDWIDTH_8_MHZ),
122 CONST (BANDWIDTH_7_MHZ),
123 CONST (BANDWIDTH_6_MHZ),
124 CONST (BANDWIDTH_AUTO),
125
126 CONST (GUARD_INTERVAL_1_32),
127 CONST (GUARD_INTERVAL_1_16),
128 CONST (GUARD_INTERVAL_1_8),
129 CONST (GUARD_INTERVAL_1_4),
130 CONST (GUARD_INTERVAL_AUTO),
131
132 CONST (HIERARCHY_NONE),
133 CONST (HIERARCHY_1),
134 CONST (HIERARCHY_2),
135 CONST (HIERARCHY_4),
136 CONST (HIERARCHY_AUTO),
137
138 CONST (DMX_OUT_DECODER),
139 CONST (DMX_OUT_TAP),
140 CONST (DMX_OUT_TS_TAP),
141
142 CONST (DMX_IN_FRONTEND),
143 CONST (DMX_IN_DVR),
144
145 CONST (DMX_PES_AUDIO0),
146 CONST (DMX_PES_VIDEO0),
147 CONST (DMX_PES_TELETEXT0),
148 CONST (DMX_PES_SUBTITLE0),
149 CONST (DMX_PES_PCR0),
150
151 CONST (DMX_PES_AUDIO1),
152 CONST (DMX_PES_VIDEO1),
153 CONST (DMX_PES_TELETEXT1),
154 CONST (DMX_PES_SUBTITLE1),
155 CONST (DMX_PES_PCR1),
156
157 CONST (DMX_PES_AUDIO2),
158 CONST (DMX_PES_VIDEO2),
159 CONST (DMX_PES_TELETEXT2),
160 CONST (DMX_PES_SUBTITLE2),
161 CONST (DMX_PES_PCR2),
162
163 CONST (DMX_PES_AUDIO3),
164 CONST (DMX_PES_VIDEO3),
165 CONST (DMX_PES_TELETEXT3),
166 CONST (DMX_PES_SUBTITLE3),
167 CONST (DMX_PES_PCR3),
168
169 CONST (DMX_PES_OTHER),
170
171 CONST (DMX_PES_AUDIO),
172 CONST (DMX_PES_VIDEO),
173 CONST (DMX_PES_TELETEXT),
174 CONST (DMX_PES_SUBTITLE),
175 CONST (DMX_PES_PCR),
176
177 CONST (DMX_SCRAMBLING_EV),
178 CONST (DMX_FRONTEND_EV),
179
180 CONST (DMX_CHECK_CRC),
181 CONST (DMX_ONESHOT),
182 CONST (DMX_IMMEDIATE_START),
183 CONST (DMX_KERNEL_CLIENT),
184
185 CONST (DMX_SOURCE_FRONT0),
186 CONST (DMX_SOURCE_FRONT1),
187 CONST (DMX_SOURCE_FRONT2),
188 CONST (DMX_SOURCE_FRONT3),
189
190 CONST (DMX_SOURCE_DVR0),
191 CONST (DMX_SOURCE_DVR1),
192 CONST (DMX_SOURCE_DVR2),
193 CONST (DMX_SOURCE_DVR3),
194
195 CONST (DMX_SCRAMBLING_OFF),
196 CONST (DMX_SCRAMBLING_ON),
197
198 // constants defined by this file
199 CONST (SCT_PAT),
200 CONST (SCT_CAT),
201 CONST (SCT_PMT),
202 CONST (SCT_TSDT),
203 CONST (SCT_NIT),
204 CONST (SCT_NIT_OTHER),
205 CONST (SCT_SDT),
206 CONST (SCT_SDT_OTHER),
207 CONST (SCT_BAT),
208 CONST (SCT_EIT_PRESENT),
209 CONST (SCT_EIT_PRESENT_OTHER),
210 CONST (SCT_EIT_SCHEDULE0),
211 CONST (SCT_EIT_SCHEDULE15),
212 CONST (SCT_EIT_SCHEDULE_OTHER0),
213 CONST (SCT_EIT_SCHEDULE_OTHER15),
214 CONST (SCT_TDT),
215 CONST (SCT_RST),
216 CONST (SCT_ST),
217 CONST (SCT_TOT),
218 CONST (SCT_RNT),
219 CONST (SCT_CST),
220 CONST (SCT_RCT),
221 CONST (SCT_CIT),
222 CONST (SCT_MPE),
223 CONST (SCT_DIT),
224 CONST (SCT_SIT),
225 };
226
227 #define HVS_S(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSVpv (struct.member, 0), 0)
228 #define HVS_I(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSViv (struct.member), 0)
229
230 static void
231 set_parameters (HV *hv, struct dvb_frontend_parameters *p, fe_type_t type)
232 {
233 HVS_I (hv, (*p), frequency);
234 HVS_I (hv, (*p), inversion);
235
236 switch (type)
237 {
238 case FE_QPSK:
239 HVS_I (hv, (*p).u.qpsk, symbol_rate);
240 HVS_I (hv, (*p).u.qpsk, fec_inner);
241 break;
242
243 case FE_QAM:
244 HVS_I (hv, (*p).u.qam, symbol_rate);
245 HVS_I (hv, (*p).u.qam, fec_inner);
246 HVS_I (hv, (*p).u.qam, modulation);
247 break;
248
249 case FE_OFDM:
250 HVS_I (hv, (*p).u.ofdm, bandwidth);
251 HVS_I (hv, (*p).u.ofdm, code_rate_HP);
252 HVS_I (hv, (*p).u.ofdm, code_rate_LP);
253 HVS_I (hv, (*p).u.ofdm, constellation);
254 HVS_I (hv, (*p).u.ofdm, transmission_mode);
255 break;
256 }
257 }
258
259 typedef unsigned char u8;
260
261 static SV *dec_sv;
262 static u8 *dec_data;
263 static long dec_ofs, dec_len8;
264 static U32 dec_field;
265 STRLEN dec_len;
266
267 #define decode_overflow (dec_ofs > dec_len8)
268
269 static void
270 decode_set (SV *data)
271 {
272 if (dec_sv)
273 SvREFCNT_dec (dec_sv);
274
275 dec_sv = newSVsv (data);
276 dec_data = SvPVbyte (dec_sv, dec_len);
277 dec_ofs = 0;
278 dec_len8 = dec_len << 3;
279 }
280
281 static U32
282 decode_field (int bits)
283 {
284 u8 *p = dec_data + (dec_ofs >> 3);
285 int frac = 8 - (dec_ofs & 7);
286 dec_ofs += bits;
287
288 if (decode_overflow)
289 return dec_field = 0;
290
291 U32 r = *p++;
292
293 r &= (1UL << frac) - 1;
294
295 if (bits < frac)
296 r >>= (frac - bits);
297 else
298 {
299 bits -= frac;
300
301 while (bits >= 8)
302 {
303 r = (r << 8) | *p++;
304 bits -= 8;
305 }
306
307 if (bits > 0)
308 r = (r << bits) | (*p >> (8 - bits));
309 }
310
311 return dec_field = r;
312 }
313
314 #define DEC_I(hv, bits, name) hv_store (hv, #name, sizeof (#name) - 1, newSViv (decode_field (bits)), 0)
315 #define DEC_S(hv, bytes, name) hv_store (hv, #name, sizeof (#name) - 1, newSVpvn (dec_data + (dec_ofs >> 3), (bytes)), 0), dec_ofs += (bytes) << 3
316
317 static AV *
318 decode_descriptors (long end)
319 {
320 AV *av = newAV ();
321
322 while (dec_ofs < end)
323 {
324 HV *hv = newHV ();
325 U8 type, len, a;
326 long end;
327
328 av_push (av, newRV_noinc ((SV *)hv));
329
330 DEC_I (hv, 8, type);
331 type = dec_field;
332 len = decode_field (8);
333
334 end = dec_ofs + (len << 3);
335
336 if (end > dec_len8)
337 return av;
338
339 switch (type)
340 {
341 case DT_PDC:
342 decode_field (4);
343 DEC_I (hv, 20, programme_identification_label);
344 break;
345
346 case DT_component:
347 decode_field (4);
348 DEC_I (hv, 4, stream_content);
349 DEC_I (hv, 8, component_type);
350 DEC_I (hv, 8, component_tag);
351 DEC_S (hv, 3, ISO_639_language_code);
352 DEC_S (hv, (end - dec_ofs) >> 3, text);
353 break;
354
355 case DT_short_event:
356 DEC_S (hv, 3, ISO_639_language_code);
357 a = decode_field (8); DEC_S (hv, a, event_name);
358 a = decode_field (8); DEC_S (hv, a, text);
359 break;
360
361 case DT_content:
362 DEC_S (hv, len, content);
363 break;
364
365 case DT_private_data_specifier:
366 DEC_I (hv, 32, private_data_specifier);
367 break;
368
369 default:
370 fprintf (stderr, "UNKXXX %x\n", type);//D
371 case 0:
372 case DT_extended_event:
373 case 0x80:
374 case 0x81:
375 case 0x82:
376 case 0x84:
377 case 0x85:
378 DEC_S (hv, len, raw_data);
379 break;
380 }
381
382 dec_ofs = end; // re-sync, in case of problems
383 }
384
385 return av;
386 }
387
388 MODULE = Linux::DVB PACKAGE = Linux::DVB
389
390 PROTOTYPES: DISABLE
391
392 void
393 _consts ()
394 PPCODE:
395 const struct consts *c;
396 for (c = consts;
397 c < consts + sizeof (consts) / sizeof (consts[0]);
398 c++)
399 {
400 XPUSHs (sv_2mortal (newSVpv (c->name, 0)));
401 XPUSHs (sv_2mortal (newSViv (c->value)));
402 }
403
404 MODULE = Linux::DVB PACKAGE = Linux::DVB::Frontend
405
406 SV *
407 _frontend_info (int fd)
408 CODE:
409 struct dvb_frontend_info fi;
410 HV *hv;
411
412 if (ioctl (fd, FE_GET_INFO, &fi) < 0)
413 XSRETURN_UNDEF;
414
415 hv = newHV ();
416 HVS_S (hv, fi, name);
417 HVS_I (hv, fi, type);
418 HVS_I (hv, fi, type);
419 HVS_I (hv, fi, frequency_min);
420 HVS_I (hv, fi, frequency_max);
421 HVS_I (hv, fi, frequency_stepsize);
422 HVS_I (hv, fi, frequency_tolerance);
423 HVS_I (hv, fi, symbol_rate_min);
424 HVS_I (hv, fi, symbol_rate_max);
425 HVS_I (hv, fi, symbol_rate_tolerance);
426 HVS_I (hv, fi, notifier_delay);
427 HVS_I (hv, fi, caps);
428
429 RETVAL = (SV *)newRV_noinc ((SV *)hv);
430 OUTPUT:
431 RETVAL
432
433 long
434 _read_status (int fd)
435 CODE:
436 fe_status_t st;
437
438 if (ioctl (fd, FE_READ_STATUS, &st) < 0)
439 XSRETURN_UNDEF;
440
441 RETVAL = st;
442 OUTPUT:
443 RETVAL
444
445 U32
446 _read_ber (int fd)
447 CODE:
448 uint32_t ber;
449 if (ioctl (fd, FE_READ_BER, &ber) < 0)
450 XSRETURN_UNDEF;
451
452 RETVAL = ber;
453 OUTPUT:
454 RETVAL
455
456 U32
457 _read_snr (int fd)
458 CODE:
459 uint32_t ber;
460 if (ioctl (fd, FE_READ_SNR, &ber) < 0)
461 XSRETURN_UNDEF;
462
463 RETVAL = ber;
464 OUTPUT:
465 RETVAL
466
467
468 I16
469 _signal_strength (int fd)
470 CODE:
471 int16_t st;
472 if (ioctl (fd, FE_READ_SIGNAL_STRENGTH, &st) < 0)
473 XSRETURN_UNDEF;
474
475 RETVAL = st;
476 OUTPUT:
477 RETVAL
478
479
480 U32
481 _uncorrected_blocks (int fd)
482 CODE:
483 uint32_t ubl;
484 if (ioctl (fd, FE_READ_UNCORRECTED_BLOCKS, &ubl) < 0)
485 XSRETURN_UNDEF;
486
487 RETVAL = ubl;
488 OUTPUT:
489 RETVAL
490
491 SV *
492 _get (int fd, int type)
493 CODE:
494 struct dvb_frontend_parameters p;
495 HV *hv;
496
497 if (ioctl (fd, FE_GET_FRONTEND, &p) < 0)
498 XSRETURN_UNDEF;
499
500 hv = newHV ();
501 set_parameters (hv, &p, type);
502 RETVAL = (SV *)newRV_noinc ((SV *)hv);
503 OUTPUT:
504 RETVAL
505
506 SV *
507 _event (int fd, int type)
508 CODE:
509 struct dvb_frontend_event e;
510 HV *hv;
511
512 if (ioctl (fd, FE_GET_EVENT, &e) < 0)
513 XSRETURN_UNDEF;
514
515 hv = newHV ();
516 HVS_I (hv, e, status);
517 set_parameters (hv, &e.parameters, type);
518 RETVAL = (SV *)newRV_noinc ((SV *)hv);
519 OUTPUT:
520 RETVAL
521
522 MODULE = Linux::DVB PACKAGE = Linux::DVB::Demux
523
524 int
525 _start (int fd)
526 ALIAS:
527 _stop = 1
528 CODE:
529 if (ioctl (fd, ix ? DMX_STOP : DMX_START, 0) < 0)
530 XSRETURN_UNDEF;
531
532 RETVAL = 1;
533 OUTPUT:
534 RETVAL
535
536 int
537 _filter (int fd, U16 pid, SV *filter, SV *mask, U32 timeout = 0, U32 flags = DMX_CHECK_CRC)
538 CODE:
539 struct dmx_sct_filter_params p;
540 STRLEN l;
541 char *s;
542
543 memset (&p.filter, 0, sizeof (p.filter));
544
545 p.pid = pid;
546 s = SvPVbyte (filter, l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.filter, s, l);
547 s = SvPVbyte (mask , l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.mask , s, l);
548 p.timeout = timeout;
549 p.flags = flags;
550 if (ioctl (fd, DMX_SET_FILTER, &p) < 0)
551 XSRETURN_UNDEF;
552
553 RETVAL = 1;
554 OUTPUT:
555 RETVAL
556
557 int
558 _pes_filter (int fd, U16 pid, long input, long output, long type, U32 flags = 0)
559 CODE:
560 struct dmx_pes_filter_params p;
561
562 p.pid = pid;
563 p.input = input;
564 p.output = output;
565 p.pes_type = type;
566 p.flags = flags;
567 if (ioctl (fd, DMX_SET_PES_FILTER, &p) < 0)
568 XSRETURN_UNDEF;
569
570 RETVAL = 1;
571 OUTPUT:
572 RETVAL
573
574 int
575 _buffer (int fd, unsigned long size)
576 CODE:
577
578 if (ioctl (fd, DMX_SET_BUFFER_SIZE, size) < 0)
579 XSRETURN_UNDEF;
580
581 RETVAL = 1;
582 OUTPUT:
583 RETVAL
584
585 MODULE = Linux::DVB PACKAGE = Linux::DVB::Decode PREFIX = decode_
586
587 void
588 set (SV *data)
589 CODE:
590
591 int
592 len ()
593 CODE:
594 RETVAL = (dec_ofs + 7) >> 3;
595 OUTPUT:
596 RETVAL
597
598 U32
599 field (int bits)
600
601 SV *
602 si (SV *stream)
603 CODE:
604 HV *hv = newHV ();
605
606 U8 table_id;
607 U16 length;
608 long end;
609
610 decode_set (stream);
611
612 do {
613 DEC_I (hv, 8, table_id);
614 table_id = dec_field;
615 } while (table_id == 0xff);
616
617 DEC_I (hv, 1, section_syntax_indicator);
618 decode_field (1);
619 decode_field (2);
620
621 length = decode_field (12);
622 end = dec_ofs + (length << 3);
623
624 switch (table_id)
625 {
626 case SCT_EIT_PRESENT:
627 case SCT_EIT_PRESENT_OTHER:
628 case SCT_EIT_SCHEDULE0...SCT_EIT_SCHEDULE15: //GCC
629 case SCT_EIT_SCHEDULE_OTHER0...SCT_EIT_SCHEDULE_OTHER15: //GCC
630 DEC_I (hv, 16, service_id);
631 decode_field (2);
632 DEC_I (hv, 5, version_number);
633 DEC_I (hv, 1, current_next_indicator);
634 DEC_I (hv, 8, section_number);
635 DEC_I (hv, 8, last_section_number);
636 DEC_I (hv, 16, transport_stream_id);
637 DEC_I (hv, 16, original_network_id);
638 DEC_I (hv, 8, segment_last_section_number);
639 DEC_I (hv, 8, last_table_id);
640
641 AV *events = newAV ();
642 hv_store (hv, "events", 6, newRV_noinc ((SV *)events), 0);
643
644 while (end - dec_ofs > 32)
645 {
646 long dll;
647 AV *desc;
648 HV *ev = newHV ();
649 av_push (events, newRV_noinc ((SV *)ev));
650
651 DEC_I (ev, 16, event_id);
652 DEC_I (ev, 16, start_time_mjd);
653 DEC_I (ev, 24, start_time_hms);
654 DEC_I (ev, 24, duration);
655 DEC_I (ev, 3, running_status);
656 DEC_I (ev, 1, free_CA_mode);
657
658 dll = dec_ofs + (decode_field (12) << 3);
659
660 desc = decode_descriptors (dll);
661 hv_store (ev, "descriptors", 11, newRV_noinc ((SV *)desc), 0);
662 }
663
664 decode_field (32); // skip CRC
665
666 break;
667 #if 0 // service desc table
668 case SCT_SDT:
669 case SCT_SDT_OTHER:
670
671 AV *events = newAV ();
672 hv_store (hv, "events", 0, newRV_noinc (events), 0);
673
674 while (end - dec_ofs > 32)
675 {
676 HV *ev = newHV ();
677 U32 dll;
678 av_push (events, newRV_noinc (ev));
679
680 DEC_I (ev, 16, service_id);
681 decode_field (6);
682 DEC_I (ev, 1, EIT_schedule_flags);
683 DEC_I (ev, 1, EIT_present_following_flag);
684 DEC_I (ev, 3, running_status);
685 DEC_I (ev, 1, free_CA_mode);
686
687 dll = decode_field (12);
688
689 DEC_I (ev, 1, free_CA_mode);
690 }
691
692 decode_field (32); // skip CRC
693 //DEC_S (hv, length + 3 - (dec_ofs >> 3), raw_data);
694 break;
695 #endif
696 default:
697 DEC_S (hv, length, raw_data);
698 break;
699 }
700
701 if (decode_overflow)
702 {
703 SvREFCNT_dec (hv);
704 XSRETURN_UNDEF;
705 }
706
707 sv_chop (stream, SvPVX (stream) + ((dec_ofs + 7) >> 3));
708
709 RETVAL = (SV *)newRV_noinc ((SV *)hv);
710 OUTPUT:
711 RETVAL
712