aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2014-07-15 05:56:09 +0200
committerHans Verkuil <hans.verkuil@cisco.com>2014-07-15 05:56:09 +0200
commitfd43a56c26495f51353e0b909cbddfdba6b1d296 (patch)
tree1871d4ba3fc2d9b66d0ef02b5e70615183ae2508
parent403701d5e11d36c807cb2c234156668c8a354dd5 (diff)
parent541c07a5f8d592c38c36ca11d474c919ec5c6ac7 (diff)
Merge remote-tracking branch 'linuxtv/master' into scalingscaling
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Conflicts: utils/v4l2-compliance/v4l2-test-formats.cpp
-rw-r--r--ChangeLog482
-rw-r--r--INSTALL27
-rw-r--r--Makefile.am45
-rw-r--r--android-config.h360
-rw-r--r--configure.ac48
-rw-r--r--contrib/Makefile.am2
-rwxr-xr-x[-rw-r--r--]contrib/az6007/parse_az6007.pl0
-rwxr-xr-x[-rw-r--r--]contrib/cx231xx/parse_cx231xx.pl0
-rwxr-xr-xcontrib/dib0700/parse_dib0700.pl231
-rwxr-xr-x[-rw-r--r--]contrib/em28xx/rewrite_eeprom.pl0
-rw-r--r--contrib/freebsd/Makefile.am7
-rwxr-xr-xcontrib/freebsd/bsdify.sh43
-rw-r--r--contrib/freebsd/include/linux/dvb/audio.h135
-rw-r--r--contrib/freebsd/include/linux/dvb/ca.h90
-rw-r--r--contrib/freebsd/include/linux/dvb/dmx.h154
-rw-r--r--contrib/freebsd/include/linux/dvb/frontend.h594
-rw-r--r--contrib/freebsd/include/linux/dvb/net.h53
-rw-r--r--contrib/freebsd/include/linux/dvb/osd.h144
-rw-r--r--contrib/freebsd/include/linux/dvb/version.h29
-rw-r--r--contrib/freebsd/include/linux/dvb/video.h272
-rw-r--r--contrib/freebsd/include/linux/input.h1
-rw-r--r--contrib/freebsd/include/linux/uinput.h13
-rw-r--r--contrib/freebsd/include/linux/v4l2-common.h12
-rw-r--r--contrib/freebsd/include/linux/videodev2.h29
-rw-r--r--contrib/freebsd/patches/dvb-audio-header.diff11
-rw-r--r--contrib/freebsd/patches/dvb-dmx-header.diff15
-rw-r--r--contrib/freebsd/patches/dvb-frontend-header.diff12
-rw-r--r--contrib/freebsd/patches/dvb-net-header.diff12
-rw-r--r--contrib/freebsd/patches/dvb-osd-header.diff11
-rw-r--r--contrib/freebsd/patches/dvb-video-header.diff15
-rw-r--r--contrib/freebsd/patches/dvb-video-timestamp.diff11
-rw-r--r--contrib/freebsd/patches/input-header.diff8
-rw-r--r--contrib/freebsd/patches/ivtv-header.diff5
-rw-r--r--contrib/freebsd/patches/series8
-rw-r--r--contrib/freebsd/patches/uinput-header.diff8
-rw-r--r--contrib/freebsd/patches/v4l2-common-header.diff13
-rw-r--r--contrib/freebsd/patches/videodev2-header.diff13
-rwxr-xr-x[-rw-r--r--]contrib/m920x/m920x_parse.pl0
-rwxr-xr-x[-rw-r--r--]contrib/m920x/m920x_sp_firmware.pl0
-rw-r--r--contrib/qv4l2-qt3/.gitignore5
-rw-r--r--contrib/qv4l2-qt3/Makefile.install5
-rw-r--r--contrib/qv4l2-qt3/ctrl-tab.cpp592
-rw-r--r--contrib/qv4l2-qt3/fileopen.xpm22
-rw-r--r--contrib/qv4l2-qt3/general-tab.cpp350
-rw-r--r--contrib/qv4l2-qt3/general-tab.h73
-rw-r--r--contrib/qv4l2-qt3/qv4l2-qt3.pro12
-rw-r--r--contrib/qv4l2-qt3/qv4l2.cpp220
-rw-r--r--contrib/qv4l2-qt3/qv4l2.h102
-rwxr-xr-x[-rw-r--r--]contrib/saa7134/parse_saa7134.pl0
-rwxr-xr-x[-rw-r--r--]contrib/sn9c201/parse_sn9c201.pl0
-rw-r--r--contrib/test/.gitignore2
-rw-r--r--contrib/test/Makefile.am6
-rw-r--r--contrib/test/ioctl-test.h5
-rw-r--r--contrib/test/ioctl_32.h5
-rw-r--r--contrib/test/ioctl_64.h5
-rw-r--r--contrib/test/v4lgrab.c203
-rw-r--r--contrib/test/vbi-test.c98
-rwxr-xr-x[-rw-r--r--]contrib/tm6000/parse_tm6000.pl0
-rwxr-xr-x[-rw-r--r--]contrib/usb_parse/parse_usb.pl0
-rwxr-xr-x[-rw-r--r--]contrib/usbmon2usbsnoop.pl0
-rw-r--r--include/linux/v4l2-common.h4
-rw-r--r--include/linux/v4l2-mediabus.h147
-rw-r--r--include/linux/v4l2-subdev.h40
-rw-r--r--include/linux/videodev2.h29
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/include/libdvbv5/atsc_eit.h5
-rw-r--r--lib/include/libdvbv5/atsc_header.h39
-rw-r--r--lib/include/libdvbv5/cat.h2
-rw-r--r--lib/include/libdvbv5/crc32.h (renamed from lib/libdvbv5/crc32.h)0
-rw-r--r--lib/include/libdvbv5/desc_atsc_service_location.h9
-rw-r--r--lib/include/libdvbv5/desc_ca.h9
-rw-r--r--lib/include/libdvbv5/desc_ca_identifier.h9
-rw-r--r--lib/include/libdvbv5/desc_cable_delivery.h9
-rw-r--r--lib/include/libdvbv5/desc_event_extended.h9
-rw-r--r--lib/include/libdvbv5/desc_event_short.h9
-rw-r--r--lib/include/libdvbv5/desc_extension.h11
-rw-r--r--lib/include/libdvbv5/desc_frequency_list.h9
-rw-r--r--lib/include/libdvbv5/desc_hierarchy.h8
-rw-r--r--lib/include/libdvbv5/desc_isdbt_delivery.h14
-rw-r--r--lib/include/libdvbv5/desc_language.h9
-rw-r--r--lib/include/libdvbv5/desc_logical_channel.h9
-rw-r--r--lib/include/libdvbv5/desc_network_name.h9
-rw-r--r--lib/include/libdvbv5/desc_partial_reception.h9
-rw-r--r--lib/include/libdvbv5/desc_sat.h9
-rw-r--r--lib/include/libdvbv5/desc_service.h9
-rw-r--r--lib/include/libdvbv5/desc_service_list.h9
-rw-r--r--lib/include/libdvbv5/desc_service_location.h8
-rw-r--r--lib/include/libdvbv5/desc_t2_delivery.h7
-rw-r--r--lib/include/libdvbv5/desc_terrestrial_delivery.h9
-rw-r--r--lib/include/libdvbv5/desc_ts_info.h9
-rw-r--r--lib/include/libdvbv5/descriptors.h55
-rw-r--r--lib/include/libdvbv5/dvb-scan.h53
-rw-r--r--lib/include/libdvbv5/eit.h5
-rw-r--r--lib/include/libdvbv5/header.h7
-rw-r--r--lib/include/libdvbv5/mgt.h5
-rw-r--r--lib/include/libdvbv5/nit.h4
-rw-r--r--lib/include/libdvbv5/pat.h6
-rw-r--r--lib/include/libdvbv5/pmt.h2
-rw-r--r--lib/include/libdvbv5/sdt.h7
-rw-r--r--lib/include/libdvbv5/vct.h5
-rw-r--r--lib/include/libv4lconvert.h6
-rw-r--r--lib/libdvbv5/Makefile.am48
-rw-r--r--lib/libdvbv5/crc32.c2
-rw-r--r--lib/libdvbv5/descriptors.c67
-rw-r--r--lib/libdvbv5/descriptors/atsc_header.c47
-rw-r--r--lib/libdvbv5/descriptors/cat.c72
-rw-r--r--lib/libdvbv5/descriptors/desc_atsc_service_location.c19
-rw-r--r--lib/libdvbv5/descriptors/desc_ca.c10
-rw-r--r--lib/libdvbv5/descriptors/desc_ca_identifier.c8
-rw-r--r--lib/libdvbv5/descriptors/desc_cable_delivery.c17
-rw-r--r--lib/libdvbv5/descriptors/desc_event_extended.c6
-rw-r--r--lib/libdvbv5/descriptors/desc_event_short.c10
-rw-r--r--lib/libdvbv5/descriptors/desc_extension.c14
-rw-r--r--lib/libdvbv5/descriptors/desc_frequency_list.c8
-rw-r--r--lib/libdvbv5/descriptors/desc_hierarchy.c13
-rw-r--r--lib/libdvbv5/descriptors/desc_isdbt_delivery.c34
-rw-r--r--lib/libdvbv5/descriptors/desc_language.c6
-rw-r--r--lib/libdvbv5/descriptors/desc_logical_channel.c14
-rw-r--r--lib/libdvbv5/descriptors/desc_network_name.c6
-rw-r--r--lib/libdvbv5/descriptors/desc_partial_reception.c10
-rw-r--r--lib/libdvbv5/descriptors/desc_sat.c19
-rw-r--r--lib/libdvbv5/descriptors/desc_service.c11
-rw-r--r--lib/libdvbv5/descriptors/desc_service_list.c12
-rw-r--r--lib/libdvbv5/descriptors/desc_service_location.c17
-rw-r--r--lib/libdvbv5/descriptors/desc_t2_delivery.c41
-rw-r--r--lib/libdvbv5/descriptors/desc_terrestrial_delivery.c31
-rw-r--r--lib/libdvbv5/descriptors/desc_ts_info.c21
-rw-r--r--lib/libdvbv5/descriptors/eit.c170
-rw-r--r--lib/libdvbv5/descriptors/mgt.c140
-rw-r--r--lib/libdvbv5/descriptors/pat.c104
-rw-r--r--lib/libdvbv5/descriptors/sdt.c112
-rw-r--r--lib/libdvbv5/dvb-fe.c16
-rw-r--r--lib/libdvbv5/dvb-file.c48
-rw-r--r--lib/libdvbv5/dvb-scan.c180
-rwxr-xr-xlib/libdvbv5/gen_dvb_structs.pl4
-rw-r--r--lib/libdvbv5/tables/atsc_eit.c (renamed from lib/libdvbv5/descriptors/atsc_eit.c)109
-rw-r--r--lib/libdvbv5/tables/cat.c100
-rw-r--r--lib/libdvbv5/tables/eit.c194
-rw-r--r--lib/libdvbv5/tables/header.c (renamed from lib/libdvbv5/descriptors/header.c)26
-rw-r--r--lib/libdvbv5/tables/mgt.c154
-rw-r--r--lib/libdvbv5/tables/mpeg_es.c (renamed from lib/libdvbv5/descriptors/mpeg_es.c)30
-rw-r--r--lib/libdvbv5/tables/mpeg_pes.c (renamed from lib/libdvbv5/descriptors/mpeg_pes.c)9
-rw-r--r--lib/libdvbv5/tables/mpeg_ts.c (renamed from lib/libdvbv5/descriptors/mpeg_ts.c)7
-rw-r--r--lib/libdvbv5/tables/nit.c (renamed from lib/libdvbv5/descriptors/nit.c)145
-rw-r--r--lib/libdvbv5/tables/pat.c130
-rw-r--r--lib/libdvbv5/tables/pmt.c (renamed from lib/libdvbv5/descriptors/pmt.c)130
-rw-r--r--lib/libdvbv5/tables/sdt.c151
-rw-r--r--lib/libdvbv5/tables/vct.c (renamed from lib/libdvbv5/descriptors/vct.c)133
-rw-r--r--lib/libv4l-mplane/libv4l-mplane.c149
-rw-r--r--lib/libv4l2/libv4l2-priv.h1
-rw-r--r--lib/libv4l2/libv4l2.c28
-rw-r--r--lib/libv4l2rds/libv4l2rds.c25
-rw-r--r--lib/libv4lconvert/control/libv4lcontrol.c181
-rw-r--r--lib/libv4lconvert/control/libv4lcontrol.h3
-rw-r--r--lib/libv4lconvert/helper.c5
-rw-r--r--lib/libv4lconvert/libv4lconvert.c25
-rw-r--r--lib/libv4lconvert/se401.c3
-rw-r--r--utils/Makefile.am1
-rw-r--r--utils/dvb/dvbv5-scan.c7
-rw-r--r--utils/dvb/dvbv5-zap.c59
-rw-r--r--utils/keytable/Makefile.am12
-rw-r--r--utils/keytable/rc_keymaps/allwinner_ba10_tv_box15
-rw-r--r--utils/keytable/rc_keymaps/allwinner_i12_a20_tv_box28
-rw-r--r--utils/keytable/rc_keymaps/tivo84
-rw-r--r--utils/keytable/rc_keymaps/wobo_i59
-rw-r--r--utils/media-ctl/.gitignore1
-rw-r--r--utils/media-ctl/Makefile.am17
-rw-r--r--utils/media-ctl/libmediactl.c957
-rw-r--r--utils/media-ctl/libmediactl.pc.in10
-rw-r--r--utils/media-ctl/libv4l2subdev.c757
-rw-r--r--utils/media-ctl/libv4l2subdev.pc.in11
-rw-r--r--utils/media-ctl/media-ctl.c660
-rw-r--r--utils/media-ctl/mediactl-priv.h64
-rw-r--r--utils/media-ctl/mediactl.h423
-rw-r--r--utils/media-ctl/options.c178
-rw-r--r--utils/media-ctl/options.h45
-rw-r--r--utils/media-ctl/tools.h32
-rw-r--r--utils/media-ctl/v4l2subdev.h258
-rw-r--r--utils/qv4l2/Makefile.am2
-rw-r--r--utils/qv4l2/capture-win-gl.cpp764
-rw-r--r--utils/qv4l2/capture-win-gl.h35
-rw-r--r--utils/qv4l2/capture-win-qt.cpp99
-rw-r--r--utils/qv4l2/capture-win-qt.h24
-rw-r--r--utils/qv4l2/capture-win.cpp190
-rw-r--r--utils/qv4l2/capture-win.h77
-rw-r--r--utils/qv4l2/ctrl-tab.cpp184
-rw-r--r--utils/qv4l2/general-tab.cpp1270
-rw-r--r--utils/qv4l2/general-tab.h57
-rw-r--r--utils/qv4l2/qv4l2.cpp150
-rw-r--r--utils/qv4l2/qv4l2.h17
-rw-r--r--utils/qv4l2/qv4l2.qrc2
-rw-r--r--utils/qv4l2/record.pngbin1618 -> 0 bytes
-rw-r--r--utils/qv4l2/snapshot.pngbin1682 -> 1767 bytes
-rw-r--r--utils/qv4l2/start.pngbin0 -> 1449 bytes
-rw-r--r--utils/qv4l2/v4l2-api.cpp180
-rw-r--r--utils/qv4l2/v4l2-api.h50
-rw-r--r--utils/rds-ctl/rds-ctl.cpp31
-rw-r--r--utils/v4l2-compliance/Android.mk24
-rw-r--r--utils/v4l2-compliance/Makefile.am4
-rw-r--r--utils/v4l2-compliance/cv4l-helpers.h2
-rw-r--r--utils/v4l2-compliance/v4l-helpers.h14
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.cpp39
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.h23
-rw-r--r--utils/v4l2-compliance/v4l2-test-buffers.cpp25
-rw-r--r--utils/v4l2-compliance/v4l2-test-controls.cpp5
-rw-r--r--utils/v4l2-compliance/v4l2-test-formats.cpp103
-rw-r--r--utils/v4l2-compliance/v4l2-test-input-output.cpp32
-rw-r--r--utils/v4l2-compliance/v4l2-test-io-config.cpp2
-rw-r--r--utils/v4l2-ctl/Android.mk25
-rw-r--r--utils/v4l2-ctl/Makefile.am5
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-common.cpp11
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-edid.cpp6
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-io.cpp5
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-misc.cpp8
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-overlay.cpp43
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-sdr.cpp5
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-selection.cpp5
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-stds.cpp5
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-streaming.cpp251
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-test-patterns.cpp299
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-tuner.cpp5
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-vbi.cpp121
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-vidcap.cpp11
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-vidout.cpp7
-rw-r--r--utils/v4l2-ctl/v4l2-ctl.cpp42
-rw-r--r--utils/v4l2-ctl/v4l2-ctl.h47
-rw-r--r--utils/v4l2-ctl/vivi-colors.c273
-rw-r--r--utils/v4l2-ctl/vivi-colors.h45
-rw-r--r--utils/v4l2-ctl/vivi-tpg.c1369
-rw-r--r--utils/v4l2-ctl/vivi-tpg.h459
-rw-r--r--utils/v4l2-dbg/Android.mk18
-rw-r--r--utils/v4l2-dbg/Makefile.am2
-rw-r--r--utils/v4l2-dbg/v4l2-dbg.cpp5
233 files changed, 11999 insertions, 6418 deletions
diff --git a/ChangeLog b/ChangeLog
index ab192709..3b0092c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,485 @@
+v4l-utils-1.2.0
+---------------
+
+Alain VOLMAT (1):
+ buildsystem: Fix configure.ac --disable-v4l-utils option
+
+Andreas Weber (2):
+ v4l2-ctl-misc.cpp: bugfix display #of readbuffers
+ v4l2gl/v4l2grab: fix errno assignment in while loop
+
+André Roth (43):
+ libdvbv5: VCT bitmap fixup
+ libdvbv5: fix NIT structures
+ libdvbv5: implement dvb_fe_dummy for logging
+ libdvbv5: prefix VCT with atsc_ instead of dvb_
+ libdvbv5: fix missing includes
+ libdvbv5: cleanup dvb_nit_transport_foreach macro
+ libdvbv5: implement ATSC standard header
+ libdvbv5: implement MGT table parser
+ libdvbv5: implement ATSC EIT
+ libdvbv5: fix reading multisection tables
+ libdvbv5: service location descriptor support
+ libdvbv5: support info info log via dvb_loginfo
+ libdvbv5: fix asprintf compile warnings
+ libdvbv5: mpeg elementary stream parsers
+ libdvbv5: fix EIT parsing
+ libdvbv5: shared lib and installing headers
+ libdvbv5: remove header files from SOURCES in Makefile.am
+ libdvbv5: fix dvb_parse_descriptors and make dvb_desc_init private
+ libdvbv5: add attribute packed to structs and unions
+ libdvbv5: add parser for CAT
+ libdvbv5: add parser for ca and ca_identifier descriptors
+ libdvbv5: fix PMT parser
+ libdvbv5: cleanup printing tables and descriptors
+ libdvbv5: use DVB_DESC_HEADER macro in all descriptors
+ libdvbv5: make dvb_desc_default_init and dvb_desc_default_print private
+ libdvbv5: allow table parsers to get specific pointer to table struct
+ libdvbv5: descriptor parser return int
+ libdvbv5: remove unneeded includes
+ libdvbv5: fix lost ressource in atsc_eit
+ libdvbv5: add support for tables with multiple ts_id and section gaps
+ libdvbv5: reunite atsc_table_header and dvb_table_header
+ libdvbv5: fix asprintf compile warning in dvbv5-scan
+ libdvbv5: make crc32 public
+ libdvbv5: make dvb_table_filter_free public
+ libdvbv5: cleanup table parsers
+ libdvbv5: cleanup printing of tables and descriptors
+ libdvbv5: rename descriptor functions
+ libdvbv5: move table parsers to separate directory
+ libdvbv5: cleanup parser API
+ libdvbv5: short API description
+ libdvbv5: build dynamic libdvbv5 by default
+ libdvbv5: improve CRC size handling
+ libdvbv5: improve DVB header handling
+
+Antonio Ospite (1):
+ libv4lconvert: Fix a regression when converting from Y10B
+
+Antti Palosaari (1):
+ v4l2-ctl: add tuner support for SDR tuners
+
+Baard Eirik Winther (1):
+ qv4l2: Add cropping option to remove pillarbox
+
+Bård Eirik Winther (33):
+ qv4l2: move function ctrlEvent
+ qv4l2: add hotkeys for common operations
+ qv4l2: fix minimum size in capture win to frame size
+ qv4l2: add Capture menu
+ qv4l2: new modular capture window design
+ qv4l2: add OpenGL rendering
+ qv4l2: alter capture menu
+ qv4l2: new ALSA stream source code
+ qv4l2: fix a bug where the alsa thread never stops
+ qv4l2: add ALSA stream to qv4l2
+ qv4l2: add ALSA audio playback
+ qv4l2: fix YUY2 shader
+ qv4l2: fix black screen with opengl after capture
+ qv4l2: show frames option can be toggled during capture
+ qv4l2: add function getMargins
+ qv4l2: add video scaling for CaptureWin
+ qv4l2: add hotkey for reset scaling to frame size
+ qv4l2: add aspect ratio support
+ qv4l2: generalized opengl include guards
+ qv4l2: fix YUY2 shader
+ qv4l2: fix black screen with opengl after capture
+ qv4l2: show frames option can be toggled during capture
+ qv4l2: create function getMargins
+ qv4l2: add video scaling for CaptureWin
+ qv4l2: added resize to frame size in Capture menu
+ qv4l2: add hotkey for reset scaling to frame size
+ qv4l2: add pixel aspect ratio support for CaptureWin
+ qv4l2: change m_scaledFrame to m_scaledSize
+ qv4l2: fix missing status tips
+ qv4l2: fix program input parameters
+ qv4l2: add manpage
+ qv4l2: updated about window
+ qv4l2: fix GeneralTab layout
+
+Gregor Jasny (22):
+ Start v4l-utils 1.1.x development branch
+ libv4lconvert: Reject too short source buffer before accessing it
+ buildsystem: use subdir-objects automake option as suggested by automake
+ buildsystem: Do not specify library version for static libs
+ buildsystem: Use autoconf variable for symbol visibility flag
+ buildsystem: Use C99 by default
+ libdvbv5: Fix compiler warning about signedness
+ libv4lconvert: Add ASUS A7M to upside down table
+ libdvbv5: FIx check for available adaptation field
+ libdvbv5; Fix typo in MPEG TS print function
+ v4l2-ctl: Do not leak framebuffer handle in error paths
+ dvbv5-zap: Close open file descriptor in error path
+ dvbv5-zap: Always initialize status variable
+ libv4lconvert: Error out if source or destination pointers are null
+ libv4lconvert: Gracefully handle unknown SE401 destination formats
+ libdvbv5: Distribute internal header, too
+ mediactl: Distribute internal header, too
+ buildsystem: Distribute Android.mk files
+ v4l2-compliance: Distribute internal header, too
+ qv4l2: Distribute manpage
+ libdvbv5: Do not install libdvbv5 by default
+ Prepare for 1.2.0 release
+
+Hans Verkuil (130):
+ qv4l2: fix a segfault for native 32 bpp formats
+ Revert "qv4l2: add aspect ratio support"
+ Revert "qv4l2: add hotkey for reset scaling to frame size"
+ Revert "qv4l2: add video scaling for CaptureWin"
+ Revert "qv4l2: add function getMargins"
+ Revert "qv4l2: show frames option can be toggled during capture"
+ Revert "qv4l2: fix black screen with opengl after capture"
+ Revert "qv4l2: fix YUY2 shader"
+ qv4l2: add cropping to CaptureWin and Qt render
+ qv4l2: call setFrame before resize to get correct frame size calculation
+ rds-ctl: fix segfault in list_devices()
+ v4l2-ctl: fix '--set-dv-bt-timings query' option.
+ v4l2-ctl: properly close filehandles on error
+ v4l-utils: sync with latest kernel.
+ v4l2-ctl: set b.num_planes to 1 for single plane output formats.
+ qv4l2: crop: take pixel aspect ratio into account.
+ v4l2-compliance: check for invalid m2m + overlay caps
+ v4l2-compliance: check that streaming will fail for overlays
+ v4l2-ctl: use libv4l2 wrapper for mmap as well.
+ qv4l2: fix broken VBI support
+ v4l-utils: run sync-with-kernel, add ioctl32 tests for v4l2-subdev.h
+ v4l2-ctl: errors during streaming setup were ignored
+ libv4l2rds: update the list of AFs if the number of AFs changes
+ libv4l2rds: rename V4L2_RDS_FLAG_STATIC_PTY to _DYNAMIC_PTY
+ rds-ctl: add support for dynamic/static PTY
+ v4l2-ctl: --all should also show multiplanar formats.
+ v4l2-compliance: add bytesperline sanity check for multiplanar formats.
+ v4l2-compliance: add streaming tests
+ v4l2-compliance: fix broken test for V4L2_FRMIVAL_TYPE_CONTINUOUS
+ v4l2-ctl: add support for fields
+ v4l2-compliance: fix read() test and reopen after read/write
+ v4l2-ctl: automatically detect single/multiplanar buffer type.
+ v4l2-compliance: test streaming with bogus v4l2_buffer values.
+ v4l2-compliance: check if USERPTR is actually supported.
+ v4l2-compliance: restore the initial formats after testing S_FMT
+ v4l2-compliance: add EXPBUF and DMABUF streaming tests.
+ v4l2-compliance: test for invalid dmabuf file descriptors.
+ qv4l2: add combobox to select the field format.
+ v4l2-compliance: add tests for multiplanar capture.
+ v4l2-compliance: fix data_offset related tests
+ v4l2-ctl: fix regression when setting vidcap format
+ v4l2-compliance: move streaming setup code to main source.
+ v4l2-compliance: move functions around.
+ v4l2-compliance: Update fixme.txt
+ v4l2-compliance: fix BUF_TYPE vs CAP mixup.
+ v4l2-compliance: obtain expbuf caps and fix radio/vbi bug
+ v4l2-compliance: now support all formats in the streaming tests.
+ v4l2-ctl: is_mplane was never set.
+ v4l2-compliance: add new mmap tests.
+ v4l-utils: fix optional args for short opts
+ v4l2-ctl: set timestamp for output buffers.
+ v4l2-ctl: add streaming between two video devices using dmabuf
+ v4l2-ctl: the colorspace can now be set for outputs.
+ v4l2-ctl: improve the overlay support
+ v4l2-compliance: add M2M streaming support
+ v4l2-compliance: fill output buffers.
+ v4l2-compliance: fix check for correct return code for STREAMON.
+ v4l2-compliance: reopen node after each streaming test.
+ v4l2-compliance: change one warn to info.
+ v4l2-compliance: lower default framecount to 60.
+ v4l2-compliance: bypass libv4l2 for expbuf handling.
+ v4l2-compliance: improve clip checking
+ v4l2-compliance: add tests for output buffer error checking
+ v4l2-ctl: skip captured buffers with flag V4L2_BUF_FLAG_ERROR
+ qv4l2: ignore buffers with flag V4L2_BUF_FLAG_ERROR.
+ sync-with-kernel should also copy fb.h
+ v4l-utils: ran sync-with-kernel which added the fb.h header.
+ qv4l2: two field related fixes
+ qv4l2: support top/bottom/alternate field settings.
+ qv4l2: add check if the shader function is available.
+ v4l2-compliance: check for presence of a tuner/modulator
+ v4l2-compliance: improve format matching code.
+ qv4l2: initialize comboboxes with sensible initial sizes.
+ qv4l2: QUERYSTD returns STD_UNKNOWN if there is no standard
+ qv4l2: fix frequency handling
+ qv4l2: disable what shouldn't be touched while streaming.
+ v4l2-compliance: add tests for queuing operations with invalid indices.
+ v4l2-compliance: more nasty evil stream I/O checks
+ qv4l2: fix incorrect call to s_fmt when disabling width/height
+ qv4l2: fix incorrect handling of fields
+ v4l-utils: sync with latest kernel headers.
+ v4l2-ctl: add support for SDR FMT
+ v4l2-ctl: implement list SDR buffers command
+ v4l2-ctl: add timestamp source support.
+ v4l2-compliance: add timestamp source tests.
+ v4l2-ctl: add missing v4l2-ctl-sdr.cpp file.
+ v4l2-ctl: support SDR capture streaming.
+ v4l2-compliance: add SDR compliance tests.
+ v4l2-compliance: add 1HZ support when setting the frequency.
+ qv4l2: add SDR support.
+ qv4l2: use QDoubleSpinBox for frequency inputs
+ v4l2-compliance: support menu controls with more than 32 items
+ v4l2-ctl/compliance: use the correct mmap/munmap functions.
+ v4l2-ctl: add support for custom bytesperline values.
+ qv4l2: increase max width/height to 4K resolution.
+ v4l2-ctl: fix printing of buffer flags
+ v4l-utils: sync to latest kernel headers
+ v4l2-ctl: add --clear-edid option.
+ v4l2-ctl: rename old v4l2_subdev_edid and VIDIOC_SUBDEV_G/S_EDID
+ v4l2-compliance: add test setting all enumerated timings.
+ v4l2-compliance: add G/S_EDID tests.
+ libv4lconvert: remove broken ALTERNATE handling
+ v4l2-compliance: add helper headers
+ v4l2-compliance: use the new cv4l-helpers.h header.
+ v4l2-compliance: m2m devices should have only one input and output
+ v4l2-compliance: test control/format/codec ioctls for all inputs/outputs
+ qv4l2: add support for V4L2_PIX_FMT_NV16M/61M
+ v4l2-compliance: fix function pointer prototype.
+ v4l2-compliance: add missing 'class' keyword after 'friend'
+ v4l2-compliance: fix 32-bit compilation for v4l_fd_init()
+ qv4l2: only set m_isRadio if m_isSDR is true.
+ qv4l2: fix modulator frequency bugs
+ libv4lconvert: fix a v4l2-compliance error
+ v4l2-compliance: don't do the global format test when using libv4l2.
+ sync-with-kernel: update to latest kernel headers.
+ libdvbv5: fix compile error
+ v4l2-ctl: add support V4L2_EVENT_SOURCE_CHANGE
+ libdvbv5: generate the correct include in dvb-v5.c
+ Synced with latest kernel.
+ Add missing v4l2-mediabus.h
+ Synced with latest kernel
+ qv4l2: fix segmentation fault when compiled without ALSA support.
+ v4l2-compliance: fix broken querymenu check.
+ qv4l2: add support for the V4L2_EVENT_SOURCE_CHANGE event.
+ v4l2-compliance: don't warn about missing frameintervals
+ v4l2-ctl: add support to try/set raw VBI formats
+ v4lgrab/vbi-test: remove these utilities
+ qv4l2-qt3: remove utility
+ qv4l2: fix opengl support for RGB32/BGR32.
+ v4l2-compliance: M2M cap + input or output caps should be an error.
+
+Hans de Goede (6):
+ libv4lcontrol: Check control_flags before doing wildcard maching on upside_down
+ libv4lcontrol: Add Asus F3Sc with 04f2:b012 cam as upside down false positive
+ libv4l2: decomress-helper: close fds then wait for helper to exit
+ rc_keymaps: Add a keymap for the remote shipped with allwinner ba10 tv boxes
+ rc_keymaps: Add a keymap for the remote shipped with allwinner i12-a20 tv boxes
+ rc_keymaps: Add keymap for the remote shipped with the Wobo i5 tv box
+
+Hans-Christian Egtvedt (8):
+ v4l2-ctl: remove unnecessary inclusion of libv4l2.h
+ v4l2-compliance/ctl: drop libv4l2 dependency if NO_LIBV4L2 is defined
+ Add static configuration file for Android builds
+ v4l2-ctl/dbg: include android-config.h header file if ANDROID is set
+ v4l2-compliance: add Android.mk makefile
+ v4l2-ctl: add Android.mk makefile
+ v4l2-dbg: add Android.mk makefile
+ INSTALL: add cross compile and install procedures for Android
+
+Lad, Prabhakar (2):
+ libv4l: Update the README name for libv4l
+ libv4l: Update the link pointing the patch for porting the application to libv4l2
+
+Laurent Pinchart (17):
+ Import the media-ctl utility and libraries
+ media-ctl: Rename source files
+ media-ctl: Remove the obsolete device argument from the help text
+ media-ctl: Document the --links option argument
+ media-ctl: Always print the full help message
+ media-ctl: Don't install libmediactl and libv4l2subdev
+ media-ctl: Update copyright years
+ media-ctl: Fix off-by-one buffer overflow with readlink
+ media-ctl: Fix media device version printing
+ media-ctl: Add fall through comment to fix Coverity warning
+ media-ctl: libv4l2subdev: Add DV timings support
+ media-ctl: Move flags printing code to a new print_flags function
+ media-ctl: Add DV timings support
+ Update sync-with-kernel to use installed kernel headers
+ wip
+ media-ctl: Pass a positive error value to strerror()
+ Revert "wip"
+
+Martin Bugge (1):
+ v4l2-ctl: add EDID get and set options
+
+Mauro Carvalho Chehab (166):
+ dvbv5-scan: Allow using separate adapter for FE and demux
+ libdvbv5: add descriptor parser for ATSC TVCT/CVCT tables
+ libdvbv5: fix VCT parsing
+ libdvbv5: Add ATSC specific descriptors
+ libdvbv5: add parser for ATSC service location
+ libdvbv5: Add support for additional descriptors at VCT table
+ libdvbv5: Add table ID of extra NIT/SDT tables
+ libdvbv5/dvb-scan: Modify to use the newer TS tables parser
+ libdvbv5: move DVB scan handler code to a separate file
+ libdvbv5: move handler code to a separate file
+ libdvbv5: move all tables structs to the handler data
+ libdvbv5: fixup parsing of PMT tables
+ libdvbv5: Add a parser for extension descriptors
+ libdvbv5/dvb-scan: handle allocation errors
+ libdvbv5/dvb-scan: be more verbose in debug mode
+ libdvbv5/dvb-scan: Fix a series of checks at buffer handling
+ libdvbv5/parse_string: don't free twice
+ libdvbv5: better handle memory errors
+ libdvbv5/descriptors: print descriptor number in hexadecimal
+ descriptors/nit: byte struct should be packed
+ libdvbv5/descriptors: Make easier to read/edit the descriptors table
+ libdvbv5: add support for ISDBT terrestrial system descriptor
+ libdvbv5: add parser for TS information descriptor
+ libdvbv5: Add descriptors for virtual channel number
+ libdvbv5: Add support for partial reception
+ libdvbv5: add suport for DVB-T2 delivery descriptor
+ libdvbv5: avoid playing with memory
+ libdvbv5/dvb-scan-table-handler:free the new table descriptors
+ libdvbv5: Add some missing code to free data
+ libdvbv5: Better handle program data
+ libdvbv5/dvb-fe: make valgrind happy
+ libdvbv5/descriptors: descriptors data should always be freed
+ libdvbv5/dvb-scan: fix memory leak
+ libdvbv5/dvb-scan-table-handler: remove free of unallocated structs
+ libdvbv5: produce dvb data from the new structures
+ libdvbv5/dvb-file: use the new descriptors for virtual channel
+ libdvbv5/dvb-file: fix allocation of dvb_file
+ libdvbv5/dvb-file: fix parameters for dvb_vchannel()
+ Fix desc_frequency_list descriptor
+ libdvbv5: add support for ATSC VCT table parsing
+ libdvbv5: On ATSC, only try to get SDT if VCT is not found
+ libdvbv5: don't leak memory on ATSC service location
+ dvb-fe: don't cause memory leak on open errors
+ dvbv5-scan: release resources on errors
+ libdvbv5/dvb-file: Allow using SDT for ATSC
+ libdvbv5/dvb-scan: avoid memory leak on table read timeout
+ dvb/dvbv5-zap: Fix help message
+ libdvbv5/dvb-scan: require PAT also for ATSC
+ libdvbv5/dvb-file: Fix the logic for program found check
+ libdvbv5/descriptors: Fix error handling routine
+ libdvbv5/descriptors: Fix extension descriptor handling
+ libdvbv5/descriptors: don't leak memory on error
+ libdvbv5/dvb-file: Don't leave memory leaks on channel store failure
+ libdvbv5: avoid nit to read out of the buffer
+ libdvbv5: be sure to not go past buffer on PAT parsing
+ libdvbv5: add multisection support for PAT table
+ libdvbv5: fix debug msg for Network PID
+ libdvbv5: don't cause crash if NIT is missing on fe-file.c
+ libdvbv5: Add missing dvb_dmx_stop() on error handling
+ libdvbv5: be sure to not go past buffer on PMT parsing
+ libdvbv5: be sure to not go past buffer on SDT parsing
+ libdvbv5: be sure to not go past buffer on VCT parsing
+ libdvbv5: shut up a few compilation warnings
+ libdvbv5: improve debug messages
+ libdvbv5/dvb-file: describe the service type on the logs
+ dvbv5-scan: move scanning code into dvb_scan_transponder()
+ libdvbv5: Re-add NIT transponders addition
+ libdvbv5: Re-add parser for ISDB-T NIT transponders addition
+ libdvbv5: Re-add parser for ISDB-T NIT transponders addition
+ libdvbv5: add support for DVB-S/S2 at NIT parser
+ libdvbv5: add support for DVB-T2 at NIT parser
+ libdvbv5: remove the remaining bits from the NIT parsers
+ libdvbv5: better implement the NIT parser
+ libdvbv5: properly handle ISDB-T partial reception
+ libdvbv5: get rid of dvb-scan-table-handler.[ch]
+ libdvbv5: handle NIT descriptors when verbose is not enabled
+ libdvbv5: Improve descriptor error logs
+ libdvbv5: Fix the size of the LCN descriptor
+ libdvbv5: some error handling improvements on dvb-file
+ libdvbv5/descriptors.c: fix two warnings
+ dvbv5-zap: allow using transponder frequency while in monitor mode
+ dvbv5-zap: make Valgrind happy
+ libdvbv5: clear data before setting a dmx filter
+ libdvbv5/dvb-demux: fix CodingStyle
+ dvbv5-zap: handle timeout also while in monitor mode
+ dvbv5-zap: exit nicely on SIGTERM/SIGINT
+ dvbv5-scan: handle SIGTERM/SIGINT nicely
+ dvbv5-zap: only handle SIGALRM if need
+ libdvbv5: fix extension descriptor handler
+ libdvbv5: fix T2 delivery descriptor handler
+ libdvbv5: fix dvb-scan handler for T2 descriptor
+ libdvbv5: fix terrestrial delivery constellation table
+ libdvbv5: change log level for the two nit handler messages
+ libdvbv5/dvb-scan: Remove dead code and add a check after realloc()
+ libdvbv5: don't use realloc() inside pat.c
+ dvbv5-scan: fix detection of duplicated freqs at the input file
+ libdvbv5: fix error condition on ATSC service location descriptor
+ libdvbv5: fix error condition on ISDBT delivery descriptor
+ libdvbv5: Fix other error conditions for out of memory
+ dvb5-zap: Better handle the MPEG TS header
+ libdvbv5/dvb-scan: all tables should have an specified size
+ libdvbv5: pack NIT table
+ libdvbv5: fix other error conditions for out of memory
+ libdvbv5: fix some out-of-bound acesses on hexdump()
+ libdvbv5: Simplify PAT handling
+ libdvbv5: simplify NIT table parser
+ libdvbv5: cleanup PAT table parser
+ libdvbv5: simplify PMT table parser
+ libdvbv5: simplify SDT table parser
+ libdvbv5: simplify VCT table parser
+ dvb/README: Remove some obsolete data
+ dvbv5-zap: fix all-pids record mode
+ libdvbv5: fix memory leak at ISDB partial reception handler
+ libdvbv5: Fix memory leak at TS info handler
+ dvb-fe: be a little less verbose with verbosity level 1
+ dvbv5-zap: on all pids mode, we can use the frequency
+ dvbv5-zap: fix frontend status handling
+ dvbv5-zap: allow using a frequency for a channel on exit after tuning
+ libdvbv5: Fix a warning at isdb_desc_partial_reception_free
+ libdvbv5: fix retrieve parameters for ISDB-T
+ libdvbv5/dvb-fe: Fall back to v3 if needed
+ libdvbv5: Only discard the services not found
+ dvb-fe: fix using a DVB-T file for ISDB-T
+ dvb: simplify the logic that sets a (compat) DTV delivery system
+ dvb-scan: remove ISDB-T hack from it
+ libdvbv5: fix get_frontend logic
+ Replace my email address with the new one
+ libdvbv5: move store/retrieve functions upper
+ libdvbv5: better handle ATSC/Annex B
+ dvb-scan: fix a print message
+ descriptors: be sure to not read past the buffer
+ vct: avoid read descriptors past the buffer
+ dvb-demux: add code for DVB section filter
+ dvb: Fix VCT handling
+ dvb-scan: don't handle NIT table by default on ATSC
+ dvb-fe: Add support for setting the LNA before tuning
+ dvb: add support for LNA setting at scan and zap
+ dvb-fe: Use a separate call to change LNA settings
+ Add a parser for drxj
+ Revert "dvb-scan: don't handle NIT table by default on ATSC"
+ libdvbv5: better document some MPEG TS fields
+ libdvbv5: reimplement the logic that gets a full section
+ dvbv5-zap: only start audio filtering if audio PID > 0
+ libdvbv5: Frequency is unsigned. use %u to print it
+ libdvbv5: fix ISDB-T frequency calculus on 32 bits machines
+ libdvbv5: move ISDB-T frq conversion to the descriptors code
+ libdvbv5: fix the area code size on ISDB-T
+ dvbv5-zap: fix usage of --record without --output
+ dvbv5-zap: Make dvbv5 as the default format
+ dvbv5-zap: better implement the --record flag
+ dvbv5-zap: only open the DVR interface if outputing
+ dvb-zap: fix --search argument
+ libdvbv5: Change license to LGPL v2.1
+ libdvbv5: Remove two warnings on 32 bits compilation
+ Revert "libdvbv5: Change license to LGPL v2.1"
+ libdvbv5: don't override a parameter when setting lna
+ libdvbv5: Fix the speedup scan condition
+ dvb-file: Fix bandwidth handling at online write function
+ contrib: add a parser for dib0700
+ parse_dib0700.pl: parse the remaining messages on dib0700
+ parse_dib0700.pl: improve parser
+ parse_dib0700.pl: add support to identify delays
+ parse_dib0700.pl: Make the delays multiple of 10ms
+ parse_dib0700.pl: autoflush writes
+ parse_dib0700.pl: Parse REQUEST_SET_I2C_PARAM
+ parse_dib0700.pl: parse REQUEST_GET_VERSION
+
+Ricardo Ribalda Delgado (2):
+ libv4lconvert: Support for Y16 pixel format
+ libv4lconvert: Support for RGB32 and BGR32 format
+
+Rob Barker (1):
+ libdvbv5: Find other TS in NIT pointer fix
+
+Stefan Ringel (1):
+ v4l-utils: bugfix memory chunk
+
+Thiago Santos (1):
+ libv4l2: release the lock before doing a DQBUF
+
+
+
v4l-utils-1.0.0
---------------
diff --git a/INSTALL b/INSTALL
index 6caa0f22..a26e1a09 100644
--- a/INSTALL
+++ b/INSTALL
@@ -44,3 +44,30 @@ export PKG_CONFIG_LIBDIR=/path/to/cross/root/lib
./configure --host=arm-linux-gnueabihf --without-jpeg
make
+Android Cross Compiling and Installing:
+----------------
+
+v4l-utils will only build using the complete AOSP source tree, because of the
+stlport dependency.
+
+List of v4l-utils that supply an Android.mk makefile:
+* utils/v4l2-compliance
+* utils/v4l2-ctl
+* utils/v4l2-dbg
+
+To cross compile an utility you must first configure the shell with Android's
+envsetup.sh to add the mm alias, before running lunch to select your target
+device.
+
+cd /path/to/aosp
+source build/envsetup.sh
+lunch
+cd /path/to/v4l-utils
+cd <utility>
+mm
+
+Output binary will be located in the Android out directory, below the
+target/product/<name>/system/bin/<v4l-utils executable name> path.
+
+The binary executable can be pushed to the target Android device using
+adb push <v4l-utils executable> /system/bin
diff --git a/Makefile.am b/Makefile.am
index 2e65b20c..cc48c2d7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,34 +7,37 @@ if WITH_V4LUTILS
SUBDIRS += utils contrib
endif
-EXTRA_DIST = include COPYING.libv4l README.libv4l README.lib-multi-threading
+EXTRA_DIST = android-config.h include COPYING.libv4l README.libv4l README.lib-multi-threading
# custom targets
sync-with-kernel:
- @if [ ! -f $(KERNEL_DIR)/include/uapi/linux/videodev2.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/fb.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/v4l2-controls.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/v4l2-common.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/v4l2-subdev.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/ivtv.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/dvb/frontend.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/dvb/dmx.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/dvb/audio.h -o \
- ! -f $(KERNEL_DIR)/include/uapi/linux/dvb/video.h ]; then \
+ @if [ ! -f $(KERNEL_DIR)/usr/include/linux/videodev2.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/fb.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/v4l2-controls.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/v4l2-common.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/v4l2-subdev.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/v4l2-mediabus.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/ivtv.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/dvb/frontend.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/dvb/dmx.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/dvb/audio.h -o \
+ ! -f $(KERNEL_DIR)/usr/include/linux/dvb/video.h ]; then \
echo "Error you must set KERNEL_DIR to point to an extracted kernel source dir"; \
+ echo "and run 'make headers_install' in \$$KERNEL_DIR."; \
exit 1; \
fi
- cp -a $(KERNEL_DIR)/include/uapi/linux/videodev2.h $(top_srcdir)/include/linux
- cp -a $(KERNEL_DIR)/include/uapi/linux/fb.h $(top_srcdir)/include/linux
- cp -a $(KERNEL_DIR)/include/uapi/linux/v4l2-controls.h $(top_srcdir)/include/linux
- cp -a $(KERNEL_DIR)/include/uapi/linux/v4l2-common.h $(top_srcdir)/include/linux
- cp -a $(KERNEL_DIR)/include/uapi/linux/v4l2-subdev.h $(top_srcdir)/include/linux
- cp -a $(KERNEL_DIR)/include/uapi/linux/ivtv.h $(top_srcdir)/include/linux
- cp -a $(KERNEL_DIR)/include/uapi/linux/dvb/frontend.h $(top_srcdir)/include/linux/dvb
- cp -a $(KERNEL_DIR)/include/uapi/linux/dvb/dmx.h $(top_srcdir)/include/linux/dvb
- cp -a $(KERNEL_DIR)/include/uapi/linux/dvb/audio.h $(top_srcdir)/include/linux/dvb
- cp -a $(KERNEL_DIR)/include/uapi/linux/dvb/video.h $(top_srcdir)/include/linux/dvb
+ cp -a $(KERNEL_DIR)/usr/include/linux/videodev2.h $(top_srcdir)/include/linux
+ cp -a $(KERNEL_DIR)/usr/include/linux/fb.h $(top_srcdir)/include/linux
+ cp -a $(KERNEL_DIR)/usr/include/linux/v4l2-controls.h $(top_srcdir)/include/linux
+ cp -a $(KERNEL_DIR)/usr/include/linux/v4l2-common.h $(top_srcdir)/include/linux
+ cp -a $(KERNEL_DIR)/usr/include/linux/v4l2-subdev.h $(top_srcdir)/include/linux
+ cp -a $(KERNEL_DIR)/usr/include/linux/v4l2-mediabus.h $(top_srcdir)/include/linux
+ cp -a $(KERNEL_DIR)/usr/include/linux/ivtv.h $(top_srcdir)/include/linux
+ cp -a $(KERNEL_DIR)/usr/include/linux/dvb/frontend.h $(top_srcdir)/include/linux/dvb
+ cp -a $(KERNEL_DIR)/usr/include/linux/dvb/dmx.h $(top_srcdir)/include/linux/dvb
+ cp -a $(KERNEL_DIR)/usr/include/linux/dvb/audio.h $(top_srcdir)/include/linux/dvb
+ cp -a $(KERNEL_DIR)/usr/include/linux/dvb/video.h $(top_srcdir)/include/linux/dvb
$(MAKE) -C utils/keytable $@
$(MAKE) -C utils/xc3028-firmware $@
diff --git a/android-config.h b/android-config.h
new file mode 100644
index 00000000..f4743304
--- /dev/null
+++ b/android-config.h
@@ -0,0 +1,360 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* alsa library is present */
+/* #undef HAVE_ALSA */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define if you have the iconv() function and it works. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* whether we use libjpeg */
+/* #undef HAVE_JPEG */
+
+/* Define to 1 if you have the `klogctl' function. */
+#define HAVE_KLOGCTL 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* qt has opengl support */
+/* #undef HAVE_QTGL */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/klog.h> header file. */
+#define HAVE_SYS_KLOG_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 or 0, depending whether the compiler supports simple visibility
+ declarations. */
+#define HAVE_VISIBILITY 1
+
+/* Define as const if the declaration of iconv() needs const. */
+/* #undef ICONV_CONST */
+
+/* ir-keytable preinstalled tables directory */
+#define IR_KEYTABLE_SYSTEM_DIR "/lib/udev/rc_keymaps"
+
+/* ir-keytable user defined tables directory */
+#define IR_KEYTABLE_USER_DIR "/system/etc/rc_keymaps"
+
+/* libv4l1 private lib directory */
+#define LIBV4L1_PRIV_DIR "/system/lib/libv4l"
+
+/* libv4l2 plugin directory */
+#define LIBV4L2_PLUGIN_DIR "/system/lib/libv4l/plugins"
+
+/* libv4l2 private lib directory */
+#define LIBV4L2_PRIV_DIR "/system/lib/libv4l"
+
+/* libv4lconvert private lib directory */
+#define LIBV4LCONVERT_PRIV_DIR "/system/lib/libv4l"
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "v4l-utils"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "v4l-utils"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "v4l-utils 1.1.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "v4l-utils"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.1.0"
+
+/* Define to the type that is the result of default argument promotions of
+ type mode_t. */
+#define PROMOTED_MODE_T int
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* v4l-utils version string */
+#define V4L_UTILS_VERSION "1.1.0"
+
+/* Version number of package */
+#define VERSION "1.1.0"
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
+
+/*
+ * Import strchrnul(...) from uClibc version 0.9.33.2 since this feature is
+ * missing in the Android C library.
+ */
+
+/* Copyright (C) 1991,93,94,95,96,97,99,2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+ with help from Dan Sahlin (dan@sics.se) and
+ bug fix and commentary by Jim Blandy (jimb@ai.mit.edu);
+ adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+ and implemented by Roland McGrath (roland@ai.mit.edu).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <string.h>
+#include <stdlib.h>
+
+/* Find the first occurrence of C in S or the final NUL byte. */
+static inline char *strchrnul (const char *s, int c_in)
+{
+ const unsigned char *char_ptr;
+ const unsigned long int *longword_ptr;
+ unsigned long int longword, magic_bits, charmask;
+ unsigned char c;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the first few characters by reading one character at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s;
+ ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;
+ ++char_ptr)
+ if (*char_ptr == c || *char_ptr == '\0')
+ return (char *) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to 8-byte longwords. */
+
+ longword_ptr = (unsigned long int *) char_ptr;
+
+ /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
+ the "holes." Note that there is a hole just to the left of
+ each byte, with an extra at the end:
+
+ bits: 01111110 11111110 11111110 11111111
+ bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+ The 1-bits make sure that carries propagate to the next 0-bit.
+ The 0-bits provide holes for carries to fall into. */
+ switch (sizeof (longword))
+ {
+ case 4: magic_bits = 0x7efefeffL; break;
+ case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;
+ default:
+ abort ();
+ }
+
+ /* Set up a longword, each of whose bytes is C. */
+ charmask = c | (c << 8);
+ charmask |= charmask << 16;
+ if (sizeof (longword) > 4)
+ /* Do the shift in two steps to avoid a warning if long has 32 bits. */
+ charmask |= (charmask << 16) << 16;
+ if (sizeof (longword) > 8)
+ abort ();
+
+ /* Instead of the traditional loop which tests each character,
+ we will test a longword at a time. The tricky part is testing
+ if *any of the four* bytes in the longword in question are zero. */
+ for (;;)
+ {
+ /* We tentatively exit the loop if adding MAGIC_BITS to
+ LONGWORD fails to change any of the hole bits of LONGWORD.
+
+ 1) Is this safe? Will it catch all the zero bytes?
+ Suppose there is a byte with all zeros. Any carry bits
+ propagating from its left will fall into the hole at its
+ least significant bit and stop. Since there will be no
+ carry from its most significant bit, the LSB of the
+ byte to the left will be unchanged, and the zero will be
+ detected.
+
+ 2) Is this worthwhile? Will it ignore everything except
+ zero bytes? Suppose every byte of LONGWORD has a bit set
+ somewhere. There will be a carry into bit 8. If bit 8
+ is set, this will carry into bit 16. If bit 8 is clear,
+ one of bits 9-15 must be set, so there will be a carry
+ into bit 16. Similarly, there will be a carry into bit
+ 24. If one of bits 24-30 is set, there will be a carry
+ into bit 31, so all of the hole bits will be changed.
+
+ The one misfire occurs when bits 24-30 are clear and bit
+ 31 is set; in this case, the hole at bit 31 is not
+ changed. If we had access to the processor carry flag,
+ we could close this loophole by putting the fourth hole
+ at bit 32!
+
+ So it ignores everything except 128's, when they're aligned
+ properly.
+
+ 3) But wait! Aren't we looking for C as well as zero?
+ Good point. So what we do is XOR LONGWORD with a longword,
+ each of whose bytes is C. This turns each byte that is C
+ into a zero. */
+
+ longword = *longword_ptr++;
+
+ /* Add MAGIC_BITS to LONGWORD. */
+ if ((((longword + magic_bits)
+
+ /* Set those bits that were unchanged by the addition. */
+ ^ ~longword)
+
+ /* Look at only the hole bits. If any of the hole bits
+ are unchanged, most likely one of the bytes was a
+ zero. */
+ & ~magic_bits) != 0 ||
+
+ /* That caught zeroes. Now test for C. */
+ ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))
+ & ~magic_bits) != 0)
+ {
+ /* Which of the bytes was C or zero?
+ If none of them were, it was a misfire; continue the search. */
+
+ const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
+
+ if (*cp == c || *cp == '\0')
+ return (char *) cp;
+ if (*++cp == c || *cp == '\0')
+ return (char *) cp;
+ if (*++cp == c || *cp == '\0')
+ return (char *) cp;
+ if (*++cp == c || *cp == '\0')
+ return (char *) cp;
+ if (sizeof (longword) > 4)
+ {
+ if (*++cp == c || *cp == '\0')
+ return (char *) cp;
+ if (*++cp == c || *cp == '\0')
+ return (char *) cp;
+ if (*++cp == c || *cp == '\0')
+ return (char *) cp;
+ if (*++cp == c || *cp == '\0')
+ return (char *) cp;
+ }
+ }
+ }
+
+ /* This should never happen. */
+ return NULL;
+}
+
+/*
+ * Import getsubopt(...) from uClibc version 0.9.33.2 since this feature is
+ * missing in the Android C library.
+ */
+
+/* Parse comma separate list into words.
+ Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdlib.h>
+#include <string.h>
+
+/* Parse comma separated suboption from *OPTIONP and match against
+ strings in TOKENS. If found return index and set *VALUEP to
+ optional value introduced by an equal sign. If the suboption is
+ not part of TOKENS return in *VALUEP beginning of unknown
+ suboption. On exit *OPTIONP is set to the beginning of the next
+ token or at the terminating NUL character. */
+static inline int
+getsubopt (char **optionp, char *const *tokens, char **valuep)
+{
+ char *endp, *vstart;
+ int cnt;
+
+ if (**optionp == '\0')
+ return -1;
+
+ /* Find end of next token. */
+ endp = strchrnul (*optionp, ',');
+
+ /* Find start of value. */
+ vstart = (char *) memchr (*optionp, '=', endp - *optionp);
+ if (vstart == NULL)
+ vstart = endp;
+
+ /* Try to match the characters between *OPTIONP and VSTART against
+ one of the TOKENS. */
+ for (cnt = 0; tokens[cnt] != NULL; ++cnt)
+ if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0
+ && tokens[cnt][vstart - *optionp] == '\0')
+ {
+ /* We found the current option in TOKENS. */
+ *valuep = vstart != endp ? vstart + 1 : NULL;
+
+ if (*endp != '\0')
+ *endp++ = '\0';
+ *optionp = endp;
+
+ return cnt;
+ }
+
+ /* The current suboption does not match any option. */
+ *valuep = *optionp;
+
+ if (*endp != '\0')
+ *endp++ = '\0';
+ *optionp = endp;
+
+ return -1;
+}
diff --git a/configure.ac b/configure.ac
index 4080d1ec..bea16e91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT([v4l-utils],[1.1.0])
+AC_INIT([v4l-utils],[1.3.0])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
@@ -24,6 +24,7 @@ AC_CONFIG_FILES([Makefile
utils/decode_tm6000/Makefile
utils/dvb/Makefile
utils/keytable/Makefile
+ utils/media-ctl/Makefile
utils/rds/Makefile
utils/v4l2-compliance/Makefile
utils/v4l2-ctl/Makefile
@@ -145,6 +146,27 @@ else
AC_MSG_WARN(ALSA library not available)
fi
+AC_ARG_WITH([libudev],
+ AS_HELP_STRING([--with-libudev],
+ [Enable libudev to detect a device name]))
+
+AS_IF([test "x$with_libudev" = "xyes"],
+ [PKG_CHECK_MODULES(libudev, libudev, have_libudev=yes, have_libudev=no)],
+ [have_libudev=no])
+
+AS_IF([test "x$have_libudev" = "xyes"],
+ [
+ AC_DEFINE([HAVE_LIBUDEV], [], [Use libudev])
+ LIBUDEV_CFLAGS="$libudev_CFLAGS"
+ LIBUDEV_LIBS="$libudev_LIBS"
+ AC_SUBST(LIBUDEV_CFLAGS)
+ AC_SUBST(LIBUDEV_LIBS)
+ ],
+ [AS_IF([test "x$with_libudev" = "xyes"],
+ [AC_MSG_ERROR([libudev requested but not found])
+ ])
+])
+
AC_SUBST([JPEG_LIBS])
# The dlopen() function is in the C library for *BSD and in
@@ -216,10 +238,10 @@ AC_DEFINE_DIR([IR_KEYTABLE_USER_DIR], [keytableuserdir], [ir-keytable user defin
# options
AC_ARG_ENABLE(libdvbv5,
- AS_HELP_STRING([--enable-libdvbv5], [enable experimental dynamic libdvbv5 compilation]),
+ AS_HELP_STRING([--disable-libdvbv5], [disable experimental dynamic libdvbv5 compilation]),
[case "${enableval}" in
yes | no ) ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-libdvbv5) ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --disable-libdvbv5) ;;
esac]
)
@@ -227,7 +249,7 @@ AC_ARG_ENABLE(libv4l,
AS_HELP_STRING([--disable-libv4l], [disable dynamic libv4l compilation]),
[case "${enableval}" in
yes | no ) ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-libv4l) ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --disable-libv4l) ;;
esac]
)
@@ -235,7 +257,7 @@ AC_ARG_ENABLE(v4l-utils,
AS_HELP_STRING([--disable-v4l-utils], [disable v4l-utils compilation]),
[case "${enableval}" in
yes | no ) ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-v4l-utils) ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --disable-v4l-utils) ;;
esac]
)
@@ -247,17 +269,17 @@ AC_ARG_ENABLE(qv4l2,
esac]
)
-AM_CONDITIONAL([WITH_LIBDVBV5], [test x$enable_libdvbv5 = xyes])
-AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno])
-AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4l_utils != "xno"])
-AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno])
-AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno])
+AM_CONDITIONAL([WITH_LIBDVBV5], [test x$enable_libdvbv5 != xno])
+AM_CONDITIONAL([WITH_LIBV4L], [test x$enable_libv4l != xno])
+AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4l_utils != xno -a x$linux_os = xyes])
+AM_CONDITIONAL([WITH_QV4L2], [test ${qt_pkgconfig} = true -a x$enable_qv4l2 != xno])
+AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_libv4l != xno -a x$enable_shared != xno])
AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_libv4l != xno -a x$enable_shared != xno])
-AM_CONDITIONAL([WITH_QTGL], [test ${qt_pkgconfig_gl} = true])
+AM_CONDITIONAL([WITH_QTGL], [test ${qt_pkgconfig_gl} = true])
# append -static to libtool compile and link command to enforce static libs
-AS_IF([test x$enable_libdvbv5 != xyes], [AC_SUBST([ENFORCE_LIBDVBV5_STATIC], ["-static"])])
-AS_IF([test x$enable_libv4l = xno], [AC_SUBST([ENFORCE_LIBV4L_STATIC], ["-static"])])
+AS_IF([test x$enable_libdvbv5 = xno], [AC_SUBST([ENFORCE_LIBDVBV5_STATIC], ["-static"])])
+AS_IF([test x$enable_libv4l = xno], [AC_SUBST([ENFORCE_LIBV4L_STATIC], ["-static"])])
# misc
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index ef538309..3ec5cb0d 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -14,10 +14,10 @@ EXTRA_DIST = \
az6007 \
cx231xx \
cx25821 \
+ dib0700 \
em28xx \
m920x \
pci_traffic \
- qv4l2-qt3 \
saa7134 \
sn9c201 \
tm6000 \
diff --git a/contrib/az6007/parse_az6007.pl b/contrib/az6007/parse_az6007.pl
index 342b8598..342b8598 100644..100755
--- a/contrib/az6007/parse_az6007.pl
+++ b/contrib/az6007/parse_az6007.pl
diff --git a/contrib/cx231xx/parse_cx231xx.pl b/contrib/cx231xx/parse_cx231xx.pl
index 6f402020..6f402020 100644..100755
--- a/contrib/cx231xx/parse_cx231xx.pl
+++ b/contrib/cx231xx/parse_cx231xx.pl
diff --git a/contrib/dib0700/parse_dib0700.pl b/contrib/dib0700/parse_dib0700.pl
new file mode 100755
index 00000000..c383cfce
--- /dev/null
+++ b/contrib/dib0700/parse_dib0700.pl
@@ -0,0 +1,231 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2008-2011 Mauro Carvalho Chehab
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+
+use strict;
+
+# Enable autoflush
+BEGIN { $| = 1 }
+
+my $min_delay = 10;
+
+my %req_map = (
+ 0x0 => "REQUEST_SET_USB_XFER_LEN",
+ 0x2 => "REQUEST_I2C_READ",
+ 0x3 => "REQUEST_I2C_WRITE",
+ 0x4 => "REQUEST_POLL_RC",
+ 0x8 => "REQUEST_JUMPRAM",
+ 0xB => "REQUEST_SET_CLOCK",
+ 0xC => "REQUEST_SET_GPIO",
+ 0xF => "REQUEST_ENABLE_VIDEO",
+ 0x10 => "REQUEST_SET_I2C_PARAM",
+ 0x11 => "REQUEST_SET_RC",
+ 0x12 => "REQUEST_NEW_I2C_READ",
+ 0x13 => "REQUEST_NEW_I2C_WRITE",
+ 0x15 => "REQUEST_GET_VERSION",
+);
+
+my %gpio_map = (
+ 0 => "GPIO0",
+ 2 => "GPIO1",
+ 3 => "GPIO2",
+ 4 => "GPIO3",
+ 5 => "GPIO4",
+ 6 => "GPIO5",
+ 8 => "GPIO6",
+ 10 => "GPIO7",
+ 11 => "GPIO8",
+ 14 => "GPIO9",
+ 15 => "GPIO10",
+);
+
+sub type_req($)
+{
+ my $reqtype = shift;
+ my $s;
+
+ if ($reqtype & 0x80) {
+ $s = "RD ";
+ } else {
+ $s = "WR ";
+ }
+ if (($reqtype & 0x60) == 0x20) {
+ $s .= "CLAS ";
+ } elsif (($reqtype & 0x60) == 0x40) {
+ $s .= "VEND ";
+ } elsif (($reqtype & 0x60) == 0x60) {
+ $s .= "RSVD ";
+ }
+
+ if (($reqtype & 0x1f) == 0x00) {
+ $s .= "DEV ";
+ } elsif (($reqtype & 0x1f) == 0x01) {
+ $s .= "INT ";
+ } elsif (($reqtype & 0x1f) == 0x02) {
+ $s .= "EP ";
+ } elsif (($reqtype & 0x1f) == 0x03) {
+ $s .= "OTHER ";
+ } elsif (($reqtype & 0x1f) == 0x04) {
+ $s .= "PORT ";
+ } elsif (($reqtype & 0x1f) == 0x05) {
+ $s .= "RPIPE ";
+ } else {
+ $s .= sprintf "RECIP 0x%02x ", $reqtype & 0x1f;
+ }
+
+ $s =~ s/\s+$//;
+ return $s;
+}
+
+my $delay = 0;
+
+while (<>) {
+ tr/A-F/a-f/;
+
+ if (m/(.*)([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].)\s*[\<\>]+\s*(.*)/) {
+ my $prev = $1;
+ my $reqtype = hex($2);
+ my $req = hex($3);
+ my $wvalue = hex("$5$4");
+ my $windex = hex("$7$6");
+ my $wlen = hex("$9$8");
+ my $payload = $10;
+ my @bytes = split(/ /, $payload);
+ for (my $i = 0; $i < scalar(@bytes); $i++) {
+ $bytes[$i] = hex($bytes[$i]);
+ }
+
+ if (defined($req_map{$req})) {
+ $req = $req_map{$req};
+ } else {
+ $req = sprintf "0x%02x", $req;
+ }
+
+ printf "msleep(%d);\n", $delay if ($delay);
+ $delay = 0;
+
+ if (m/(IN|OUT): (\d+) ms \d+ ms/) {
+ $delay = $min_delay * int(($2 + $min_delay / 2) / $min_delay);
+ }
+
+ if ($req eq "REQUEST_I2C_READ") {
+ my $txlen = ($wvalue >> 8) + 2;
+ my $addr = sprintf "0x%02x >> 1", $wvalue & 0xfe;
+ my $val;
+
+ if ($txlen == 2) {
+ printf("dib0700_i2c_read($addr); /* $payload */\n");
+ next;
+ } elsif ($txlen == 3) {
+ $val = $windex >> 8;
+ printf("dib0700_i2c_read($addr, %d); /* $payload */\n", $val);
+ next;
+ } elsif ($txlen == 4) {
+ $val = $windex;
+ printf("dib0700_i2c_read($addr, %d); /* $payload */\n", $val);
+ next;
+ }
+ }
+
+ if ($req eq "REQUEST_I2C_WRITE") {
+ if ($wlen == 5 || $wlen == 6) {
+ my $addr = sprintf "0x%02x >> 1", $bytes[1];
+ my $reg = sprintf "0x%04x", $bytes[2] << 8 | $bytes[3];
+ my $val;
+ if ($wlen == 6) {
+ $val = sprintf "%d", $bytes[4] << 8 | $bytes[5];
+ } else {
+ $val = sprintf "%d", $bytes[4];
+ }
+ printf("dib0700_i2c_write($addr, $reg, $val);\n");
+ next;
+ }
+ }
+
+ if ($req eq "REQUEST_SET_I2C_PARAM") {
+ my $divider1 = $bytes[2] << 8 | $bytes[3];
+ my $divider2 = $bytes[4] << 8 | $bytes[5];
+ my $divider3 = $bytes[6] << 8 | $bytes[7];
+
+ my $xclk1 = 30000/$divider1;
+ my $xclk2 = 72000/$divider2;
+ my $xclk3 = 72000/$divider3;
+
+ if ($xclk1 == $xclk2 && $xclk2 == $xclk3) {
+ printf("dib0700_set_i2c_speed(adap->dev, $xclk1 /* kHz */);\n");
+ next;
+ }
+ printf("dib0700_set_i2c_speed: $divider1 ($xclk1 kHz), $divider2 ($xclk2 kHz), $divider3 ($xclk3 kHz)\n");
+ next;
+ }
+
+ if ($req eq "REQUEST_GET_VERSION") {
+ my $hwversion = $bytes[0] << 24 | $bytes[1] << 16 | $bytes[2] << 8 | $bytes[3];
+ my $romversion = $bytes[4] << 24 | $bytes[5] << 16 | $bytes[6] << 8 | $bytes[7];
+ my $fw_version = $bytes[8] << 24 | $bytes[9] << 16 | $bytes[10] << 8 | $bytes[11];
+ my $fwtype = $bytes[12] << 24 | $bytes[13] << 16 | $bytes[14] << 8 | $bytes[15];
+
+ printf("dib0700_get_version(adap->dev, NULL, NULL, NULL, NULL); /* hw: 0x%x rom: 0x%0x fw version: 0x%x, fw type: 0x%x */\n",
+ $hwversion, $romversion, $fw_version, $fwtype);
+ next;
+ }
+
+ if ($req eq "REQUEST_SET_GPIO") {
+ my $gpio = $bytes[1];
+ my $v = $bytes[2];
+
+ my $dir = "GPIO_IN";
+ my $val = 0;
+
+ $dir = "GPIO_OUT" if ($v & 0x80);
+ $val = 1 if ($v & 0x40);
+
+ if (!($v & 0x3f)) {
+ $gpio = $gpio_map{$gpio} if (defined($gpio_map{$gpio}));
+ printf("dib0700_set_gpio(adap->dev, $gpio, $dir, $val);\n");
+ next;
+ }
+ }
+
+ if (($reqtype & 0xf0) == 0xc0) {
+ my $txlen = ($wvalue >> 8) + 2;
+ my $addr = $req;
+ my $val;
+
+ if ($txlen == 2) {
+ printf("dib0700_ctrl_rd(adap->dev, $txlen, { cmd, $addr }, &buf, $wlen); /* $payload */\n");
+ next;
+ } elsif ($txlen == 3) {
+ $val = $windex >> 8;
+ printf("dib0700_ctrl_rd(adap->dev, $txlen, { cmd, $addr, $val }, &buf, $wlen); /* $payload */\n");
+ next;
+ } elsif ($txlen == 4) {
+ $val = $windex;
+ printf("dib0700_ctrl_rd(adap->dev, $txlen, { cmd, $addr, $val }, &buf, $wlen); /* $payload */\n");
+ next;
+ }
+ }
+ if ($wvalue == 0 && $windex == 0 && (($reqtype & 0xf0) == 0x40)) {
+ my $cmd = $req;
+ for (my $i = 0; $i < scalar(@bytes); $i++) {
+ $cmd .= sprintf ", 0x%02x", $bytes[$i];
+ }
+
+ printf("dib0700_ctrl_wr(adap->dev, { $cmd }, %d);\n", $wlen + 1);
+ next;
+ }
+
+ printf("%s(0x%02x), Req %s, wValue: 0x%04x, wIndex 0x%04x, wlen %d: %s\n",
+ type_req($reqtype), $reqtype, $req, $wvalue, $windex, $wlen, $payload);
+ }
+}
diff --git a/contrib/em28xx/rewrite_eeprom.pl b/contrib/em28xx/rewrite_eeprom.pl
index ec7d557e..ec7d557e 100644..100755
--- a/contrib/em28xx/rewrite_eeprom.pl
+++ b/contrib/em28xx/rewrite_eeprom.pl
diff --git a/contrib/freebsd/Makefile.am b/contrib/freebsd/Makefile.am
index 8ad4c016..bf665242 100644
--- a/contrib/freebsd/Makefile.am
+++ b/contrib/freebsd/Makefile.am
@@ -1,17 +1,16 @@
EXTRA_DIST = \
- bsdify.sh \
include \
patches
sync-with-kernel:
rm -rf .pc
- for i in input.h ivtv.h uinput.h videodev2.h v4l2-controls.h v4l2-common.h dvb/{audio.h,ca.h,dmx.h,frontend.h,net.h,osd.h,version.h,video.h}; do \
+ for i in input.h ivtv.h uinput.h videodev2.h v4l2-controls.h v4l2-common.h do \
mkdir -p include/linux/$$(dirname $$i); \
- cp $(KERNEL_DIR)/include/uapi/linux/$$i include/linux/$$i; \
+ cp $(KERNEL_DIR)/usr/include/linux/$$i include/linux/$$i; \
done
- for i in ivtv.h uinput.h videodev2.h dvb/{audio.h,ca.h,dmx.h,frontend.h,net.h,osd.h,version.h,video.h}; do \
+ for i in ivtv.h uinput.h videodev2.h v4l2-common.h do \
sed -e 's/__u8/uint8_t/g' -e 's/__u16/uint16_t/g' -e 's/__u32/uint32_t/g' -e 's/__u64/uint64_t/g' -e 's/__s8/int8_t/g' -e 's/__s16/int16_t/g' -e 's/__s32/int32_t/g' -e 's/__s64/int64_t/g' -e 's/__le32/uint32_t/g' -e 's/__user//g' -i include/linux/$$i; \
done
diff --git a/contrib/freebsd/bsdify.sh b/contrib/freebsd/bsdify.sh
deleted file mode 100755
index d4652cb5..00000000
--- a/contrib/freebsd/bsdify.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-set -o errexit
-set -x
-
-KERNEL_DIR="${1?'Need kernel directory'}"
-
-SED=sed
-
-function replace_types {
- $SED \
- -e 's/__u8/uint8_t/g' \
- -e 's/__u16/uint16_t/g' \
- -e 's/__u32/uint32_t/g' \
- -e 's/__u64/uint64_t/g' \
- -e 's/__s8/int8_t/g' \
- -e 's/__s16/int16_t/g' \
- -e 's/__s32/int32_t/g' \
- -e 's/__s64/int64_t/g' \
- -e 's/__le32/uint32_t/g' \
- -e 's/__user//g' \
- -i "${1?'Missing file name'}"
-}
-
-# clean
-
-rm -rf include .pc
-
-# copy
-
-for i in input.h ivtv.h uinput.h videodev2.h v4l2-controls.h v4l2-common.h dvb/{audio.h,ca.h,dmx.h,frontend.h,net.h,osd.h,version.h,video.h}; do
- mkdir -p include/linux/$(dirname $i)
- cp $KERNEL_DIR/include/uapi/linux/$i include/linux/$i
-done
-
-# replace kernel types
-
-for i in ivtv.h uinput.h videodev2.h dvb/{audio.h,ca.h,dmx.h,frontend.h,net.h,osd.h,version.h,video.h}; do
- replace_types include/linux/$i
-done
-
-
-quilt push -a
diff --git a/contrib/freebsd/include/linux/dvb/audio.h b/contrib/freebsd/include/linux/dvb/audio.h
deleted file mode 100644
index e344cf34..00000000
--- a/contrib/freebsd/include/linux/dvb/audio.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * audio.h
- *
- * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
- * & Marcus Metzler <marcus@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DVBAUDIO_H_
-#define _DVBAUDIO_H_
-
-#include <sys/types.h>
-
-typedef enum {
- AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
- AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
-} audio_stream_source_t;
-
-
-typedef enum {
- AUDIO_STOPPED, /* Device is stopped */
- AUDIO_PLAYING, /* Device is currently playing */
- AUDIO_PAUSED /* Device is paused */
-} audio_play_state_t;
-
-
-typedef enum {
- AUDIO_STEREO,
- AUDIO_MONO_LEFT,
- AUDIO_MONO_RIGHT,
- AUDIO_MONO,
- AUDIO_STEREO_SWAPPED
-} audio_channel_select_t;
-
-
-typedef struct audio_mixer {
- unsigned int volume_left;
- unsigned int volume_right;
- // what else do we need? bass, pass-through, ...
-} audio_mixer_t;
-
-
-typedef struct audio_status {
- int AV_sync_state; /* sync audio and video? */
- int mute_state; /* audio is muted */
- audio_play_state_t play_state; /* current playback state */
- audio_stream_source_t stream_source; /* current stream source */
- audio_channel_select_t channel_select; /* currently selected channel */
- int bypass_mode; /* pass on audio data to */
- audio_mixer_t mixer_state; /* current mixer state */
-} audio_status_t; /* separate decoder hardware */
-
-
-typedef
-struct audio_karaoke { /* if Vocal1 or Vocal2 are non-zero, they get mixed */
- int vocal1; /* into left and right t at 70% each */
- int vocal2; /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/
- int melody; /* mixed into the left channel and */
- /* Vocal2 into the right channel at 100% each. */
- /* if Melody is non-zero, the melody channel gets mixed*/
-} audio_karaoke_t; /* into left and right */
-
-
-typedef uint16_t audio_attributes_t;
-/* bits: descr. */
-/* 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */
-/* 12 multichannel extension */
-/* 11-10 audio type (0=not spec, 1=language included) */
-/* 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */
-/* 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, */
-/* 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */
-/* 2- 0 number of audio channels (n+1 channels) */
-
-
-/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
-#define AUDIO_CAP_DTS 1
-#define AUDIO_CAP_LPCM 2
-#define AUDIO_CAP_MP1 4
-#define AUDIO_CAP_MP2 8
-#define AUDIO_CAP_MP3 16
-#define AUDIO_CAP_AAC 32
-#define AUDIO_CAP_OGG 64
-#define AUDIO_CAP_SDDS 128
-#define AUDIO_CAP_AC3 256
-
-#define AUDIO_STOP _IO('o', 1)
-#define AUDIO_PLAY _IO('o', 2)
-#define AUDIO_PAUSE _IO('o', 3)
-#define AUDIO_CONTINUE _IO('o', 4)
-#define AUDIO_SELECT_SOURCE _IO('o', 5)
-#define AUDIO_SET_MUTE _IO('o', 6)
-#define AUDIO_SET_AV_SYNC _IO('o', 7)
-#define AUDIO_SET_BYPASS_MODE _IO('o', 8)
-#define AUDIO_CHANNEL_SELECT _IO('o', 9)
-#define AUDIO_GET_STATUS _IOR('o', 10, audio_status_t)
-
-#define AUDIO_GET_CAPABILITIES _IOR('o', 11, unsigned int)
-#define AUDIO_CLEAR_BUFFER _IO('o', 12)
-#define AUDIO_SET_ID _IO('o', 13)
-#define AUDIO_SET_MIXER _IOW('o', 14, audio_mixer_t)
-#define AUDIO_SET_STREAMTYPE _IO('o', 15)
-#define AUDIO_SET_EXT_ID _IO('o', 16)
-#define AUDIO_SET_ATTRIBUTES _IOW('o', 17, audio_attributes_t)
-#define AUDIO_SET_KARAOKE _IOW('o', 18, audio_karaoke_t)
-
-/**
- * AUDIO_GET_PTS
- *
- * Read the 33 bit presentation time stamp as defined
- * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
- *
- * The PTS should belong to the currently played
- * frame if possible, but may also be a value close to it
- * like the PTS of the last decoded frame or the last PTS
- * extracted by the PES parser.
- */
-#define AUDIO_GET_PTS _IOR('o', 19, uint64_t)
-#define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
-
-#endif /* _DVBAUDIO_H_ */
diff --git a/contrib/freebsd/include/linux/dvb/ca.h b/contrib/freebsd/include/linux/dvb/ca.h
deleted file mode 100644
index c18537f3..00000000
--- a/contrib/freebsd/include/linux/dvb/ca.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * ca.h
- *
- * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
- * & Marcus Metzler <marcus@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DVBCA_H_
-#define _DVBCA_H_
-
-/* slot interface types and info */
-
-typedef struct ca_slot_info {
- int num; /* slot number */
-
- int type; /* CA interface this slot supports */
-#define CA_CI 1 /* CI high level interface */
-#define CA_CI_LINK 2 /* CI link layer level interface */
-#define CA_CI_PHYS 4 /* CI physical layer level interface */
-#define CA_DESCR 8 /* built-in descrambler */
-#define CA_SC 128 /* simple smart card interface */
-
- unsigned int flags;
-#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
-#define CA_CI_MODULE_READY 2
-} ca_slot_info_t;
-
-
-/* descrambler types and info */
-
-typedef struct ca_descr_info {
- unsigned int num; /* number of available descramblers (keys) */
- unsigned int type; /* type of supported scrambling system */
-#define CA_ECD 1
-#define CA_NDS 2
-#define CA_DSS 4
-} ca_descr_info_t;
-
-typedef struct ca_caps {
- unsigned int slot_num; /* total number of CA card and module slots */
- unsigned int slot_type; /* OR of all supported types */
- unsigned int descr_num; /* total number of descrambler slots (keys) */
- unsigned int descr_type; /* OR of all supported types */
-} ca_caps_t;
-
-/* a message to/from a CI-CAM */
-typedef struct ca_msg {
- unsigned int index;
- unsigned int type;
- unsigned int length;
- unsigned char msg[256];
-} ca_msg_t;
-
-typedef struct ca_descr {
- unsigned int index;
- unsigned int parity; /* 0 == even, 1 == odd */
- unsigned char cw[8];
-} ca_descr_t;
-
-typedef struct ca_pid {
- unsigned int pid;
- int index; /* -1 == disable*/
-} ca_pid_t;
-
-#define CA_RESET _IO('o', 128)
-#define CA_GET_CAP _IOR('o', 129, ca_caps_t)
-#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t)
-#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
-#define CA_GET_MSG _IOR('o', 132, ca_msg_t)
-#define CA_SEND_MSG _IOW('o', 133, ca_msg_t)
-#define CA_SET_DESCR _IOW('o', 134, ca_descr_t)
-#define CA_SET_PID _IOW('o', 135, ca_pid_t)
-
-#endif
diff --git a/contrib/freebsd/include/linux/dvb/dmx.h b/contrib/freebsd/include/linux/dvb/dmx.h
deleted file mode 100644
index 65ab7790..00000000
--- a/contrib/freebsd/include/linux/dvb/dmx.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * dmx.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- * & Ralph Metzler <ralph@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _UAPI_DVBDMX_H_
-#define _UAPI_DVBDMX_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <time.h>
-
-
-#define DMX_FILTER_SIZE 16
-
-typedef enum
-{
- DMX_OUT_DECODER, /* Streaming directly to decoder. */
- DMX_OUT_TAP, /* Output going to a memory buffer */
- /* (to be retrieved via the read command).*/
- DMX_OUT_TS_TAP, /* Output multiplexed into a new TS */
- /* (to be retrieved by reading from the */
- /* logical DVR device). */
- DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
-} dmx_output_t;
-
-
-typedef enum
-{
- DMX_IN_FRONTEND, /* Input from a front-end device. */
- DMX_IN_DVR /* Input from the logical DVR device. */
-} dmx_input_t;
-
-
-typedef enum dmx_ts_pes
-{
- DMX_PES_AUDIO0,
- DMX_PES_VIDEO0,
- DMX_PES_TELETEXT0,
- DMX_PES_SUBTITLE0,
- DMX_PES_PCR0,
-
- DMX_PES_AUDIO1,
- DMX_PES_VIDEO1,
- DMX_PES_TELETEXT1,
- DMX_PES_SUBTITLE1,
- DMX_PES_PCR1,
-
- DMX_PES_AUDIO2,
- DMX_PES_VIDEO2,
- DMX_PES_TELETEXT2,
- DMX_PES_SUBTITLE2,
- DMX_PES_PCR2,
-
- DMX_PES_AUDIO3,
- DMX_PES_VIDEO3,
- DMX_PES_TELETEXT3,
- DMX_PES_SUBTITLE3,
- DMX_PES_PCR3,
-
- DMX_PES_OTHER
-} dmx_pes_type_t;
-
-#define DMX_PES_AUDIO DMX_PES_AUDIO0
-#define DMX_PES_VIDEO DMX_PES_VIDEO0
-#define DMX_PES_TELETEXT DMX_PES_TELETEXT0
-#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0
-#define DMX_PES_PCR DMX_PES_PCR0
-
-
-typedef struct dmx_filter
-{
- uint8_t filter[DMX_FILTER_SIZE];
- uint8_t mask[DMX_FILTER_SIZE];
- uint8_t mode[DMX_FILTER_SIZE];
-} dmx_filter_t;
-
-
-struct dmx_sct_filter_params
-{
- uint16_t pid;
- dmx_filter_t filter;
- uint32_t timeout;
- uint32_t flags;
-#define DMX_CHECK_CRC 1
-#define DMX_ONESHOT 2
-#define DMX_IMMEDIATE_START 4
-#define DMX_KERNEL_CLIENT 0x8000
-};
-
-
-struct dmx_pes_filter_params
-{
- uint16_t pid;
- dmx_input_t input;
- dmx_output_t output;
- dmx_pes_type_t pes_type;
- uint32_t flags;
-};
-
-typedef struct dmx_caps {
- uint32_t caps;
- int num_decoders;
-} dmx_caps_t;
-
-typedef enum {
- DMX_SOURCE_FRONT0 = 0,
- DMX_SOURCE_FRONT1,
- DMX_SOURCE_FRONT2,
- DMX_SOURCE_FRONT3,
- DMX_SOURCE_DVR0 = 16,
- DMX_SOURCE_DVR1,
- DMX_SOURCE_DVR2,
- DMX_SOURCE_DVR3
-} dmx_source_t;
-
-struct dmx_stc {
- unsigned int num; /* input : which STC? 0..N */
- unsigned int base; /* output: divisor for stc to get 90 kHz clock */
- uint64_t stc; /* output: stc in 'base'*90 kHz units */
-};
-
-
-#define DMX_START _IO('o', 41)
-#define DMX_STOP _IO('o', 42)
-#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params)
-#define DMX_SET_PES_FILTER _IOW('o', 44, struct dmx_pes_filter_params)
-#define DMX_SET_BUFFER_SIZE _IO('o', 45)
-#define DMX_GET_PES_PIDS _IOR('o', 47, uint16_t[5])
-#define DMX_GET_CAPS _IOR('o', 48, dmx_caps_t)
-#define DMX_SET_SOURCE _IOW('o', 49, dmx_source_t)
-#define DMX_GET_STC _IOWR('o', 50, struct dmx_stc)
-#define DMX_ADD_PID _IOW('o', 51, uint16_t)
-#define DMX_REMOVE_PID _IOW('o', 52, uint16_t)
-
-#endif /* _UAPI_DVBDMX_H_ */
diff --git a/contrib/freebsd/include/linux/dvb/frontend.h b/contrib/freebsd/include/linux/dvb/frontend.h
deleted file mode 100644
index d36dbfcb..00000000
--- a/contrib/freebsd/include/linux/dvb/frontend.h
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * frontend.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- * Ralph Metzler <ralph@convergence.de>
- * Holger Waechtler <holger@convergence.de>
- * Andre Draszik <ad@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DVBFRONTEND_H_
-#define _DVBFRONTEND_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-typedef enum fe_type {
- FE_QPSK,
- FE_QAM,
- FE_OFDM,
- FE_ATSC
-} fe_type_t;
-
-
-typedef enum fe_caps {
- FE_IS_STUPID = 0,
- FE_CAN_INVERSION_AUTO = 0x1,
- FE_CAN_FEC_1_2 = 0x2,
- FE_CAN_FEC_2_3 = 0x4,
- FE_CAN_FEC_3_4 = 0x8,
- FE_CAN_FEC_4_5 = 0x10,
- FE_CAN_FEC_5_6 = 0x20,
- FE_CAN_FEC_6_7 = 0x40,
- FE_CAN_FEC_7_8 = 0x80,
- FE_CAN_FEC_8_9 = 0x100,
- FE_CAN_FEC_AUTO = 0x200,
- FE_CAN_QPSK = 0x400,
- FE_CAN_QAM_16 = 0x800,
- FE_CAN_QAM_32 = 0x1000,
- FE_CAN_QAM_64 = 0x2000,
- FE_CAN_QAM_128 = 0x4000,
- FE_CAN_QAM_256 = 0x8000,
- FE_CAN_QAM_AUTO = 0x10000,
- FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000,
- FE_CAN_BANDWIDTH_AUTO = 0x40000,
- FE_CAN_GUARD_INTERVAL_AUTO = 0x80000,
- FE_CAN_HIERARCHY_AUTO = 0x100000,
- FE_CAN_8VSB = 0x200000,
- FE_CAN_16VSB = 0x400000,
- FE_HAS_EXTENDED_CAPS = 0x800000, /* We need more bitspace for newer APIs, indicate this. */
- FE_CAN_MULTISTREAM = 0x4000000, /* frontend supports multistream filtering */
- FE_CAN_TURBO_FEC = 0x8000000, /* frontend supports "turbo fec modulation" */
- FE_CAN_2G_MODULATION = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
- FE_NEEDS_BENDING = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
- FE_CAN_RECOVER = 0x40000000, /* frontend can recover from a cable unplug automatically */
- FE_CAN_MUTE_TS = 0x80000000 /* frontend can stop spurious TS data output */
-} fe_caps_t;
-
-
-struct dvb_frontend_info {
- char name[128];
- fe_type_t type; /* DEPRECATED. Use DTV_ENUM_DELSYS instead */
- uint32_t frequency_min;
- uint32_t frequency_max;
- uint32_t frequency_stepsize;
- uint32_t frequency_tolerance;
- uint32_t symbol_rate_min;
- uint32_t symbol_rate_max;
- uint32_t symbol_rate_tolerance; /* ppm */
- uint32_t notifier_delay; /* DEPRECATED */
- fe_caps_t caps;
-};
-
-
-/**
- * Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
- * the meaning of this struct...
- */
-struct dvb_diseqc_master_cmd {
- uint8_t msg [6]; /* { framing, address, command, data [3] } */
- uint8_t msg_len; /* valid values are 3...6 */
-};
-
-
-struct dvb_diseqc_slave_reply {
- uint8_t msg [4]; /* { framing, data [3] } */
- uint8_t msg_len; /* valid values are 0...4, 0 means no msg */
- int timeout; /* return from ioctl after timeout ms with */
-}; /* errorcode when no message was received */
-
-
-typedef enum fe_sec_voltage {
- SEC_VOLTAGE_13,
- SEC_VOLTAGE_18,
- SEC_VOLTAGE_OFF
-} fe_sec_voltage_t;
-
-
-typedef enum fe_sec_tone_mode {
- SEC_TONE_ON,
- SEC_TONE_OFF
-} fe_sec_tone_mode_t;
-
-
-typedef enum fe_sec_mini_cmd {
- SEC_MINI_A,
- SEC_MINI_B
-} fe_sec_mini_cmd_t;
-
-
-/**
- * enum fe_status - enumerates the possible frontend status
- * @FE_HAS_SIGNAL: found something above the noise level
- * @FE_HAS_CARRIER: found a DVB signal
- * @FE_HAS_VITERBI: FEC is stable
- * @FE_HAS_SYNC: found sync bytes
- * @FE_HAS_LOCK: everything's working
- * @FE_TIMEDOUT: no lock within the last ~2 seconds
- * @FE_REINIT: frontend was reinitialized, application is recommended
- * to reset DiSEqC, tone and parameters
- */
-
-typedef enum fe_status {
- FE_HAS_SIGNAL = 0x01,
- FE_HAS_CARRIER = 0x02,
- FE_HAS_VITERBI = 0x04,
- FE_HAS_SYNC = 0x08,
- FE_HAS_LOCK = 0x10,
- FE_TIMEDOUT = 0x20,
- FE_REINIT = 0x40,
-} fe_status_t;
-
-typedef enum fe_spectral_inversion {
- INVERSION_OFF,
- INVERSION_ON,
- INVERSION_AUTO
-} fe_spectral_inversion_t;
-
-
-typedef enum fe_code_rate {
- FEC_NONE = 0,
- FEC_1_2,
- FEC_2_3,
- FEC_3_4,
- FEC_4_5,
- FEC_5_6,
- FEC_6_7,
- FEC_7_8,
- FEC_8_9,
- FEC_AUTO,
- FEC_3_5,
- FEC_9_10,
- FEC_2_5,
-} fe_code_rate_t;
-
-
-typedef enum fe_modulation {
- QPSK,
- QAM_16,
- QAM_32,
- QAM_64,
- QAM_128,
- QAM_256,
- QAM_AUTO,
- VSB_8,
- VSB_16,
- PSK_8,
- APSK_16,
- APSK_32,
- DQPSK,
- QAM_4_NR,
-} fe_modulation_t;
-
-typedef enum fe_transmit_mode {
- TRANSMISSION_MODE_2K,
- TRANSMISSION_MODE_8K,
- TRANSMISSION_MODE_AUTO,
- TRANSMISSION_MODE_4K,
- TRANSMISSION_MODE_1K,
- TRANSMISSION_MODE_16K,
- TRANSMISSION_MODE_32K,
- TRANSMISSION_MODE_C1,
- TRANSMISSION_MODE_C3780,
-} fe_transmit_mode_t;
-
-#if defined(__DVB_CORE__) || !defined (__KERNEL__)
-typedef enum fe_bandwidth {
- BANDWIDTH_8_MHZ,
- BANDWIDTH_7_MHZ,
- BANDWIDTH_6_MHZ,
- BANDWIDTH_AUTO,
- BANDWIDTH_5_MHZ,
- BANDWIDTH_10_MHZ,
- BANDWIDTH_1_712_MHZ,
-} fe_bandwidth_t;
-#endif
-
-typedef enum fe_guard_interval {
- GUARD_INTERVAL_1_32,
- GUARD_INTERVAL_1_16,
- GUARD_INTERVAL_1_8,
- GUARD_INTERVAL_1_4,
- GUARD_INTERVAL_AUTO,
- GUARD_INTERVAL_1_128,
- GUARD_INTERVAL_19_128,
- GUARD_INTERVAL_19_256,
- GUARD_INTERVAL_PN420,
- GUARD_INTERVAL_PN595,
- GUARD_INTERVAL_PN945,
-} fe_guard_interval_t;
-
-
-typedef enum fe_hierarchy {
- HIERARCHY_NONE,
- HIERARCHY_1,
- HIERARCHY_2,
- HIERARCHY_4,
- HIERARCHY_AUTO
-} fe_hierarchy_t;
-
-enum fe_interleaving {
- INTERLEAVING_NONE,
- INTERLEAVING_AUTO,
- INTERLEAVING_240,
- INTERLEAVING_720,
-};
-
-#if defined(__DVB_CORE__) || !defined (__KERNEL__)
-struct dvb_qpsk_parameters {
- uint32_t symbol_rate; /* symbol rate in Symbols per second */
- fe_code_rate_t fec_inner; /* forward error correction (see above) */
-};
-
-struct dvb_qam_parameters {
- uint32_t symbol_rate; /* symbol rate in Symbols per second */
- fe_code_rate_t fec_inner; /* forward error correction (see above) */
- fe_modulation_t modulation; /* modulation type (see above) */
-};
-
-struct dvb_vsb_parameters {
- fe_modulation_t modulation; /* modulation type (see above) */
-};
-
-struct dvb_ofdm_parameters {
- fe_bandwidth_t bandwidth;
- fe_code_rate_t code_rate_HP; /* high priority stream code rate */
- fe_code_rate_t code_rate_LP; /* low priority stream code rate */
- fe_modulation_t constellation; /* modulation type (see above) */
- fe_transmit_mode_t transmission_mode;
- fe_guard_interval_t guard_interval;
- fe_hierarchy_t hierarchy_information;
-};
-
-
-struct dvb_frontend_parameters {
- uint32_t frequency; /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
- /* intermediate frequency in kHz for QPSK */
- fe_spectral_inversion_t inversion;
- union {
- struct dvb_qpsk_parameters qpsk;
- struct dvb_qam_parameters qam;
- struct dvb_ofdm_parameters ofdm;
- struct dvb_vsb_parameters vsb;
- } u;
-};
-
-struct dvb_frontend_event {
- fe_status_t status;
- struct dvb_frontend_parameters parameters;
-};
-#endif
-
-/* S2API Commands */
-#define DTV_UNDEFINED 0
-#define DTV_TUNE 1
-#define DTV_CLEAR 2
-#define DTV_FREQUENCY 3
-#define DTV_MODULATION 4
-#define DTV_BANDWIDTH_HZ 5
-#define DTV_INVERSION 6
-#define DTV_DISEQC_MASTER 7
-#define DTV_SYMBOL_RATE 8
-#define DTV_INNER_FEC 9
-#define DTV_VOLTAGE 10
-#define DTV_TONE 11
-#define DTV_PILOT 12
-#define DTV_ROLLOFF 13
-#define DTV_DISEQC_SLAVE_REPLY 14
-
-/* Basic enumeration set for querying unlimited capabilities */
-#define DTV_FE_CAPABILITY_COUNT 15
-#define DTV_FE_CAPABILITY 16
-#define DTV_DELIVERY_SYSTEM 17
-
-/* ISDB-T and ISDB-Tsb */
-#define DTV_ISDBT_PARTIAL_RECEPTION 18
-#define DTV_ISDBT_SOUND_BROADCASTING 19
-
-#define DTV_ISDBT_SB_SUBCHANNEL_ID 20
-#define DTV_ISDBT_SB_SEGMENT_IDX 21
-#define DTV_ISDBT_SB_SEGMENT_COUNT 22
-
-#define DTV_ISDBT_LAYERA_FEC 23
-#define DTV_ISDBT_LAYERA_MODULATION 24
-#define DTV_ISDBT_LAYERA_SEGMENT_COUNT 25
-#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING 26
-
-#define DTV_ISDBT_LAYERB_FEC 27
-#define DTV_ISDBT_LAYERB_MODULATION 28
-#define DTV_ISDBT_LAYERB_SEGMENT_COUNT 29
-#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING 30
-
-#define DTV_ISDBT_LAYERC_FEC 31
-#define DTV_ISDBT_LAYERC_MODULATION 32
-#define DTV_ISDBT_LAYERC_SEGMENT_COUNT 33
-#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING 34
-
-#define DTV_API_VERSION 35
-
-#define DTV_CODE_RATE_HP 36
-#define DTV_CODE_RATE_LP 37
-#define DTV_GUARD_INTERVAL 38
-#define DTV_TRANSMISSION_MODE 39
-#define DTV_HIERARCHY 40
-
-#define DTV_ISDBT_LAYER_ENABLED 41
-
-#define DTV_STREAM_ID 42
-#define DTV_ISDBS_TS_ID_LEGACY DTV_STREAM_ID
-#define DTV_DVBT2_PLP_ID_LEGACY 43
-
-#define DTV_ENUM_DELSYS 44
-
-/* ATSC-MH */
-#define DTV_ATSCMH_FIC_VER 45
-#define DTV_ATSCMH_PARADE_ID 46
-#define DTV_ATSCMH_NOG 47
-#define DTV_ATSCMH_TNOG 48
-#define DTV_ATSCMH_SGN 49
-#define DTV_ATSCMH_PRC 50
-#define DTV_ATSCMH_RS_FRAME_MODE 51
-#define DTV_ATSCMH_RS_FRAME_ENSEMBLE 52
-#define DTV_ATSCMH_RS_CODE_MODE_PRI 53
-#define DTV_ATSCMH_RS_CODE_MODE_SEC 54
-#define DTV_ATSCMH_SCCC_BLOCK_MODE 55
-#define DTV_ATSCMH_SCCC_CODE_MODE_A 56
-#define DTV_ATSCMH_SCCC_CODE_MODE_B 57
-#define DTV_ATSCMH_SCCC_CODE_MODE_C 58
-#define DTV_ATSCMH_SCCC_CODE_MODE_D 59
-
-#define DTV_INTERLEAVING 60
-#define DTV_LNA 61
-
-/* Quality parameters */
-#define DTV_STAT_SIGNAL_STRENGTH 62
-#define DTV_STAT_CNR 63
-#define DTV_STAT_PRE_ERROR_BIT_COUNT 64
-#define DTV_STAT_PRE_TOTAL_BIT_COUNT 65
-#define DTV_STAT_POST_ERROR_BIT_COUNT 66
-#define DTV_STAT_POST_TOTAL_BIT_COUNT 67
-#define DTV_STAT_ERROR_BLOCK_COUNT 68
-#define DTV_STAT_TOTAL_BLOCK_COUNT 69
-
-#define DTV_MAX_COMMAND DTV_STAT_TOTAL_BLOCK_COUNT
-
-typedef enum fe_pilot {
- PILOT_ON,
- PILOT_OFF,
- PILOT_AUTO,
-} fe_pilot_t;
-
-typedef enum fe_rolloff {
- ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
- ROLLOFF_20,
- ROLLOFF_25,
- ROLLOFF_AUTO,
-} fe_rolloff_t;
-
-typedef enum fe_delivery_system {
- SYS_UNDEFINED,
- SYS_DVBC_ANNEX_A,
- SYS_DVBC_ANNEX_B,
- SYS_DVBT,
- SYS_DSS,
- SYS_DVBS,
- SYS_DVBS2,
- SYS_DVBH,
- SYS_ISDBT,
- SYS_ISDBS,
- SYS_ISDBC,
- SYS_ATSC,
- SYS_ATSCMH,
- SYS_DTMB,
- SYS_CMMB,
- SYS_DAB,
- SYS_DVBT2,
- SYS_TURBO,
- SYS_DVBC_ANNEX_C,
-} fe_delivery_system_t;
-
-/* backward compatibility */
-#define SYS_DVBC_ANNEX_AC SYS_DVBC_ANNEX_A
-#define SYS_DMBTH SYS_DTMB /* DMB-TH is legacy name, use DTMB instead */
-
-/* ATSC-MH */
-
-enum atscmh_sccc_block_mode {
- ATSCMH_SCCC_BLK_SEP = 0,
- ATSCMH_SCCC_BLK_COMB = 1,
- ATSCMH_SCCC_BLK_RES = 2,
-};
-
-enum atscmh_sccc_code_mode {
- ATSCMH_SCCC_CODE_HLF = 0,
- ATSCMH_SCCC_CODE_QTR = 1,
- ATSCMH_SCCC_CODE_RES = 2,
-};
-
-enum atscmh_rs_frame_ensemble {
- ATSCMH_RSFRAME_ENS_PRI = 0,
- ATSCMH_RSFRAME_ENS_SEC = 1,
-};
-
-enum atscmh_rs_frame_mode {
- ATSCMH_RSFRAME_PRI_ONLY = 0,
- ATSCMH_RSFRAME_PRI_SEC = 1,
- ATSCMH_RSFRAME_RES = 2,
-};
-
-enum atscmh_rs_code_mode {
- ATSCMH_RSCODE_211_187 = 0,
- ATSCMH_RSCODE_223_187 = 1,
- ATSCMH_RSCODE_235_187 = 2,
- ATSCMH_RSCODE_RES = 3,
-};
-
-#define NO_STREAM_ID_FILTER (~0U)
-#define LNA_AUTO (~0U)
-
-struct dtv_cmds_h {
- char *name; /* A display name for debugging purposes */
-
- uint32_t cmd; /* A unique ID */
-
- /* Flags */
- uint32_t set:1; /* Either a set or get property */
- uint32_t buffer:1; /* Does this property use the buffer? */
- uint32_t reserved:30; /* Align */
-};
-
-/**
- * Scale types for the quality parameters.
- * @FE_SCALE_NOT_AVAILABLE: That QoS measure is not available. That
- * could indicate a temporary or a permanent
- * condition.
- * @FE_SCALE_DECIBEL: The scale is measured in 0.0001 dB steps, typically
- * used on signal measures.
- * @FE_SCALE_RELATIVE: The scale is a relative percentual measure,
- * ranging from 0 (0%) to 0xffff (100%).
- * @FE_SCALE_COUNTER: The scale counts the occurrence of an event, like
- * bit error, block error, lapsed time.
- */
-enum fecap_scale_params {
- FE_SCALE_NOT_AVAILABLE = 0,
- FE_SCALE_DECIBEL,
- FE_SCALE_RELATIVE,
- FE_SCALE_COUNTER
-};
-
-/**
- * struct dtv_stats - Used for reading a DTV status property
- *
- * @value: value of the measure. Should range from 0 to 0xffff;
- * @scale: Filled with enum fecap_scale_params - the scale
- * in usage for that parameter
- *
- * For most delivery systems, this will return a single value for each
- * parameter.
- * It should be noticed, however, that new OFDM delivery systems like
- * ISDB can use different modulation types for each group of carriers.
- * On such standards, up to 8 groups of statistics can be provided, one
- * for each carrier group (called "layer" on ISDB).
- * In order to be consistent with other delivery systems, the first
- * value refers to the entire set of carriers ("global").
- * dtv_status:scale should use the value FE_SCALE_NOT_AVAILABLE when
- * the value for the entire group of carriers or from one specific layer
- * is not provided by the hardware.
- * st.len should be filled with the latest filled status + 1.
- *
- * In other words, for ISDB, those values should be filled like:
- * u.st.stat.svalue[0] = global statistics;
- * u.st.stat.scale[0] = FE_SCALE_DECIBELS;
- * u.st.stat.value[1] = layer A statistics;
- * u.st.stat.scale[1] = FE_SCALE_NOT_AVAILABLE (if not available);
- * u.st.stat.svalue[2] = layer B statistics;
- * u.st.stat.scale[2] = FE_SCALE_DECIBELS;
- * u.st.stat.svalue[3] = layer C statistics;
- * u.st.stat.scale[3] = FE_SCALE_DECIBELS;
- * u.st.len = 4;
- */
-struct dtv_stats {
- uint8_t scale; /* enum fecap_scale_params type */
- union {
- uint64_t uvalue; /* for counters and relative scales */
- int64_t svalue; /* for 0.0001 dB measures */
- };
-} __attribute__ ((packed));
-
-
-#define MAX_DTV_STATS 4
-
-struct dtv_fe_stats {
- uint8_t len;
- struct dtv_stats stat[MAX_DTV_STATS];
-} __attribute__ ((packed));
-
-struct dtv_property {
- uint32_t cmd;
- uint32_t reserved[3];
- union {
- uint32_t data;
- struct dtv_fe_stats st;
- struct {
- uint8_t data[32];
- uint32_t len;
- uint32_t reserved1[3];
- void *reserved2;
- } buffer;
- } u;
- int result;
-} __attribute__ ((packed));
-
-/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
-#define DTV_IOCTL_MAX_MSGS 64
-
-struct dtv_properties {
- uint32_t num;
- struct dtv_property *props;
-};
-
-#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties)
-#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties)
-
-
-/**
- * When set, this flag will disable any zigzagging or other "normal" tuning
- * behaviour. Additionally, there will be no automatic monitoring of the lock
- * status, and hence no frontend events will be generated. If a frontend device
- * is closed, this flag will be automatically turned off when the device is
- * reopened read-write.
- */
-#define FE_TUNE_MODE_ONESHOT 0x01
-
-
-#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
-
-#define FE_DISEQC_RESET_OVERLOAD _IO('o', 62)
-#define FE_DISEQC_SEND_MASTER_CMD _IOW('o', 63, struct dvb_diseqc_master_cmd)
-#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply)
-#define FE_DISEQC_SEND_BURST _IO('o', 65) /* fe_sec_mini_cmd_t */
-
-#define FE_SET_TONE _IO('o', 66) /* fe_sec_tone_mode_t */
-#define FE_SET_VOLTAGE _IO('o', 67) /* fe_sec_voltage_t */
-#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68) /* int */
-
-#define FE_READ_STATUS _IOR('o', 69, fe_status_t)
-#define FE_READ_BER _IOR('o', 70, uint32_t)
-#define FE_READ_SIGNAL_STRENGTH _IOR('o', 71, uint16_t)
-#define FE_READ_SNR _IOR('o', 72, uint16_t)
-#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, uint32_t)
-
-#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters)
-#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters)
-#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81) /* unsigned int */
-#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event)
-
-#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
-
-#endif /*_DVBFRONTEND_H_*/
diff --git a/contrib/freebsd/include/linux/dvb/net.h b/contrib/freebsd/include/linux/dvb/net.h
deleted file mode 100644
index e338de0f..00000000
--- a/contrib/freebsd/include/linux/dvb/net.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * net.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- * & Ralph Metzler <ralph@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DVBNET_H_
-#define _DVBNET_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-struct dvb_net_if {
- uint16_t pid;
- uint16_t if_num;
- uint8_t feedtype;
-#define DVB_NET_FEEDTYPE_MPE 0 /* multi protocol encapsulation */
-#define DVB_NET_FEEDTYPE_ULE 1 /* ultra lightweight encapsulation */
-};
-
-
-#define NET_ADD_IF _IOWR('o', 52, struct dvb_net_if)
-#define NET_REMOVE_IF _IO('o', 53)
-#define NET_GET_IF _IOWR('o', 54, struct dvb_net_if)
-
-
-/* binary compatibility cruft: */
-struct __dvb_net_if_old {
- uint16_t pid;
- uint16_t if_num;
-};
-#define __NET_ADD_IF_OLD _IOWR('o', 52, struct __dvb_net_if_old)
-#define __NET_GET_IF_OLD _IOWR('o', 54, struct __dvb_net_if_old)
-
-
-#endif /*_DVBNET_H_*/
diff --git a/contrib/freebsd/include/linux/dvb/osd.h b/contrib/freebsd/include/linux/dvb/osd.h
deleted file mode 100644
index 0e9d26ae..00000000
--- a/contrib/freebsd/include/linux/dvb/osd.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * osd.h
- *
- * Copyright (C) 2001 Ralph Metzler <ralph@convergence.de>
- * & Marcus Metzler <marcus@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DVBOSD_H_
-#define _DVBOSD_H_
-
-#include <sys/types.h>
-
-typedef enum {
- // All functions return -2 on "not open"
- OSD_Close=1, // ()
- // Disables OSD and releases the buffers
- // returns 0 on success
- OSD_Open, // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0))
- // Opens OSD with this size and bit depth
- // returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
- OSD_Show, // ()
- // enables OSD mode
- // returns 0 on success
- OSD_Hide, // ()
- // disables OSD mode
- // returns 0 on success
- OSD_Clear, // ()
- // Sets all pixel to color 0
- // returns 0 on success
- OSD_Fill, // (color)
- // Sets all pixel to color <col>
- // returns 0 on success
- OSD_SetColor, // (color,R{x0},G{y0},B{x1},opacity{y1})
- // set palette entry <num> to <r,g,b>, <mix> and <trans> apply
- // R,G,B: 0..255
- // R=Red, G=Green, B=Blue
- // opacity=0: pixel opacity 0% (only video pixel shows)
- // opacity=1..254: pixel opacity as specified in header
- // opacity=255: pixel opacity 100% (only OSD pixel shows)
- // returns 0 on success, -1 on error
- OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data)
- // Set a number of entries in the palette
- // sets the entries "firstcolor" through "lastcolor" from the array "data"
- // data has 4 byte for each color:
- // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
- OSD_SetTrans, // (transparency{color})
- // Sets transparency of mixed pixel (0..15)
- // returns 0 on success
- OSD_SetPixel, // (x0,y0,color)
- // sets pixel <x>,<y> to color number <col>
- // returns 0 on success, -1 on error
- OSD_GetPixel, // (x0,y0)
- // returns color number of pixel <x>,<y>, or -1
- OSD_SetRow, // (x0,y0,x1,data)
- // fills pixels x0,y through x1,y with the content of data[]
- // returns 0 on success, -1 on clipping all pixel (no pixel drawn)
- OSD_SetBlock, // (x0,y0,x1,y1,increment{color},data)
- // fills pixels x0,y0 through x1,y1 with the content of data[]
- // inc contains the width of one line in the data block,
- // inc<=0 uses blockwidth as linewidth
- // returns 0 on success, -1 on clipping all pixel
- OSD_FillRow, // (x0,y0,x1,color)
- // fills pixels x0,y through x1,y with the color <col>
- // returns 0 on success, -1 on clipping all pixel
- OSD_FillBlock, // (x0,y0,x1,y1,color)
- // fills pixels x0,y0 through x1,y1 with the color <col>
- // returns 0 on success, -1 on clipping all pixel
- OSD_Line, // (x0,y0,x1,y1,color)
- // draw a line from x0,y0 to x1,y1 with the color <col>
- // returns 0 on success
- OSD_Query, // (x0,y0,x1,y1,xasp{color}}), yasp=11
- // fills parameters with the picture dimensions and the pixel aspect ratio
- // returns 0 on success
- OSD_Test, // ()
- // draws a test picture. for debugging purposes only
- // returns 0 on success
-// TODO: remove "test" in final version
- OSD_Text, // (x0,y0,size,color,text)
- OSD_SetWindow, // (x0) set window with number 0<x0<8 as current
- OSD_MoveWindow, // move current window to (x0, y0)
- OSD_OpenRaw, // Open other types of OSD windows
-} OSD_Command;
-
-typedef struct osd_cmd_s {
- OSD_Command cmd;
- int x0;
- int y0;
- int x1;
- int y1;
- int color;
- void *data;
-} osd_cmd_t;
-
-/* OSD_OpenRaw: set 'color' to desired window type */
-typedef enum {
- OSD_BITMAP1, /* 1 bit bitmap */
- OSD_BITMAP2, /* 2 bit bitmap */
- OSD_BITMAP4, /* 4 bit bitmap */
- OSD_BITMAP8, /* 8 bit bitmap */
- OSD_BITMAP1HR, /* 1 Bit bitmap half resolution */
- OSD_BITMAP2HR, /* 2 bit bitmap half resolution */
- OSD_BITMAP4HR, /* 4 bit bitmap half resolution */
- OSD_BITMAP8HR, /* 8 bit bitmap half resolution */
- OSD_YCRCB422, /* 4:2:2 YCRCB Graphic Display */
- OSD_YCRCB444, /* 4:4:4 YCRCB Graphic Display */
- OSD_YCRCB444HR, /* 4:4:4 YCRCB graphic half resolution */
- OSD_VIDEOTSIZE, /* True Size Normal MPEG Video Display */
- OSD_VIDEOHSIZE, /* MPEG Video Display Half Resolution */
- OSD_VIDEOQSIZE, /* MPEG Video Display Quarter Resolution */
- OSD_VIDEODSIZE, /* MPEG Video Display Double Resolution */
- OSD_VIDEOTHSIZE, /* True Size MPEG Video Display Half Resolution */
- OSD_VIDEOTQSIZE, /* True Size MPEG Video Display Quarter Resolution*/
- OSD_VIDEOTDSIZE, /* True Size MPEG Video Display Double Resolution */
- OSD_VIDEONSIZE, /* Full Size MPEG Video Display */
- OSD_CURSOR /* Cursor */
-} osd_raw_window_t;
-
-typedef struct osd_cap_s {
- int cmd;
-#define OSD_CAP_MEMSIZE 1 /* memory size */
- long val;
-} osd_cap_t;
-
-
-#define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t)
-#define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t)
-
-#endif
diff --git a/contrib/freebsd/include/linux/dvb/version.h b/contrib/freebsd/include/linux/dvb/version.h
deleted file mode 100644
index e53e2ad4..00000000
--- a/contrib/freebsd/include/linux/dvb/version.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * version.h
- *
- * Copyright (C) 2000 Holger Waechtler <holger@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _DVBVERSION_H_
-#define _DVBVERSION_H_
-
-#define DVB_API_VERSION 5
-#define DVB_API_VERSION_MINOR 10
-
-#endif /*_DVBVERSION_H_*/
diff --git a/contrib/freebsd/include/linux/dvb/video.h b/contrib/freebsd/include/linux/dvb/video.h
deleted file mode 100644
index 55d919e0..00000000
--- a/contrib/freebsd/include/linux/dvb/video.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * video.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- * & Ralph Metzler <ralph@convergence.de>
- * for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _UAPI_DVBVIDEO_H_
-#define _UAPI_DVBVIDEO_H_
-
-#include <sys/types.h>
-#include <stdint.h>
-#include <time.h>
-
-typedef enum {
- VIDEO_FORMAT_4_3, /* Select 4:3 format */
- VIDEO_FORMAT_16_9, /* Select 16:9 format. */
- VIDEO_FORMAT_221_1 /* 2.21:1 */
-} video_format_t;
-
-
-typedef enum {
- VIDEO_SYSTEM_PAL,
- VIDEO_SYSTEM_NTSC,
- VIDEO_SYSTEM_PALN,
- VIDEO_SYSTEM_PALNc,
- VIDEO_SYSTEM_PALM,
- VIDEO_SYSTEM_NTSC60,
- VIDEO_SYSTEM_PAL60,
- VIDEO_SYSTEM_PALM60
-} video_system_t;
-
-
-typedef enum {
- VIDEO_PAN_SCAN, /* use pan and scan format */
- VIDEO_LETTER_BOX, /* use letterbox format */
- VIDEO_CENTER_CUT_OUT /* use center cut out format */
-} video_displayformat_t;
-
-typedef struct {
- int w;
- int h;
- video_format_t aspect_ratio;
-} video_size_t;
-
-typedef enum {
- VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
- VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
- comes from the user through the write
- system call */
-} video_stream_source_t;
-
-
-typedef enum {
- VIDEO_STOPPED, /* Video is stopped */
- VIDEO_PLAYING, /* Video is currently playing */
- VIDEO_FREEZED /* Video is freezed */
-} video_play_state_t;
-
-
-/* Decoder commands */
-#define VIDEO_CMD_PLAY (0)
-#define VIDEO_CMD_STOP (1)
-#define VIDEO_CMD_FREEZE (2)
-#define VIDEO_CMD_CONTINUE (3)
-
-/* Flags for VIDEO_CMD_FREEZE */
-#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0)
-
-/* Flags for VIDEO_CMD_STOP */
-#define VIDEO_CMD_STOP_TO_BLACK (1 << 0)
-#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1)
-
-/* Play input formats: */
-/* The decoder has no special format requirements */
-#define VIDEO_PLAY_FMT_NONE (0)
-/* The decoder requires full GOPs */
-#define VIDEO_PLAY_FMT_GOP (1)
-
-/* The structure must be zeroed before use by the application
- This ensures it can be extended safely in the future. */
-struct video_command {
- uint32_t cmd;
- uint32_t flags;
- union {
- struct {
- uint64_t pts;
- } stop;
-
- struct {
- /* 0 or 1000 specifies normal speed,
- 1 specifies forward single stepping,
- -1 specifies backward single stepping,
- >1: playback at speed/1000 of the normal speed,
- <-1: reverse playback at (-speed/1000) of the normal speed. */
- int32_t speed;
- uint32_t format;
- } play;
-
- struct {
- uint32_t data[16];
- } raw;
- };
-};
-
-/* FIELD_UNKNOWN can be used if the hardware does not know whether
- the Vsync is for an odd, even or progressive (i.e. non-interlaced)
- field. */
-#define VIDEO_VSYNC_FIELD_UNKNOWN (0)
-#define VIDEO_VSYNC_FIELD_ODD (1)
-#define VIDEO_VSYNC_FIELD_EVEN (2)
-#define VIDEO_VSYNC_FIELD_PROGRESSIVE (3)
-
-struct video_event {
- int32_t type;
-#define VIDEO_EVENT_SIZE_CHANGED 1
-#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
-#define VIDEO_EVENT_DECODER_STOPPED 3
-#define VIDEO_EVENT_VSYNC 4
- struct timespec timestamp;
- union {
- video_size_t size;
- unsigned int frame_rate; /* in frames per 1000sec */
- unsigned char vsync_field; /* unknown/odd/even/progressive */
- } u;
-};
-
-
-struct video_status {
- int video_blank; /* blank video on freeze? */
- video_play_state_t play_state; /* current state of playback */
- video_stream_source_t stream_source; /* current source (demux/memory) */
- video_format_t video_format; /* current aspect ratio of stream*/
- video_displayformat_t display_format;/* selected cropping mode */
-};
-
-
-struct video_still_picture {
- char *iFrame; /* pointer to a single iframe in memory */
- int32_t size;
-};
-
-
-typedef
-struct video_highlight {
- int active; /* 1=show highlight, 0=hide highlight */
- uint8_t contrast1; /* 7- 4 Pattern pixel contrast */
- /* 3- 0 Background pixel contrast */
- uint8_t contrast2; /* 7- 4 Emphasis pixel-2 contrast */
- /* 3- 0 Emphasis pixel-1 contrast */
- uint8_t color1; /* 7- 4 Pattern pixel color */
- /* 3- 0 Background pixel color */
- uint8_t color2; /* 7- 4 Emphasis pixel-2 color */
- /* 3- 0 Emphasis pixel-1 color */
- uint32_t ypos; /* 23-22 auto action mode */
- /* 21-12 start y */
- /* 9- 0 end y */
- uint32_t xpos; /* 23-22 button color number */
- /* 21-12 start x */
- /* 9- 0 end x */
-} video_highlight_t;
-
-
-typedef struct video_spu {
- int active;
- int stream_id;
-} video_spu_t;
-
-
-typedef struct video_spu_palette { /* SPU Palette information */
- int length;
- uint8_t *palette;
-} video_spu_palette_t;
-
-
-typedef struct video_navi_pack {
- int length; /* 0 ... 1024 */
- uint8_t data[1024];
-} video_navi_pack_t;
-
-
-typedef uint16_t video_attributes_t;
-/* bits: descr. */
-/* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
-/* 13-12 TV system (0=525/60, 1=625/50) */
-/* 11-10 Aspect ratio (0=4:3, 3=16:9) */
-/* 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
-/* 7 line 21-1 data present in GOP (1=yes, 0=no) */
-/* 6 line 21-2 data present in GOP (1=yes, 0=no) */
-/* 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
-/* 2 source letterboxed (1=yes, 0=no) */
-/* 0 film/camera mode (0=camera, 1=film (625/50 only)) */
-
-
-/* bit definitions for capabilities: */
-/* can the hardware decode MPEG1 and/or MPEG2? */
-#define VIDEO_CAP_MPEG1 1
-#define VIDEO_CAP_MPEG2 2
-/* can you send a system and/or program stream to video device?
- (you still have to open the video and the audio device but only
- send the stream to the video device) */
-#define VIDEO_CAP_SYS 4
-#define VIDEO_CAP_PROG 8
-/* can the driver also handle SPU, NAVI and CSS encoded data?
- (CSS API is not present yet) */
-#define VIDEO_CAP_SPU 16
-#define VIDEO_CAP_NAVI 32
-#define VIDEO_CAP_CSS 64
-
-
-#define VIDEO_STOP _IO('o', 21)
-#define VIDEO_PLAY _IO('o', 22)
-#define VIDEO_FREEZE _IO('o', 23)
-#define VIDEO_CONTINUE _IO('o', 24)
-#define VIDEO_SELECT_SOURCE _IO('o', 25)
-#define VIDEO_SET_BLANK _IO('o', 26)
-#define VIDEO_GET_STATUS _IOR('o', 27, struct video_status)
-#define VIDEO_GET_EVENT _IOR('o', 28, struct video_event)
-#define VIDEO_SET_DISPLAY_FORMAT _IO('o', 29)
-#define VIDEO_STILLPICTURE _IOW('o', 30, struct video_still_picture)
-#define VIDEO_FAST_FORWARD _IO('o', 31)
-#define VIDEO_SLOWMOTION _IO('o', 32)
-#define VIDEO_GET_CAPABILITIES _IOR('o', 33, unsigned int)
-#define VIDEO_CLEAR_BUFFER _IO('o', 34)
-#define VIDEO_SET_ID _IO('o', 35)
-#define VIDEO_SET_STREAMTYPE _IO('o', 36)
-#define VIDEO_SET_FORMAT _IO('o', 37)
-#define VIDEO_SET_SYSTEM _IO('o', 38)
-#define VIDEO_SET_HIGHLIGHT _IOW('o', 39, video_highlight_t)
-#define VIDEO_SET_SPU _IOW('o', 50, video_spu_t)
-#define VIDEO_SET_SPU_PALETTE _IOW('o', 51, video_spu_palette_t)
-#define VIDEO_GET_NAVI _IOR('o', 52, video_navi_pack_t)
-#define VIDEO_SET_ATTRIBUTES _IO('o', 53)
-#define VIDEO_GET_SIZE _IOR('o', 55, video_size_t)
-#define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int)
-
-/**
- * VIDEO_GET_PTS
- *
- * Read the 33 bit presentation time stamp as defined
- * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
- *
- * The PTS should belong to the currently played
- * frame if possible, but may also be a value close to it
- * like the PTS of the last decoded frame or the last PTS
- * extracted by the PES parser.
- */
-#define VIDEO_GET_PTS _IOR('o', 57, uint64_t)
-
-/* Read the number of displayed frames since the decoder was started */
-#define VIDEO_GET_FRAME_COUNT _IOR('o', 58, uint64_t)
-
-#define VIDEO_COMMAND _IOWR('o', 59, struct video_command)
-#define VIDEO_TRY_COMMAND _IOWR('o', 60, struct video_command)
-
-#endif /* _UAPI_DVBVIDEO_H_ */
diff --git a/contrib/freebsd/include/linux/input.h b/contrib/freebsd/include/linux/input.h
index 615cf76b..431deb73 100644
--- a/contrib/freebsd/include/linux/input.h
+++ b/contrib/freebsd/include/linux/input.h
@@ -200,6 +200,7 @@ struct input_keymap_entry {
#define INPUT_PROP_DIRECT 0x01 /* direct input devices */
#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
+#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
#define INPUT_PROP_MAX 0x1f
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
diff --git a/contrib/freebsd/include/linux/uinput.h b/contrib/freebsd/include/linux/uinput.h
index 687e3ce7..add58b9f 100644
--- a/contrib/freebsd/include/linux/uinput.h
+++ b/contrib/freebsd/include/linux/uinput.h
@@ -20,6 +20,8 @@
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
*
* Changes/Revisions:
+ * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ * - add UI_GET_SYSNAME ioctl
* 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
* - update ff support for the changes in kernel interface
* - add UINPUT_VERSION
@@ -34,7 +36,7 @@
#include <linux/input.h>
-#define UINPUT_VERSION 3
+#define UINPUT_VERSION 4
struct uinput_ff_upload {
@@ -72,6 +74,15 @@ struct uinput_ff_erase {
#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
+/**
+ * UI_GET_SYSNAME - get the sysfs name of the created uinput device
+ *
+ * @return the sysfs name of the created virtual input device.
+ * The complete sysfs path is then /sys/devices/virtual/input/--NAME--
+ * Usually, it is in the form "inputN"
+ */
+#define UI_GET_SYSNAME(len) _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 300, len)
+
/*
* To write a force-feedback-capable driver, the upload_effect
* and erase_effect callbacks in input_dev must be implemented.
diff --git a/contrib/freebsd/include/linux/v4l2-common.h b/contrib/freebsd/include/linux/v4l2-common.h
index 270db891..0b663bab 100644
--- a/contrib/freebsd/include/linux/v4l2-common.h
+++ b/contrib/freebsd/include/linux/v4l2-common.h
@@ -29,6 +29,8 @@
#ifndef __V4L2_COMMON__
#define __V4L2_COMMON__
+#include <sys/types.h>
+
/*
*
* Selection interface definitions
@@ -69,11 +71,11 @@
#define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG V4L2_SEL_FLAG_KEEP_CONFIG
struct v4l2_edid {
- __u32 pad;
- __u32 start_block;
- __u32 blocks;
- __u32 reserved[5];
- __u8 __user *edid;
+ uint32_t pad;
+ uint32_t start_block;
+ uint32_t blocks;
+ uint32_t reserved[5];
+ uint8_t *edid;
};
#endif /* __V4L2_COMMON__ */
diff --git a/contrib/freebsd/include/linux/videodev2.h b/contrib/freebsd/include/linux/videodev2.h
index 7f1d242e..94585831 100644
--- a/contrib/freebsd/include/linux/videodev2.h
+++ b/contrib/freebsd/include/linux/videodev2.h
@@ -683,7 +683,6 @@ struct v4l2_plane {
* @length: size in bytes of the buffer (NOT its payload) for single-plane
* buffers (when type != *_MPLANE); number of elements in the
* planes array for multi-plane buffers
- * @input: input number from which the video data has has been captured
*
* Contains data exchanged by application and driver using one of the Streaming
* I/O methods.
@@ -1114,14 +1113,14 @@ struct v4l2_bt_timings {
/* A few useful defines to calculate the total blanking and frame sizes */
#define V4L2_DV_BT_BLANKING_WIDTH(bt) \
- (bt->hfrontporch + bt->hsync + bt->hbackporch)
+ ((bt)->hfrontporch + (bt)->hsync + (bt)->hbackporch)
#define V4L2_DV_BT_FRAME_WIDTH(bt) \
- (bt->width + V4L2_DV_BT_BLANKING_WIDTH(bt))
+ ((bt)->width + V4L2_DV_BT_BLANKING_WIDTH(bt))
#define V4L2_DV_BT_BLANKING_HEIGHT(bt) \
- (bt->vfrontporch + bt->vsync + bt->vbackporch + \
- bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch)
+ ((bt)->vfrontporch + (bt)->vsync + (bt)->vbackporch + \
+ (bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch)
#define V4L2_DV_BT_FRAME_HEIGHT(bt) \
- (bt->height + V4L2_DV_BT_BLANKING_HEIGHT(bt))
+ ((bt)->height + V4L2_DV_BT_BLANKING_HEIGHT(bt))
/** struct v4l2_dv_timings - DV timings
* @type: the type of the timings
@@ -1141,12 +1140,15 @@ struct v4l2_dv_timings {
/** struct v4l2_enum_dv_timings - DV timings enumeration
* @index: enumeration index
+ * @pad: the pad number for which to enumerate timings (used with
+ * v4l-subdev nodes only)
* @reserved: must be zeroed
* @timings: the timings for the given index
*/
struct v4l2_enum_dv_timings {
uint32_t index;
- uint32_t reserved[3];
+ uint32_t pad;
+ uint32_t reserved[2];
struct v4l2_dv_timings timings;
};
@@ -1184,11 +1186,14 @@ struct v4l2_bt_timings_cap {
/** struct v4l2_dv_timings_cap - DV timings capabilities
* @type: the type of the timings (same as in struct v4l2_dv_timings)
+ * @pad: the pad number for which to query capabilities (used with
+ * v4l-subdev nodes only)
* @bt: the BT656/1120 timings capabilities
*/
struct v4l2_dv_timings_cap {
uint32_t type;
- uint32_t reserved[3];
+ uint32_t pad;
+ uint32_t reserved[2];
union {
struct v4l2_bt_timings_cap bt;
uint32_t raw_data[32];
@@ -1799,6 +1804,7 @@ struct v4l2_streamparm {
#define V4L2_EVENT_EOS 2
#define V4L2_EVENT_CTRL 3
#define V4L2_EVENT_FRAME_SYNC 4
+#define V4L2_EVENT_SOURCE_CHANGE 5
#define V4L2_EVENT_PRIVATE_START 0x08000000
/* Payload for V4L2_EVENT_VSYNC */
@@ -1830,12 +1836,19 @@ struct v4l2_event_frame_sync {
uint32_t frame_sequence;
};
+#define V4L2_EVENT_SRC_CH_RESOLUTION (1 << 0)
+
+struct v4l2_event_src_change {
+ uint32_t changes;
+};
+
struct v4l2_event {
uint32_t type;
union {
struct v4l2_event_vsync vsync;
struct v4l2_event_ctrl ctrl;
struct v4l2_event_frame_sync frame_sync;
+ struct v4l2_event_src_change src_change;
uint8_t data[64];
} u;
uint32_t pending;
diff --git a/contrib/freebsd/patches/dvb-audio-header.diff b/contrib/freebsd/patches/dvb-audio-header.diff
deleted file mode 100644
index 70437a45..00000000
--- a/contrib/freebsd/patches/dvb-audio-header.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/include/linux/dvb/audio.h
-+++ b/include/linux/dvb/audio.h
-@@ -24,7 +24,7 @@
- #ifndef _DVBAUDIO_H_
- #define _DVBAUDIO_H_
-
--#include <linux/types.h>
-+#include <sys/types.h>
-
- typedef enum {
- AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
diff --git a/contrib/freebsd/patches/dvb-dmx-header.diff b/contrib/freebsd/patches/dvb-dmx-header.diff
deleted file mode 100644
index b86cb8f3..00000000
--- a/contrib/freebsd/patches/dvb-dmx-header.diff
+++ /dev/null
@@ -1,15 +0,0 @@
---- freebsd/include/linux/dvb/dmx.h.orig 2012-12-05 10:26:23.000000000 +0100
-+++ freebsd/include/linux/dvb/dmx.h 2012-12-05 10:27:35.989684418 +0100
-@@ -24,10 +24,9 @@
- #ifndef _UAPI_DVBDMX_H_
- #define _UAPI_DVBDMX_H_
-
--#include <linux/types.h>
--#ifndef __KERNEL__
-+#include <stdint.h>
-+#include <sys/types.h>
- #include <time.h>
--#endif
-
-
- #define DMX_FILTER_SIZE 16
diff --git a/contrib/freebsd/patches/dvb-frontend-header.diff b/contrib/freebsd/patches/dvb-frontend-header.diff
deleted file mode 100644
index 83766680..00000000
--- a/contrib/freebsd/patches/dvb-frontend-header.diff
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/include/linux/dvb/frontend.h
-+++ b/include/linux/dvb/frontend.h
-@@ -26,7 +26,8 @@
- #ifndef _DVBFRONTEND_H_
- #define _DVBFRONTEND_H_
-
--#include <linux/types.h>
-+#include <stdint.h>
-+#include <sys/types.h>
-
- typedef enum fe_type {
- FE_QPSK,
diff --git a/contrib/freebsd/patches/dvb-net-header.diff b/contrib/freebsd/patches/dvb-net-header.diff
deleted file mode 100644
index 24838c3c..00000000
--- a/contrib/freebsd/patches/dvb-net-header.diff
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/include/linux/dvb/net.h
-+++ b/include/linux/dvb/net.h
-@@ -24,7 +24,8 @@
- #ifndef _DVBNET_H_
- #define _DVBNET_H_
-
--#include <linux/types.h>
-+#include <stdint.h>
-+#include <sys/types.h>
-
- struct dvb_net_if {
- uint16_t pid;
diff --git a/contrib/freebsd/patches/dvb-osd-header.diff b/contrib/freebsd/patches/dvb-osd-header.diff
deleted file mode 100644
index a2938743..00000000
--- a/contrib/freebsd/patches/dvb-osd-header.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/include/linux/dvb/osd.h
-+++ b/include/linux/dvb/osd.h
-@@ -24,7 +24,7 @@
- #ifndef _DVBOSD_H_
- #define _DVBOSD_H_
-
--#include <linux/compiler.h>
-+#include <sys/types.h>
-
- typedef enum {
- // All functions return -2 on "not open"
diff --git a/contrib/freebsd/patches/dvb-video-header.diff b/contrib/freebsd/patches/dvb-video-header.diff
deleted file mode 100644
index 7d9fc0e6..00000000
--- a/contrib/freebsd/patches/dvb-video-header.diff
+++ /dev/null
@@ -1,15 +0,0 @@
---- freebsd/include/linux/dvb/video.h.orig 2012-12-05 10:28:14.000000000 +0100
-+++ freebsd/include/linux/dvb/video.h 2012-12-05 10:29:13.054783858 +0100
-@@ -24,11 +24,9 @@
- #ifndef _UAPI_DVBVIDEO_H_
- #define _UAPI_DVBVIDEO_H_
-
--#include <linux/types.h>
--#ifndef __KERNEL__
-+#include <sys/types.h>
- #include <stdint.h>
- #include <time.h>
--#endif
-
- typedef enum {
- VIDEO_FORMAT_4_3, /* Select 4:3 format */
diff --git a/contrib/freebsd/patches/dvb-video-timestamp.diff b/contrib/freebsd/patches/dvb-video-timestamp.diff
deleted file mode 100644
index f73f8eaf..00000000
--- a/contrib/freebsd/patches/dvb-video-timestamp.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/include/linux/dvb/video.h
-+++ b/include/linux/dvb/video.h
-@@ -133,7 +133,7 @@
- #define VIDEO_EVENT_FRAME_RATE_CHANGED 2
- #define VIDEO_EVENT_DECODER_STOPPED 3
- #define VIDEO_EVENT_VSYNC 4
-- __kernel_time_t timestamp;
-+ struct timespec timestamp;
- union {
- video_size_t size;
- unsigned int frame_rate; /* in frames per 1000sec */
diff --git a/contrib/freebsd/patches/input-header.diff b/contrib/freebsd/patches/input-header.diff
index db1194ce..d9c7d66c 100644
--- a/contrib/freebsd/patches/input-header.diff
+++ b/contrib/freebsd/patches/input-header.diff
@@ -1,11 +1,10 @@
--- freebsd/include/linux/input.h.orig 2012-12-05 10:18:56.000000000 +0100
+++ freebsd/include/linux/input.h 2012-12-05 10:22:11.228350200 +0100
-@@ -8,13 +8,49 @@
- #ifndef _UAPI_INPUT_H
- #define _UAPI_INPUT_H
+@@ -8,11 +8,47 @@
+ #ifndef _INPUT_H
+ #define _INPUT_H
-
- #ifndef __KERNEL__
+#include <stdint.h>
#include <sys/time.h>
#include <sys/ioctl.h>
@@ -46,7 +45,6 @@
+#define _IOC_WRITE IOC_IN
+#else
#include <linux/types.h>
- #endif
+#endif
diff --git a/contrib/freebsd/patches/ivtv-header.diff b/contrib/freebsd/patches/ivtv-header.diff
index 549ce40c..53573da2 100644
--- a/contrib/freebsd/patches/ivtv-header.diff
+++ b/contrib/freebsd/patches/ivtv-header.diff
@@ -1,10 +1,9 @@
--- a/include/linux/ivtv.h
+++ b/include/linux/ivtv.h
-@@ -21,8 +21,8 @@
- #ifndef __LINUX_IVTV_H__
+@@ -22,7 +22,8 @@
#define __LINUX_IVTV_H__
--#include <linux/compiler.h>
+
-#include <linux/types.h>
+#include <stdint.h>
+#include <sys/types.h>
diff --git a/contrib/freebsd/patches/series b/contrib/freebsd/patches/series
index a78be3e2..cc480a8b 100644
--- a/contrib/freebsd/patches/series
+++ b/contrib/freebsd/patches/series
@@ -2,10 +2,4 @@ input-header.diff
uinput-header.diff
ivtv-header.diff
videodev2-header.diff
-dvb-audio-header.diff
-dvb-dmx-header.diff
-dvb-frontend-header.diff
-dvb-net-header.diff
-dvb-osd-header.diff
-dvb-video-header.diff
-dvb-video-timestamp.diff
+v4l2-common-header.diff
diff --git a/contrib/freebsd/patches/uinput-header.diff b/contrib/freebsd/patches/uinput-header.diff
index a92f7d5b..537d529e 100644
--- a/contrib/freebsd/patches/uinput-header.diff
+++ b/contrib/freebsd/patches/uinput-header.diff
@@ -1,10 +1,10 @@
--- freebsd/include/linux/uinput.h.orig 2012-12-05 10:38:23.417354136 +0100
+++ freebsd/include/linux/uinput.h 2012-12-05 10:38:27.832358799 +0100
-@@ -32,7 +32,6 @@
- #ifndef _UAPI__UINPUT_H_
- #define _UAPI__UINPUT_H_
+@@ -34,7 +34,6 @@
+ #ifndef __UINPUT_H_
+ #define __UINPUT_H_
-#include <linux/types.h>
#include <linux/input.h>
- #define UINPUT_VERSION 3
+ #define UINPUT_VERSION 4
diff --git a/contrib/freebsd/patches/v4l2-common-header.diff b/contrib/freebsd/patches/v4l2-common-header.diff
new file mode 100644
index 00000000..efe5c018
--- /dev/null
+++ b/contrib/freebsd/patches/v4l2-common-header.diff
@@ -0,0 +1,13 @@
+Index: freebsd/include/linux/v4l2-common.h
+===================================================================
+--- freebsd.orig/include/linux/v4l2-common.h
++++ freebsd/include/linux/v4l2-common.h
+@@ -29,7 +29,7 @@
+ #ifndef __V4L2_COMMON__
+ #define __V4L2_COMMON__
+
+-#include <linux/types.h>
++#include <sys/types.h>
+
+ /*
+ *
diff --git a/contrib/freebsd/patches/videodev2-header.diff b/contrib/freebsd/patches/videodev2-header.diff
index f440e652..e8507467 100644
--- a/contrib/freebsd/patches/videodev2-header.diff
+++ b/contrib/freebsd/patches/videodev2-header.diff
@@ -1,14 +1,14 @@
--- freebsd/include/linux/videodev2.h.orig 2012-12-05 10:23:08.000000000 +0100
+++ freebsd/include/linux/videodev2.h 2012-12-05 10:25:46.864570965 +0100
-@@ -57,11 +57,45 @@
- #define _UAPI__LINUX_VIDEODEV2_H
+@@ -56,10 +56,44 @@
+ #ifndef __LINUX_VIDEODEV2_H
+ #define __LINUX_VIDEODEV2_H
- #ifndef __KERNEL__
+#include <stdint.h>
#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
-+
+
+#ifndef HAVE_LINUX_INTEGER_TYPES
+/* XXX remove when depending software has been updated */
+#ifndef __u64
@@ -26,7 +26,7 @@
+
+#ifndef __s64
+typedef int64_t __s64;
- #endif
++#endif
+#ifndef __s32
+typedef int32_t __s32;
+#endif
@@ -38,8 +38,7 @@
+#endif
+#endif
+
-+#else
- #include <linux/compiler.h>
++#ifdef __KERNEL__
#include <linux/ioctl.h>
#include <linux/types.h>
+#endif
diff --git a/contrib/m920x/m920x_parse.pl b/contrib/m920x/m920x_parse.pl
index 19ff71de..19ff71de 100644..100755
--- a/contrib/m920x/m920x_parse.pl
+++ b/contrib/m920x/m920x_parse.pl
diff --git a/contrib/m920x/m920x_sp_firmware.pl b/contrib/m920x/m920x_sp_firmware.pl
index 3c1f0fdb..3c1f0fdb 100644..100755
--- a/contrib/m920x/m920x_sp_firmware.pl
+++ b/contrib/m920x/m920x_sp_firmware.pl
diff --git a/contrib/qv4l2-qt3/.gitignore b/contrib/qv4l2-qt3/.gitignore
deleted file mode 100644
index 92036caa..00000000
--- a/contrib/qv4l2-qt3/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-Makefile
-moc_general-tab.cpp
-moc_qv4l2.cpp
-qv4l2
-
diff --git a/contrib/qv4l2-qt3/Makefile.install b/contrib/qv4l2-qt3/Makefile.install
deleted file mode 100644
index 22c0207d..00000000
--- a/contrib/qv4l2-qt3/Makefile.install
+++ /dev/null
@@ -1,5 +0,0 @@
-include Makefile
-
-install: qv4l2
- mkdir -p $(DESTDIR)$(PREFIX)/bin
- install -m 755 qv4l2 $(DESTDIR)$(PREFIX)/bin
diff --git a/contrib/qv4l2-qt3/ctrl-tab.cpp b/contrib/qv4l2-qt3/ctrl-tab.cpp
deleted file mode 100644
index 6f436b49..00000000
--- a/contrib/qv4l2-qt3/ctrl-tab.cpp
+++ /dev/null
@@ -1,592 +0,0 @@
-
-#include "qv4l2.h"
-#include "libv4l2util.h"
-
-#include <qstatusbar.h>
-#include <qlineedit.h>
-#include <qvalidator.h>
-#include <qlayout.h>
-#include <qvbox.h>
-#include <qhbox.h>
-#include <qlabel.h>
-#include <qslider.h>
-#include <qspinbox.h>
-#include <qcombobox.h>
-#include <qcheckbox.h>
-#include <qpushbutton.h>
-#include <qtooltip.h>
-#include <qwhatsthis.h>
-
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-
-void ApplicationWindow::addTabs()
-{
- struct v4l2_queryctrl qctrl;
- unsigned ctrl_class;
- unsigned i;
- int id;
-
- memset(&qctrl, 0, sizeof(qctrl));
- qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
- while (::ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0) {
- if ((qctrl.flags & V4L2_CTRL_FLAG_DISABLED) == 0) {
- ctrlMap[qctrl.id] = qctrl;
- if (qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS)
- classMap[V4L2_CTRL_ID2CLASS(qctrl.id)].push_back(qctrl.id);
- }
- qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
- }
- if (qctrl.id == V4L2_CTRL_FLAG_NEXT_CTRL) {
- strcpy((char *)qctrl.name, "User Controls");
- qctrl.id = V4L2_CTRL_CLASS_USER | 1;
- qctrl.type = V4L2_CTRL_TYPE_CTRL_CLASS;
- ctrlMap[qctrl.id] = qctrl;
- for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) {
- qctrl.id = id;
- if (::ioctl(fd, VIDIOC_QUERYCTRL, &qctrl))
- continue;
- if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED)
- continue;
- ctrlMap[qctrl.id] = qctrl;
- classMap[V4L2_CTRL_CLASS_USER].push_back(qctrl.id);
- }
- for (qctrl.id = V4L2_CID_PRIVATE_BASE;
- ::ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) {
- if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED)
- continue;
- ctrlMap[qctrl.id] = qctrl;
- classMap[V4L2_CTRL_CLASS_USER].push_back(qctrl.id);
- }
- }
-
- for (ClassMap::iterator iter = classMap.begin(); iter != classMap.end(); ++iter) {
- ctrl_class = V4L2_CTRL_ID2CLASS(iter->second[0]);
- id = ctrl_class | 1;
- const struct v4l2_queryctrl &qctrl = ctrlMap[id];
- QVBox *vbox = new QVBox(tabs);
- QGrid *grid = new QGrid(4, vbox);
- grid->setSpacing(3);
- tabs->addTab(vbox, (char *)qctrl.name);
- for (i = 0; i < iter->second.size(); i++) {
- if (i & 1)
- id = iter->second[(1+iter->second.size()) / 2 + i / 2];
- else
- id = iter->second[i / 2];
- addCtrl(grid, ctrlMap[id]);
- }
- finishGrid(vbox, grid, ctrl_class, i & 1);
- }
-}
-
-void ApplicationWindow::finishGrid(QWidget *vbox, QGrid *grid, unsigned ctrl_class, bool odd)
-{
- if (odd) {
- new QWidget(grid);
- new QWidget(grid);
- }
- QWidget *stretch = new QWidget(grid);
- stretch->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
-
- QFrame *frame = new QFrame(vbox);
- frame->setFrameShape(QFrame::HLine);
- frame->setFrameShadow(QFrame::Sunken);
- frame->setMargin(3);
-
- QHBox *hbox = new QHBox(vbox);
- hbox->setSpacing(3);
-
- QCheckBox *cbox = new QCheckBox("Update on change", hbox);
- widgetMap[ctrl_class | CTRL_UPDATE_ON_CHANGE] = cbox;
- connect(cbox, SIGNAL(clicked()), sigMapper, SLOT(map()));
- sigMapper->setMapping(cbox, ctrl_class | CTRL_UPDATE_ON_CHANGE);
-
- stretch = new QWidget(hbox);
- stretch->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
-
- QPushButton *defBut = new QPushButton("Set Defaults", hbox);
- widgetMap[ctrl_class | CTRL_DEFAULTS] = defBut;
- connect(defBut, SIGNAL(clicked()), sigMapper, SLOT(map()));
- sigMapper->setMapping(defBut, ctrl_class | CTRL_DEFAULTS);
-
- QPushButton *refreshBut = new QPushButton("Refresh", hbox);
- widgetMap[ctrl_class | CTRL_REFRESH] = refreshBut;
- connect(refreshBut, SIGNAL(clicked()), sigMapper, SLOT(map()));
- sigMapper->setMapping(refreshBut, ctrl_class | CTRL_REFRESH);
-
- QPushButton *button = new QPushButton("Update", hbox);
- widgetMap[ctrl_class | CTRL_UPDATE] = button;
- connect(button, SIGNAL(clicked()), sigMapper, SLOT(map()));
- sigMapper->setMapping(button, ctrl_class | CTRL_UPDATE);
- connect(cbox, SIGNAL(toggled(bool)), button, SLOT(setDisabled(bool)));
-
- cbox->setChecked(ctrl_class == V4L2_CTRL_CLASS_USER);
-
- refresh(ctrl_class);
-}
-
-void ApplicationWindow::addCtrl(QGrid *grid, const struct v4l2_queryctrl &qctrl)
-{
- QIntValidator *val;
- QLineEdit *edit;
- QString name((char *)qctrl.name);
- QComboBox *combo;
- struct v4l2_querymenu qmenu;
-
- QLabel *label = new QLabel(name, grid);
- label->setAlignment(Qt::AlignRight);
-
- switch (qctrl.type) {
- case V4L2_CTRL_TYPE_INTEGER:
- if (qctrl.flags & V4L2_CTRL_FLAG_SLIDER) {
- widgetMap[qctrl.id] =
- new QSlider(qctrl.minimum, qctrl.maximum,
- qctrl.step, qctrl.default_value,
- Horizontal, grid);
- connect(widgetMap[qctrl.id], SIGNAL(valueChanged(int)),
- sigMapper, SLOT(map()));
- break;
- }
-
- if (qctrl.maximum - qctrl.minimum <= 255) {
- widgetMap[qctrl.id] =
- new QSpinBox(qctrl.minimum, qctrl.maximum, 1, grid);
- connect(widgetMap[qctrl.id], SIGNAL(valueChanged(int)),
- sigMapper, SLOT(map()));
- break;
- }
-
- val = new QIntValidator(qctrl.minimum, qctrl.maximum, grid);
- edit = new QLineEdit(grid);
- edit->setValidator(val);
- widgetMap[qctrl.id] = edit;
- connect(widgetMap[qctrl.id], SIGNAL(lostFocus()),
- sigMapper, SLOT(map()));
- connect(widgetMap[qctrl.id], SIGNAL(returnPressed()),
- sigMapper, SLOT(map()));
- break;
-
- case V4L2_CTRL_TYPE_INTEGER64:
- widgetMap[qctrl.id] = new QLineEdit(grid);
- connect(widgetMap[qctrl.id], SIGNAL(lostFocus()),
- sigMapper, SLOT(map()));
- connect(widgetMap[qctrl.id], SIGNAL(returnPressed()),
- sigMapper, SLOT(map()));
- break;
-
- case V4L2_CTRL_TYPE_BOOLEAN:
- label->setText("");
- widgetMap[qctrl.id] = new QCheckBox(name, grid);
- connect(widgetMap[qctrl.id], SIGNAL(clicked()),
- sigMapper, SLOT(map()));
- break;
-
- case V4L2_CTRL_TYPE_BUTTON:
- label->setText("");
- widgetMap[qctrl.id] = new QPushButton((char *)qctrl.name, grid);
- connect(widgetMap[qctrl.id], SIGNAL(clicked()),
- sigMapper, SLOT(map()));
- break;
-
- case V4L2_CTRL_TYPE_MENU:
- combo = new QComboBox(grid);
- widgetMap[qctrl.id] = combo;
- for (int i = qctrl.minimum; i <= qctrl.maximum; i++) {
- qmenu.id = qctrl.id;
- qmenu.index = i;
- if (::ioctl(fd, VIDIOC_QUERYMENU, &qmenu))
- continue;
- combo->insertItem((char *)qmenu.name);
- }
- connect(widgetMap[qctrl.id], SIGNAL(activated(int)),
- sigMapper, SLOT(map()));
- break;
-
- default:
- return;
- }
- sigMapper->setMapping(widgetMap[qctrl.id], qctrl.id);
- if (qctrl.flags & (V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_INACTIVE))
- widgetMap[qctrl.id]->setDisabled(true);
-}
-
-void ApplicationWindow::ctrlAction(int id)
-{
- unsigned ctrl_class = V4L2_CTRL_ID2CLASS(id);
- if (ctrl_class == V4L2_CID_PRIVATE_BASE)
- ctrl_class = V4L2_CTRL_CLASS_USER;
- unsigned ctrl = id & 0xffff;
- QCheckBox *cbox = static_cast<QCheckBox *>(widgetMap[ctrl_class | CTRL_UPDATE_ON_CHANGE]);
- bool update = cbox->isChecked();
- bool all = (ctrl == CTRL_UPDATE || (update && ctrl == CTRL_UPDATE_ON_CHANGE));
-
- if (ctrl == CTRL_DEFAULTS) {
- setDefaults(ctrl_class);
- return;
- }
- if (ctrl == CTRL_REFRESH) {
- refresh(ctrl_class);
- return;
- }
- if (!update && !all && ctrlMap[id].type != V4L2_CTRL_TYPE_BUTTON)
- return;
- if (ctrl_class == V4L2_CTRL_CLASS_USER) {
- if (!all) {
- updateCtrl(id);
- return;
- }
- for (unsigned i = 0; i < classMap[ctrl_class].size(); i++) {
- updateCtrl(classMap[ctrl_class][i]);
- }
- return;
- }
- if (!all) {
- updateCtrl(id);
- return;
- }
- unsigned count = classMap[ctrl_class].size();
- struct v4l2_ext_control *c = new v4l2_ext_control[count];
- struct v4l2_ext_controls ctrls;
- int idx = 0;
-
- for (unsigned i = 0; i < count; i++) {
- unsigned id = classMap[ctrl_class][i];
-
- if (ctrlMap[id].flags & (V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_INACTIVE))
- continue;
- c[idx].id = id;
- if (ctrlMap[id].type == V4L2_CTRL_TYPE_INTEGER64)
- c[idx].value64 = getVal64(id);
- else
- c[idx].value = getVal(id);
- idx++;
- }
- memset(&ctrls, 0, sizeof(ctrls));
- ctrls.count = idx;
- ctrls.ctrl_class = ctrl_class;
- ctrls.controls = c;
- if (::ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls)) {
- int err = errno;
-
- if (ctrls.error_idx >= ctrls.count) {
- printf("error: %s\n", strerror(err));
- }
- else {
- id = c[ctrls.error_idx].id;
- printf("error %08x (%s): %s\n", id,
- ctrlMap[id].name, strerror(err));
- }
- }
- delete [] c;
- refresh(ctrl_class);
-}
-
-long long ApplicationWindow::getVal64(unsigned id)
-{
- const v4l2_queryctrl &qctrl = ctrlMap[id];
- QWidget *w = widgetMap[qctrl.id];
- long long v = 0;
-
- switch (qctrl.type) {
- case V4L2_CTRL_TYPE_INTEGER64:
- v = static_cast<QLineEdit *>(w)->text().toLongLong();
- break;
- default:
- break;
- }
- setWhat(w, id, v);
- return v;
-}
-
-int ApplicationWindow::getVal(unsigned id)
-{
- const v4l2_queryctrl &qctrl = ctrlMap[id];
- QWidget *w = widgetMap[qctrl.id];
- v4l2_querymenu qmenu;
- int i, idx;
- int v = 0;
-
- switch (qctrl.type) {
- case V4L2_CTRL_TYPE_INTEGER:
- if (qctrl.flags & V4L2_CTRL_FLAG_SLIDER) {
- v = static_cast<QSlider *>(w)->value();
- break;
- }
-
- if (qctrl.maximum - qctrl.minimum <= 255) {
- v = static_cast<QSpinBox *>(w)->value();
- break;
- }
- v = static_cast<QLineEdit *>(w)->text().toInt();
- break;
-
- case V4L2_CTRL_TYPE_BOOLEAN:
- v = static_cast<QCheckBox *>(w)->isChecked();
- break;
-
- case V4L2_CTRL_TYPE_MENU:
- idx = static_cast<QComboBox *>(w)->currentItem();
- for (i = qctrl.minimum; i <= qctrl.maximum; i++) {
- qmenu.id = qctrl.id;
- qmenu.index = i;
- if (::ioctl(fd, VIDIOC_QUERYMENU, &qmenu))
- continue;
- if (idx-- == 0)
- break;
- }
- v = i;
- break;
-
- default:
- break;
- }
- setWhat(w, id, v);
- return v;
-}
-
-void ApplicationWindow::updateCtrl(unsigned id)
-{
- unsigned ctrl_class = V4L2_CTRL_ID2CLASS(id);
- if (ctrl_class == V4L2_CID_PRIVATE_BASE)
- ctrl_class = V4L2_CTRL_CLASS_USER;
-
- if (ctrlMap[id].flags & (V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_INACTIVE))
- return;
-
- if (ctrl_class == V4L2_CTRL_CLASS_USER) {
- struct v4l2_control c;
-
- c.id = id;
- c.value = getVal(id);
- if (::ioctl(fd, VIDIOC_S_CTRL, &c)) {
- int err = errno;
- char buf[200];
-
- sprintf(buf, "Error %08x (%s): %s", id,
- ctrlMap[id].name, strerror(err));
- statusBar()->message(buf, 10000);
- }
- return;
- }
- struct v4l2_ext_control c;
- struct v4l2_ext_controls ctrls;
-
- memset(&c, 0, sizeof(c));
- memset(&ctrls, 0, sizeof(ctrls));
- c.id = id;
- if (ctrlMap[id].type == V4L2_CTRL_TYPE_INTEGER64)
- c.value64 = getVal64(id);
- else
- c.value = getVal(id);
- ctrls.count = 1;
- ctrls.ctrl_class = ctrl_class;
- ctrls.controls = &c;
- if (::ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls)) {
- int err = errno;
- char buf[200];
-
- sprintf(buf, "Error %08x (%s): %s", id,
- ctrlMap[id].name, strerror(err));
- statusBar()->message(buf, 10000);
- }
- else if (ctrlMap[id].flags & V4L2_CTRL_FLAG_UPDATE)
- refresh(ctrl_class);
- else {
- if (ctrlMap[id].type == V4L2_CTRL_TYPE_INTEGER64)
- setVal64(id, c.value64);
- else
- setVal(id, c.value);
- }
-}
-
-void ApplicationWindow::refresh(unsigned ctrl_class)
-{
- if (ctrl_class == V4L2_CTRL_CLASS_USER) {
- for (unsigned i = 0; i < classMap[ctrl_class].size(); i++) {
- unsigned id = classMap[ctrl_class][i];
-
- v4l2_control c;
-
- c.id = id;
- if (::ioctl(fd, VIDIOC_G_CTRL, &c)) {
- int err = errno;
- char buf[200];
-
- sprintf(buf, "Error %08x (%s): %s", id,
- ctrlMap[id].name, strerror(err));
- statusBar()->message(buf, 10000);
- }
- setVal(id, c.value);
- }
- return;
- }
- unsigned count = classMap[ctrl_class].size();
- struct v4l2_ext_control *c = new v4l2_ext_control[count];
- struct v4l2_ext_controls ctrls;
-
- for (unsigned i = 0; i < count; i++) {
- c[i].id = classMap[ctrl_class][i];
- }
- memset(&ctrls, 0, sizeof(ctrls));
- ctrls.count = count;
- ctrls.ctrl_class = ctrl_class;
- ctrls.controls = c;
- if (::ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls)) {
- int err = errno;
-
- if (ctrls.error_idx >= ctrls.count) {
- statusBar()->message(strerror(err), 10000);
- }
- else {
- unsigned id = c[ctrls.error_idx].id;
- char buf[200];
-
- sprintf(buf, "Error %08x (%s): %s", id,
- ctrlMap[id].name, strerror(err));
- statusBar()->message(buf, 10000);
- }
- }
- else {
- for (unsigned i = 0; i < ctrls.count; i++) {
- unsigned id = c[i].id;
- if (ctrlMap[id].type == V4L2_CTRL_TYPE_INTEGER64)
- setVal64(id, c[i].value64);
- else
- setVal(id, c[i].value);
- ::ioctl(fd, VIDIOC_QUERYCTRL, &ctrlMap[id]);
- widgetMap[id]->setDisabled(ctrlMap[id].flags &
- (V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_INACTIVE));
- }
- }
- delete [] c;
-}
-
-void ApplicationWindow::setWhat(QWidget *w, unsigned id, long long v)
-{
- const v4l2_queryctrl &qctrl = ctrlMap[id];
- QString what;
- QString flags = getCtrlFlags(qctrl.flags);
-
- switch (qctrl.type) {
- case V4L2_CTRL_TYPE_INTEGER:
- QWhatsThis::add(w, what.sprintf("Integer type control\n"
- "Minimum: %d\n"
- "Maximum: %d\n"
- "Current: %d\n"
- "Default: %d\n",
- qctrl.minimum, qctrl.maximum, (int)v, qctrl.default_value) + flags);
- break;
-
- case V4L2_CTRL_TYPE_INTEGER64:
- QWhatsThis::add(w, what.sprintf("64-bit Integer type control\n"
- "Current: %lld\n", v) + flags);
- break;
-
- case V4L2_CTRL_TYPE_BUTTON:
- QWhatsThis::add(w, what.sprintf("Button type control\n") + flags);
- break;
-
- case V4L2_CTRL_TYPE_BOOLEAN:
- QWhatsThis::add(w, what.sprintf("Boolean type control\n"
- "Current: %d\n"
- "Default: %d\n",
- (int)v, qctrl.default_value) + flags);
- break;
-
- case V4L2_CTRL_TYPE_MENU:
- QWhatsThis::add(w, what.sprintf("Menu type control\n"
- "Minimum: %d\n"
- "Maximum: %d\n"
- "Current: %d\n"
- "Default: %d\n",
- qctrl.minimum, qctrl.maximum, (int)v, qctrl.default_value) + flags);
- break;
- default:
- break;
- }
-}
-
-void ApplicationWindow::setVal(unsigned id, int v)
-{
- const v4l2_queryctrl &qctrl = ctrlMap[id];
- v4l2_querymenu qmenu;
- QWidget *w = widgetMap[qctrl.id];
- int i, idx;
-
- switch (qctrl.type) {
- case V4L2_CTRL_TYPE_INTEGER:
- if (qctrl.flags & V4L2_CTRL_FLAG_SLIDER)
- static_cast<QSlider *>(w)->setValue(v);
- else if (qctrl.maximum - qctrl.minimum <= 255)
- static_cast<QSpinBox *>(w)->setValue(v);
- else
- static_cast<QLineEdit *>(w)->setText(QString::number(v));
- break;
-
- case V4L2_CTRL_TYPE_BOOLEAN:
- static_cast<QCheckBox *>(w)->setChecked(v);
- break;
-
- case V4L2_CTRL_TYPE_MENU:
- idx = 0;
- for (i = qctrl.minimum; i <= v; i++) {
- qmenu.id = id;
- qmenu.index = i;
- if (::ioctl(fd, VIDIOC_QUERYMENU, &qmenu))
- continue;
- idx++;
- }
- static_cast<QComboBox *>(w)->setCurrentItem(idx - 1);
- break;
- default:
- break;
- }
- setWhat(w, id, v);
-}
-
-void ApplicationWindow::setVal64(unsigned id, long long v)
-{
- const v4l2_queryctrl &qctrl = ctrlMap[id];
- QWidget *w = widgetMap[qctrl.id];
-
- switch (qctrl.type) {
- case V4L2_CTRL_TYPE_INTEGER64:
- static_cast<QLineEdit *>(w)->setText(QString::number(v));
- break;
- default:
- break;
- }
- setWhat(w, id, v);
-}
-
-void ApplicationWindow::setDefaults(unsigned ctrl_class)
-{
- for (unsigned i = 0; i < classMap[ctrl_class].size(); i++) {
- unsigned id = classMap[ctrl_class][i];
-
- if (ctrlMap[id].type != V4L2_CTRL_TYPE_INTEGER64 &&
- ctrlMap[id].type != V4L2_CTRL_TYPE_BUTTON)
- setVal(id, ctrlMap[id].default_value);
- }
- ctrlAction(ctrl_class | CTRL_UPDATE);
-}
-
-QString ApplicationWindow::getCtrlFlags(unsigned flags)
-{
- QString s;
-
- if (flags & V4L2_CTRL_FLAG_GRABBED)
- s += "grabbed ";
- if (flags & V4L2_CTRL_FLAG_READ_ONLY)
- s += "readonly ";
- if (flags & V4L2_CTRL_FLAG_UPDATE)
- s += "update ";
- if (flags & V4L2_CTRL_FLAG_INACTIVE)
- s += "inactive ";
- if (flags & V4L2_CTRL_FLAG_SLIDER)
- s += "slider ";
- if (s.length()) s = QString("Flags: ") + s;
- return s;
-}
-
diff --git a/contrib/qv4l2-qt3/fileopen.xpm b/contrib/qv4l2-qt3/fileopen.xpm
deleted file mode 100644
index 880417ee..00000000
--- a/contrib/qv4l2-qt3/fileopen.xpm
+++ /dev/null
@@ -1,22 +0,0 @@
-/* XPM */
-static const char *fileopen[] = {
-" 16 13 5 1",
-". c #040404",
-"# c #808304",
-"a c None",
-"b c #f3f704",
-"c c #f3f7f3",
-"aaaaaaaaa...aaaa",
-"aaaaaaaa.aaa.a.a",
-"aaaaaaaaaaaaa..a",
-"a...aaaaaaaa...a",
-".bcb.......aaaaa",
-".cbcbcbcbc.aaaaa",
-".bcbcbcbcb.aaaaa",
-".cbcb...........",
-".bcb.#########.a",
-".cb.#########.aa",
-".b.#########.aaa",
-"..#########.aaaa",
-"...........aaaaa"
-};
diff --git a/contrib/qv4l2-qt3/general-tab.cpp b/contrib/qv4l2-qt3/general-tab.cpp
deleted file mode 100644
index 78656cf1..00000000
--- a/contrib/qv4l2-qt3/general-tab.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-/* qv4l2: a control panel controlling v4l2 devices.
- *
- * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
-#include "qv4l2.h"
-#include "general-tab.h"
-#include "libv4l2util.h"
-
-#include <qlabel.h>
-#include <qspinbox.h>
-#include <qcombobox.h>
-#include <qwhatsthis.h>
-
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-
-GeneralTab::GeneralTab(const char *device, int _fd, int n, QWidget *parent) :
- QGrid(n, parent),
- fd(_fd)
-{
- int cnt = 0;
-
- setSpacing(3);
-
- memset(&querycap, 0, sizeof(querycap));
- if (ioctl(fd, VIDIOC_QUERYCAP, &querycap) >=0) {
- QLabel *l1 = new QLabel("Device:", this);
- new QLabel(device, this);
- l1->setAlignment(Qt::AlignRight);
-
- QLabel *l2 = new QLabel("Driver:", this);
- l2->setAlignment(Qt::AlignRight);
-
- new QLabel((char *)querycap.driver, this);
-
- QLabel *l3 = new QLabel("Card:", this);
- l3->setAlignment(Qt::AlignRight);
-
- new QLabel((char *)querycap.card, this);
-
- QLabel *l4 = new QLabel("Bus:", this);
- l4->setAlignment(Qt::AlignRight);
-
- new QLabel((char *)querycap.bus_info, this);
- }
-
- memset(&tuner, 0, sizeof(tuner));
- ioctl(fd, VIDIOC_G_TUNER, &tuner);
- if (tuner.rangehigh>INT_MAX)
- tuner.rangehigh=INT_MAX;
-
- struct v4l2_input vin;
- memset(&vin, 0, sizeof(vin));
- if (ioctl(fd, VIDIOC_ENUMINPUT, &vin) >= 0) {
- QLabel *label = new QLabel("Input", this);
- label->setAlignment(Qt::AlignRight);
- videoInput = new QComboBox(this);
- while (ioctl(fd, VIDIOC_ENUMINPUT, &vin) >= 0) {
- videoInput->insertItem((char *)vin.name);
- vin.index++;
- }
- connect(videoInput, SIGNAL(activated(int)), SLOT(inputChanged(int)));
- updateVideoInput();
- cnt++;
- }
-
- struct v4l2_output vout;
- memset(&vout, 0, sizeof(vout));
- if (ioctl(fd, VIDIOC_ENUMOUTPUT, &vout) >= 0) {
- QLabel *label = new QLabel("Output", this);
- label->setAlignment(Qt::AlignRight);
- videoOutput = new QComboBox(this);
- while (ioctl(fd, VIDIOC_ENUMOUTPUT, &vout) >= 0) {
- videoOutput->insertItem((char *)vout.name);
- vout.index++;
- }
- connect(videoOutput, SIGNAL(activated(int)), SLOT(outputChanged(int)));
- updateVideoOutput();
- cnt++;
- }
-
- struct v4l2_audio vaudio;
- memset(&vaudio, 0, sizeof(vaudio));
- if (ioctl(fd, VIDIOC_ENUMAUDIO, &vaudio) >= 0) {
- QLabel *label = new QLabel("Input Audio", this);
- label->setAlignment(Qt::AlignRight);
- audioInput = new QComboBox(this);
- vaudio.index = 0;
- while (ioctl(fd, VIDIOC_ENUMAUDIO, &vaudio) >= 0) {
- audioInput->insertItem((char *)vaudio.name);
- vaudio.index++;
- }
- connect(audioInput, SIGNAL(activated(int)), SLOT(inputAudioChanged(int)));
- updateAudioInput();
- cnt++;
- }
-
- struct v4l2_audioout vaudioout;
- memset(&vaudioout, 0, sizeof(vaudioout));
- if (ioctl(fd, VIDIOC_ENUMAUDOUT, &vaudioout) >= 0) {
- QLabel *label = new QLabel("Output Audio", this);
- label->setAlignment(Qt::AlignRight);
- audioOutput = new QComboBox(this);
- while (ioctl(fd, VIDIOC_ENUMAUDOUT, &vaudioout) >= 0) {
- audioOutput->insertItem((char *)vaudioout.name);
- vaudioout.index++;
- }
- connect(audioOutput, SIGNAL(activated(int)), SLOT(outputAudioChanged(int)));
- updateAudioOutput();
- cnt++;
- }
-
- struct v4l2_standard vs;
- memset(&vs, 0, sizeof(vs));
- if (ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) {
- QLabel *label = new QLabel("TV Standard", this);
- label->setAlignment(Qt::AlignRight);
- tvStandard = new QComboBox(this);
- while (ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) {
- tvStandard->insertItem((char *)vs.name);
- vs.index++;
- }
- connect(tvStandard, SIGNAL(activated(int)), SLOT(standardChanged(int)));
- updateStandard();
- cnt++;
- }
-
- bool first = cnt & 1;
-
- if (first) {
- QString what;
- QLabel *label = new QLabel("Frequency", this);
- label->setAlignment(Qt::AlignRight);
- freq = new QSpinBox(tuner.rangelow, tuner.rangehigh, 1, this);
- QWhatsThis::add(freq, what.sprintf("Frequency\n"
- "Low: %d\n"
- "High: %d\n",
- tuner.rangelow, tuner.rangehigh));
- connect(freq, SIGNAL(valueChanged(int)), SLOT(freqChanged(int)));
- updateFreq();
- cnt++;
- }
-
- {
- QLabel *label = new QLabel("Frequency Tables", this);
- label->setAlignment(Qt::AlignRight);
- freqTable = new QComboBox(this);
- for (int i = 0; v4l2_channel_lists[i].name; i++) {
- freqTable->insertItem(v4l2_channel_lists[i].name);
- }
- connect(freqTable, SIGNAL(activated(int)), SLOT(freqTableChanged(int)));
-
- label = new QLabel("Channels", this);
- label->setAlignment(Qt::AlignRight);
- freqChannel = new QComboBox(this);
- connect(freqChannel, SIGNAL(activated(int)), SLOT(freqChannelChanged(int)));
- updateFreqChannel();
- }
-
- if (!first) {
- QString what;
- QLabel *label = new QLabel("Frequency", this);
- label->setAlignment(Qt::AlignRight);
- freq = new QSpinBox(tuner.rangelow, tuner.rangehigh, 1, this);
- QWhatsThis::add(freq, what.sprintf("Frequency\n"
- "Low: %d\n"
- "High: %d\n",
- tuner.rangelow, tuner.rangehigh));
- connect(freq, SIGNAL(valueChanged(int)), SLOT(freqChanged(int)));
- updateFreq();
- cnt++;
- }
-
- if (cnt & 1) {
- new QWidget(this);
- new QWidget(this);
- }
- QWidget *stretch = new QWidget(this);
- stretch->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
-}
-
-void GeneralTab::inputChanged(int input)
-{
- g_mw->doIoctl("Set Input", VIDIOC_S_INPUT, &input);
- struct v4l2_audio vaudio;
- memset(&vaudio, 0, sizeof(vaudio));
- if (audioInput && ioctl(fd, VIDIOC_G_AUDIO, &vaudio) >= 0) {
- audioInput->setCurrentItem(vaudio.index);
- updateAudioInput();
- }
- updateVideoInput();
-}
-
-void GeneralTab::outputChanged(int output)
-{
- g_mw->doIoctl("Set Output", VIDIOC_S_OUTPUT, &output);
- updateVideoOutput();
-}
-
-void GeneralTab::inputAudioChanged(int input)
-{
- struct v4l2_audio vaudio;
- memset(&vaudio, 0, sizeof(vaudio));
- vaudio.index = input;
- g_mw->doIoctl("Set Audio Input", VIDIOC_S_AUDIO, &vaudio);
- updateAudioInput();
-}
-
-void GeneralTab::outputAudioChanged(int output)
-{
- struct v4l2_audioout vaudioout;
- memset(&vaudioout, 0, sizeof(vaudioout));
- vaudioout.index = output;
- g_mw->doIoctl("Set Audio Output", VIDIOC_S_AUDOUT, &vaudioout);
- updateAudioOutput();
-}
-
-void GeneralTab::standardChanged(int std)
-{
- struct v4l2_standard vs;
- memset(&vs, 0, sizeof(vs));
- vs.index = std;
- ioctl(fd, VIDIOC_ENUMSTD, &vs);
- g_mw->doIoctl("Set TV Standard", VIDIOC_S_STD, &vs.id);
- updateStandard();
-}
-
-void GeneralTab::freqTableChanged(int)
-{
- updateFreqChannel();
- freqChannelChanged(0);
-}
-
-void GeneralTab::freqChannelChanged(int idx)
-{
- freq->setValue((int)(v4l2_channel_lists[freqTable->currentItem()].list[idx].freq / 62.5));
-}
-
-void GeneralTab::freqChanged(int val)
-{
- struct v4l2_frequency f;
-
- memset(&f, 0, sizeof(f));
- f.type = V4L2_TUNER_ANALOG_TV;
- f.frequency = val;
- g_mw->doIoctl("Set frequency", VIDIOC_S_FREQUENCY, &f);
-}
-
-void GeneralTab::updateVideoInput()
-{
- int input;
-
- ioctl(fd, VIDIOC_G_INPUT, &input);
- videoInput->setCurrentItem(input);
-}
-
-void GeneralTab::updateVideoOutput()
-{
- int output;
-
- ioctl(fd, VIDIOC_G_OUTPUT, &output);
- videoOutput->setCurrentItem(output);
-}
-
-void GeneralTab::updateAudioInput()
-{
- struct v4l2_audio audio;
- QString what;
-
- memset(&audio, 0, sizeof(audio));
- ioctl(fd, VIDIOC_G_AUDIO, &audio);
- audioInput->setCurrentItem(audio.index);
- if (audio.capability & V4L2_AUDCAP_STEREO)
- what = "stereo input";
- else
- what = "mono input";
- if (audio.capability & V4L2_AUDCAP_AVL)
- what += ", has AVL";
- if (audio.mode & V4L2_AUDMODE_AVL)
- what += ", AVL is on";
- QWhatsThis::add(audioInput, what);
-}
-
-void GeneralTab::updateAudioOutput()
-{
- struct v4l2_audioout audio;
-
- memset(&audio, 0, sizeof(audio));
- ioctl(fd, VIDIOC_G_AUDOUT, &audio);
- audioOutput->setCurrentItem(audio.index);
-}
-
-void GeneralTab::updateStandard()
-{
- v4l2_std_id std;
- struct v4l2_standard vs;
- QString what;
- ioctl(fd, VIDIOC_G_STD, &std);
- memset(&vs, 0, sizeof(vs));
- while (ioctl(fd, VIDIOC_ENUMSTD, &vs) != -1) {
- if (vs.id & std) {
- tvStandard->setCurrentItem(vs.index);
- what.sprintf("TV Standard (0x%llX)\n"
- "Frame period: %f (%d/%d)\n"
- "Frame lines: %d\n", (long long int)std,
- (double)vs.frameperiod.numerator / vs.frameperiod.denominator,
- vs.frameperiod.numerator, vs.frameperiod.denominator,
- vs.framelines);
- QWhatsThis::add(tvStandard, what);
- return;
- }
- vs.index++;
- }
-}
-
-void GeneralTab::updateFreq()
-{
- struct v4l2_frequency f;
-
- memset(&f, 0, sizeof(f));
- ioctl(fd, VIDIOC_G_FREQUENCY, &f);
- freq->setValue(f.frequency);
-}
-
-void GeneralTab::updateFreqChannel()
-{
- freqChannel->clear();
- int tbl = freqTable->currentItem();
- const struct v4l2_channel_list *list = v4l2_channel_lists[tbl].list;
- for (unsigned i = 0; i < v4l2_channel_lists[tbl].count; i++)
- freqChannel->insertItem(list[i].name);
-}
-
diff --git a/contrib/qv4l2-qt3/general-tab.h b/contrib/qv4l2-qt3/general-tab.h
deleted file mode 100644
index 8130e11e..00000000
--- a/contrib/qv4l2-qt3/general-tab.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* qv4l2: a control panel controlling v4l2 devices.
- *
- * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef GENERAL_TAB_H
-#define GENERAL_TAB_H
-
-#include <sys/time.h>
-#include <linux/videodev2.h>
-#include <qgrid.h>
-
-class QComboBox;
-class QSpinBox;
-
-class GeneralTab: public QGrid
-{
- Q_OBJECT
-
-public:
- GeneralTab(const char *device, int fd, int n, QWidget *parent = 0);
- virtual ~GeneralTab() {}
-
-private slots:
- void inputChanged(int);
- void outputChanged(int);
- void inputAudioChanged(int);
- void outputAudioChanged(int);
- void standardChanged(int);
- void freqTableChanged(int);
- void freqChannelChanged(int);
- void freqChanged(int);
-
-private:
- void updateVideoInput();
- void updateVideoOutput();
- void updateAudioInput();
- void updateAudioOutput();
- void updateStandard();
- void updateFreq();
- void updateFreqChannel();
-
- int fd;
- struct v4l2_tuner tuner;
- struct v4l2_capability querycap;
-
- // General tab
- QComboBox *videoInput;
- QComboBox *videoOutput;
- QComboBox *audioInput;
- QComboBox *audioOutput;
- QComboBox *tvStandard;
- QSpinBox *freq;
- QComboBox *freqTable;
- QComboBox *freqChannel;
-};
-
-#endif
diff --git a/contrib/qv4l2-qt3/qv4l2-qt3.pro b/contrib/qv4l2-qt3/qv4l2-qt3.pro
deleted file mode 100644
index bd639e1b..00000000
--- a/contrib/qv4l2-qt3/qv4l2-qt3.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-######################################################################
-# Automatically generated by qmake (1.07a) Sat Jun 17 12:35:16 2006
-######################################################################
-
-TEMPLATE = app
-INCLUDEPATH += . ../../utils/libv4l2util ../../include
-CONFIG += debug thread
-
-# Input
-HEADERS += qv4l2.h general-tab.h
-SOURCES += qv4l2.cpp general-tab.cpp ctrl-tab.cpp
-LIBS += -lv4l2util -L../../utils/libv4l2util
diff --git a/contrib/qv4l2-qt3/qv4l2.cpp b/contrib/qv4l2-qt3/qv4l2.cpp
deleted file mode 100644
index 764fbd17..00000000
--- a/contrib/qv4l2-qt3/qv4l2.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-
-#include "qv4l2.h"
-#include "general-tab.h"
-#include "libv4l2util.h"
-
-#include <qimage.h>
-#include <qpixmap.h>
-#include <qtoolbar.h>
-#include <qtoolbutton.h>
-#include <qpopupmenu.h>
-#include <qmenubar.h>
-#include <qfile.h>
-#include <qfiledialog.h>
-#include <qstatusbar.h>
-#include <qapplication.h>
-#include <qmessagebox.h>
-#include <qlineedit.h>
-#include <qvalidator.h>
-#include <qlayout.h>
-#include <qvbox.h>
-#include <qhbox.h>
-#include <qlabel.h>
-#include <qslider.h>
-#include <qspinbox.h>
-#include <qcombobox.h>
-#include <qcheckbox.h>
-#include <qpushbutton.h>
-#include <qtooltip.h>
-#include <qwhatsthis.h>
-
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <dirent.h>
-
-#include "fileopen.xpm"
-
-ApplicationWindow::ApplicationWindow()
- : QMainWindow( 0, "V4L2 main window", WDestructiveClose | WGroupLeader )
-{
- QPixmap openIcon, saveIcon;
-
- fd = -1;
-
- videoDevice = NULL;
- sigMapper = NULL;
- QToolBar * fileTools = new QToolBar( this, "file operations" );
- fileTools->setLabel( "File Operations" );
-
- openIcon = QPixmap( fileopen );
- QToolButton * fileOpen
- = new QToolButton( openIcon, "Open File", QString::null,
- this, SLOT(choose()), fileTools, "open file" );
-
- (void)QWhatsThis::whatsThisButton( fileTools );
-
- const char * fileOpenText = "<p><img source=\"fileopen\"> "
- "Click this button to open a <em>new v4l device</em>.<br>"
- "You can also select the <b>Open</b> command "
- "from the <b>File</b> menu.</p>";
-
- QWhatsThis::add( fileOpen, fileOpenText );
-
- QMimeSourceFactory::defaultFactory()->setPixmap( "fileopen", openIcon );
-
- QPopupMenu * file = new QPopupMenu( this );
- menuBar()->insertItem( "&File", file );
-
-
- int id;
- id = file->insertItem( openIcon, "&Open...",
- this, SLOT(choose()), CTRL+Key_O );
- file->setWhatsThis( id, fileOpenText );
-
- file->insertSeparator();
-
- file->insertItem( "&Close", this, SLOT(close()), CTRL+Key_W );
-
- file->insertItem( "&Quit", qApp, SLOT( closeAllWindows() ), CTRL+Key_Q );
-
- menuBar()->insertSeparator();
-
- QPopupMenu * help = new QPopupMenu( this );
- menuBar()->insertItem( "&Help", help );
-
- help->insertItem( "&About", this, SLOT(about()), Key_F1 );
- help->insertItem( "What's &This", this, SLOT(whatsThis()), SHIFT+Key_F1 );
-
- statusBar()->message( "Ready", 2000 );
-
- tabs = new QTabWidget(this);
- tabs->setMargin(3);
-
- //resize( 450, 600 );
-}
-
-
-ApplicationWindow::~ApplicationWindow()
-{
- if (fd >= 0) ::close(fd);
-}
-
-
-void ApplicationWindow::setDevice(const QString &device)
-{
- if (fd >= 0) ::close(fd);
- while (QWidget *page = tabs->page(0)) {
- tabs->removePage(page);
- delete page;
- }
- delete tabs;
- delete sigMapper;
- tabs = new QTabWidget(this);
- tabs->setMargin(3);
- sigMapper = new QSignalMapper(this);
- connect(sigMapper, SIGNAL(mapped(int)), this, SLOT(ctrlAction(int)));
- ctrlMap.clear();
- widgetMap.clear();
- classMap.clear();
-
- fd = ::open(device, O_RDONLY);
- if (fd >= 0) {
- tabs->addTab(new GeneralTab(device, fd, 4, tabs), "General");
- addTabs();
- }
- if (QWidget *current = tabs->currentPage()) {
- current->show();
- }
- tabs->show();
- tabs->setFocus();
- setCentralWidget(tabs);
-}
-
-void ApplicationWindow::selectdev(int index)
-{
- setDevice(videoDevice->text(index));
-}
-
-void ApplicationWindow::add_dirVideoDevice(const char *dirname)
-{
- DIR *dir;
- struct dirent *entry;
- const char *vid = "video";
- const char *rad = "radio";
- const char *vbi = "vbi";
- char name[512], *p;
-
- dir = opendir(dirname);
- if (!dir)
- return;
-
- strcpy(name, dirname);
- strcat(name, "/");
- p = name + strlen(name);
-
- entry = readdir(dir);
- while (entry) {
- if (!strncmp(entry->d_name, vid, strlen(vid)) ||
- !strncmp(entry->d_name, rad, strlen(rad)) ||
- !strncmp(entry->d_name, vbi, strlen(vbi))) {
- strcpy(p, entry->d_name);
-
- videoDevice->insertItem(name);
- }
- entry = readdir(dir);
- }
- closedir(dir);
-}
-
-void ApplicationWindow::choose()
-{
- if (videoDevice)
- delete videoDevice;
-
- videoDevice = new QPopupMenu(this);
-
- add_dirVideoDevice("/dev");
- add_dirVideoDevice("/dev/v4l");
-
- connect(videoDevice, SIGNAL(activated(int)), this, SLOT(selectdev(int)));
-
- videoDevice->show();
- videoDevice->setFocus();
-}
-
-void ApplicationWindow::closeEvent( QCloseEvent* ce )
-{
- ce->accept();
-}
-
-bool ApplicationWindow::doIoctl(QString descr, unsigned cmd, void *arg)
-{
- statusBar()->clear();
- int err = ioctl(fd, cmd, arg);
-
- if (err == -1) {
- QString s = strerror(errno);
- statusBar()->message(descr + ": " + s, 10000);
- }
- return err != -1;
-}
-
-void ApplicationWindow::about()
-{
- QMessageBox::about( this, "V4L2 Control Panel",
- "This program allows easy experimenting with video4linux devices.");
-}
-
-ApplicationWindow *g_mw;
-
-int main(int argc, char **argv)
-{
- QApplication a(argc, argv);
- g_mw = new ApplicationWindow();
- g_mw->setCaption( "V4L2 Control Panel" );
- g_mw->setDevice("/dev/video0");
- g_mw->show();
- a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
- return a.exec();
-}
diff --git a/contrib/qv4l2-qt3/qv4l2.h b/contrib/qv4l2-qt3/qv4l2.h
deleted file mode 100644
index 5421a867..00000000
--- a/contrib/qv4l2-qt3/qv4l2.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* qv4l2: a control panel controlling v4l2 devices.
- *
- * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef QV4L2_H
-#define QV4L2_H
-
-#include <qmainwindow.h>
-#include <qtabwidget.h>
-#include <qsignalmapper.h>
-#include <qgrid.h>
-#include <map>
-#include <vector>
-
-#include <linux/videodev2.h>
-
-class QComboBox;
-class QSpinBox;
-
-typedef std::vector<unsigned> ClassIDVec;
-typedef std::map<unsigned, ClassIDVec> ClassMap;
-typedef std::map<unsigned, struct v4l2_queryctrl> CtrlMap;
-typedef std::map<unsigned, QWidget *> WidgetMap;
-
-enum {
- CTRL_UPDATE_ON_CHANGE = 0x10,
- CTRL_DEFAULTS,
- CTRL_REFRESH,
- CTRL_UPDATE
-};
-
-class ApplicationWindow: public QMainWindow
-{
- Q_OBJECT
-
-public:
- ApplicationWindow();
- ~ApplicationWindow();
-
- void setDevice(const QString &device);
- bool doIoctl(QString descr, unsigned cmd, void *arg);
-
-protected:
- void closeEvent( QCloseEvent* );
-
-private slots:
- void selectdev(int);
- void choose();
- void ctrlAction(int);
-
- void about();
-
-private:
- void add_dirVideoDevice(const char *dirname);
- void addTabs();
- void finishGrid(QWidget *vbox, QGrid *grid, unsigned ctrl_class, bool odd);
- void addCtrl(QGrid *grid, const struct v4l2_queryctrl &qctrl);
- void updateCtrl(unsigned id);
- void refresh(unsigned ctrl_class);
- void setDefaults(unsigned ctrl_class);
- int getVal(unsigned id);
- long long getVal64(unsigned id);
- void setVal(unsigned id, int v);
- void setVal64(unsigned id, long long v);
- QString getCtrlFlags(unsigned flags);
- void setWhat(QWidget *w, unsigned id, long long v);
- void updateVideoInput();
- void updateVideoOutput();
- void updateAudioInput();
- void updateAudioOutput();
- void updateStandard();
- void updateFreq();
- void updateFreqChannel();
-
- QString filename;
- QSignalMapper *sigMapper;
- QTabWidget *tabs;
- QPopupMenu *videoDevice;
- int fd;
- CtrlMap ctrlMap;
- WidgetMap widgetMap;
- ClassMap classMap;
-};
-
-extern ApplicationWindow *g_mw;
-
-#endif
diff --git a/contrib/saa7134/parse_saa7134.pl b/contrib/saa7134/parse_saa7134.pl
index 0eee4581..0eee4581 100644..100755
--- a/contrib/saa7134/parse_saa7134.pl
+++ b/contrib/saa7134/parse_saa7134.pl
diff --git a/contrib/sn9c201/parse_sn9c201.pl b/contrib/sn9c201/parse_sn9c201.pl
index b4322878..b4322878 100644..100755
--- a/contrib/sn9c201/parse_sn9c201.pl
+++ b/contrib/sn9c201/parse_sn9c201.pl
diff --git a/contrib/test/.gitignore b/contrib/test/.gitignore
index 8c3f8348..2e68b9eb 100644
--- a/contrib/test/.gitignore
+++ b/contrib/test/.gitignore
@@ -7,5 +7,3 @@ sliced-vbi-test
stress-buffer
v4l2gl
v4l2grab
-v4lgrab
-vbi-test
diff --git a/contrib/test/Makefile.am b/contrib/test/Makefile.am
index 80c76652..4ccb5ede 100644
--- a/contrib/test/Makefile.am
+++ b/contrib/test/Makefile.am
@@ -2,8 +2,6 @@ noinst_PROGRAMS = \
ioctl-test \
sliced-vbi-test \
sliced-vbi-detect \
- vbi-test \
- v4lgrab \
v4l2grab \
driver-test \
stress-buffer \
@@ -37,10 +35,6 @@ sliced_vbi_test_SOURCES = sliced-vbi-test.c
sliced_vbi_detect_SOURCES = sliced-vbi-detect.c
-vbi_test_SOURCES = vbi-test.c
-
-v4lgrab_SOURCES = v4lgrab.c
-
stress_buffer_SOURCES = stress-buffer.c
capture_example_SOURCES = capture-example.c
diff --git a/contrib/test/ioctl-test.h b/contrib/test/ioctl-test.h
index f2cecb73..a2b6b071 100644
--- a/contrib/test/ioctl-test.h
+++ b/contrib/test/ioctl-test.h
@@ -171,15 +171,20 @@ static const struct {
ioc(video, VIDIOC_RESERVED), /* void */
ioc(video, VIDIOC_STREAMOFF), /* int */
ioc(video, VIDIOC_STREAMON), /* int */
+ ioc(subdev, VIDIOC_SUBDEV_DV_TIMINGS_CAP), /* struct v4l2_dv_timings_cap */
+ ioc(subdev, VIDIOC_SUBDEV_ENUM_DV_TIMINGS), /* struct v4l2_enum_dv_timings */
ioc(subdev, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL), /* struct v4l2_subdev_frame_interval_enum */
ioc(subdev, VIDIOC_SUBDEV_ENUM_FRAME_SIZE), /* struct v4l2_subdev_frame_size_enum */
ioc(subdev, VIDIOC_SUBDEV_ENUM_MBUS_CODE), /* struct v4l2_subdev_mbus_code_enum */
ioc(subdev, VIDIOC_SUBDEV_G_CROP), /* struct v4l2_subdev_crop */
+ ioc(subdev, VIDIOC_SUBDEV_G_DV_TIMINGS), /* struct v4l2_dv_timings */
ioc(subdev, VIDIOC_SUBDEV_G_EDID), /* struct v4l2_edid */
ioc(subdev, VIDIOC_SUBDEV_G_FMT), /* struct v4l2_subdev_format */
ioc(subdev, VIDIOC_SUBDEV_G_FRAME_INTERVAL), /* struct v4l2_subdev_frame_interval */
ioc(subdev, VIDIOC_SUBDEV_G_SELECTION), /* struct v4l2_subdev_selection */
+ ioc(subdev, VIDIOC_SUBDEV_QUERY_DV_TIMINGS), /* struct v4l2_dv_timings */
ioc(subdev, VIDIOC_SUBDEV_S_CROP), /* struct v4l2_subdev_crop */
+ ioc(subdev, VIDIOC_SUBDEV_S_DV_TIMINGS), /* struct v4l2_dv_timings */
ioc(subdev, VIDIOC_SUBDEV_S_EDID), /* struct v4l2_edid */
ioc(subdev, VIDIOC_SUBDEV_S_FMT), /* struct v4l2_subdev_format */
ioc(subdev, VIDIOC_SUBDEV_S_FRAME_INTERVAL), /* struct v4l2_subdev_frame_interval */
diff --git a/contrib/test/ioctl_32.h b/contrib/test/ioctl_32.h
index b0907685..2a5c70eb 100644
--- a/contrib/test/ioctl_32.h
+++ b/contrib/test/ioctl_32.h
@@ -87,15 +87,20 @@
#define CMD32_VIDIOC_RESERVED 0x5601
#define CMD32_VIDIOC_STREAMOFF 0x40045613
#define CMD32_VIDIOC_STREAMON 0x40045612
+#define CMD32_VIDIOC_SUBDEV_DV_TIMINGS_CAP 0xc0905664
+#define CMD32_VIDIOC_SUBDEV_ENUM_DV_TIMINGS 0xc0945662
#define CMD32_VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL 0xc040564b
#define CMD32_VIDIOC_SUBDEV_ENUM_FRAME_SIZE 0xc040564a
#define CMD32_VIDIOC_SUBDEV_ENUM_MBUS_CODE 0xc0305602
#define CMD32_VIDIOC_SUBDEV_G_CROP 0xc038563b
+#define CMD32_VIDIOC_SUBDEV_G_DV_TIMINGS 0xc0845658
#define CMD32_VIDIOC_SUBDEV_G_EDID 0xc0245628
#define CMD32_VIDIOC_SUBDEV_G_FMT 0xc0585604
#define CMD32_VIDIOC_SUBDEV_G_FRAME_INTERVAL 0xc0305615
#define CMD32_VIDIOC_SUBDEV_G_SELECTION 0xc040563d
+#define CMD32_VIDIOC_SUBDEV_QUERY_DV_TIMINGS 0x80845663
#define CMD32_VIDIOC_SUBDEV_S_CROP 0xc038563c
+#define CMD32_VIDIOC_SUBDEV_S_DV_TIMINGS 0xc0845657
#define CMD32_VIDIOC_SUBDEV_S_EDID 0xc0245629
#define CMD32_VIDIOC_SUBDEV_S_FMT 0xc0585605
#define CMD32_VIDIOC_SUBDEV_S_FRAME_INTERVAL 0xc0305616
diff --git a/contrib/test/ioctl_64.h b/contrib/test/ioctl_64.h
index 975dbdc4..6487ea36 100644
--- a/contrib/test/ioctl_64.h
+++ b/contrib/test/ioctl_64.h
@@ -87,15 +87,20 @@
#define CMD64_VIDIOC_RESERVED 0x5601
#define CMD64_VIDIOC_STREAMOFF 0x40045613
#define CMD64_VIDIOC_STREAMON 0x40045612
+#define CMD64_VIDIOC_SUBDEV_DV_TIMINGS_CAP 0xc0905664
+#define CMD64_VIDIOC_SUBDEV_ENUM_DV_TIMINGS 0xc0945662
#define CMD64_VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL 0xc040564b
#define CMD64_VIDIOC_SUBDEV_ENUM_FRAME_SIZE 0xc040564a
#define CMD64_VIDIOC_SUBDEV_ENUM_MBUS_CODE 0xc0305602
#define CMD64_VIDIOC_SUBDEV_G_CROP 0xc038563b
+#define CMD64_VIDIOC_SUBDEV_G_DV_TIMINGS 0xc0845658
#define CMD64_VIDIOC_SUBDEV_G_EDID 0xc0285628
#define CMD64_VIDIOC_SUBDEV_G_FMT 0xc0585604
#define CMD64_VIDIOC_SUBDEV_G_FRAME_INTERVAL 0xc0305615
#define CMD64_VIDIOC_SUBDEV_G_SELECTION 0xc040563d
+#define CMD64_VIDIOC_SUBDEV_QUERY_DV_TIMINGS 0x80845663
#define CMD64_VIDIOC_SUBDEV_S_CROP 0xc038563c
+#define CMD64_VIDIOC_SUBDEV_S_DV_TIMINGS 0xc0845657
#define CMD64_VIDIOC_SUBDEV_S_EDID 0xc0285629
#define CMD64_VIDIOC_SUBDEV_S_FMT 0xc0585605
#define CMD64_VIDIOC_SUBDEV_S_FRAME_INTERVAL 0xc0305616
diff --git a/contrib/test/v4lgrab.c b/contrib/test/v4lgrab.c
deleted file mode 100644
index 43f22163..00000000
--- a/contrib/test/v4lgrab.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* Simple Video4Linux image grabber. */
-/*
- * Video4Linux Driver Test/Example Framegrabbing Program
- *
- * Compile with:
- * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
- * Use as:
- * v4lgrab >image.ppm
- *
- * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
- * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
- * with minor modifications (Dave Forrest, drf5n@virginia.edu).
- *
- * NOTE: This utility uses the old, discontinued V4L version 1 API.
- * It is kept here solely for the purposes of testing the libv4l1
- * compatibility layer, as the V4L1 API were removed on kernel 2.6.39.
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <stdlib.h>
-
-#include <linux/types.h>
-#include "../../lib/include/libv4l1-videodev.h"
-
-#define FILE "/dev/video0"
-
-/* Stole this from tvset.c */
-
-#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \
-{ \
- switch (format) \
- { \
- case VIDEO_PALETTE_GREY: \
- switch (depth) \
- { \
- case 4: \
- case 6: \
- case 8: \
- (r) = (g) = (b) = (*buf++ << 8);\
- break; \
- \
- case 16: \
- (r) = (g) = (b) = \
- *((unsigned short *) buf); \
- buf += 2; \
- break; \
- } \
- break; \
- \
- \
- case VIDEO_PALETTE_RGB565: \
- { \
- unsigned short tmp = *(unsigned short *)buf; \
- (r) = tmp&0xF800; \
- (g) = (tmp<<5)&0xFC00; \
- (b) = (tmp<<11)&0xF800; \
- buf += 2; \
- } \
- break; \
- \
- case VIDEO_PALETTE_RGB555: \
- (r) = (buf[0]&0xF8)<<8; \
- (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \
- (b) = ((buf[1] << 2 ) & 0xF8)<<8; \
- buf += 2; \
- break; \
- \
- case VIDEO_PALETTE_RGB24: \
- (r) = buf[0] << 8; (g) = buf[1] << 8; \
- (b) = buf[2] << 8; \
- buf += 3; \
- break; \
- \
- default: \
- fprintf(stderr, \
- "Format %d not yet supported\n", \
- format); \
- } \
-}
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int get_brightness_adj(unsigned char *image, long size, int *brightness)
-{
- long i, tot = 0;
- for (i=0;i<size*3;i++)
- tot += image[i];
- *brightness = (128 - tot/(size*3))/3;
- return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
-}
-#endif
-
-int main(int argc, char **argv)
-{
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
- int fd = open(FILE, O_RDONLY), f;
- struct video_capability cap;
- struct video_window win;
- struct video_picture vpic;
-
- unsigned char *buffer, *src;
- int bpp = 24, r, g, b;
- unsigned int i, src_depth;
-
- if (fd < 0) {
- perror(FILE);
- exit(1);
- }
-
- if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
- perror("VIDIOGCAP");
- fprintf(stderr, "(" FILE " not a video4linux device?)\n");
- close(fd);
- exit(1);
- }
-
- if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
- perror("VIDIOCGWIN");
- close(fd);
- exit(1);
- }
-
- if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
- perror("VIDIOCGPICT");
- close(fd);
- exit(1);
- }
-
- if (cap.type & VID_TYPE_MONOCHROME) {
- vpic.depth=8;
- vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */
- if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
- vpic.depth=6;
- if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
- vpic.depth=4;
- if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
- fprintf(stderr, "Unable to find a supported capture format.\n");
- close(fd);
- exit(1);
- }
- }
- }
- }
- else {
- vpic.depth=24;
- vpic.palette=VIDEO_PALETTE_RGB24;
-
- if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
- vpic.palette=VIDEO_PALETTE_RGB565;
- vpic.depth=16;
-
- if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
- vpic.palette=VIDEO_PALETTE_RGB555;
- vpic.depth=15;
-
- if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
- fprintf(stderr, "Unable to find a supported capture format.\n");
- return -1;
- }
- }
- }
- }
-
- buffer = malloc(win.width * win.height * bpp);
- if (!buffer) {
- fprintf(stderr, "Out of memory.\n");
- exit(1);
- }
-
- do {
- int newbright;
- read(fd, buffer, win.width * win.height * bpp);
- f = get_brightness_adj(buffer, win.width * win.height, &newbright);
- if (f) {
- vpic.brightness += (newbright << 8);
- if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
- perror("VIDIOSPICT");
- break;
- }
- }
- } while (f);
-
- fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
-
- src = buffer;
-
- for (i = 0; i < win.width * win.height; i++) {
- READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
- fputc(r>>8, stdout);
- fputc(g>>8, stdout);
- fputc(b>>8, stdout);
- }
-
- close(fd);
-#else
- fprintf(stderr, "V4L1 API is not configured!\n");
-#endif
- return 0;
-}
diff --git a/contrib/test/vbi-test.c b/contrib/test/vbi-test.c
deleted file mode 100644
index 0fa2a6d0..00000000
--- a/contrib/test/vbi-test.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- v4l-ioctl-test - This small utility checks VBI format
-
- Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <linux/videodev2.h>
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-#include "../../lib/include/libv4l1-videodev.h"
-#endif
-
-/* All possible parameters used on v4l ioctls */
-union v4l_parms {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
- /* V4L1 structs */
- struct vbi_format v1;
-#endif
-
- /* V4L2 structs */
- struct v4l2_format v2;
-};
-
-/* All defined ioctls */
-int ioctls[] = {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
- /* V4L ioctls */
-
- VIDIOCGVBIFMT,/* struct vbi_format */
-#endif
-
- /* V4L2 ioctls */
-
- VIDIOC_G_FMT,/* struct v4l2_format */
-};
-#define S_IOCTLS sizeof(ioctls)/sizeof(ioctls[0])
-
-/********************************************************************/
-int main (void)
-{
- int fd=0, ret=0;
- char *device="/dev/video0";
- union v4l_parms p;
-
- if ((fd = open(device, O_RDONLY)) < 0) {
- perror("Couldn't open video0");
- return(-1);
- }
-
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
- /* V4L1 call */
- memset(&p,0,sizeof(p));
- ret=ioctl(fd,VIDIOCGVBIFMT, (void *) &p);
-
- printf ("V4L1 call: ret=%i: sampling_rate=%d, samples_per_line=%d, "
- "sample_format=%d, start=%d/%d, count=%d/%d, flags=%d\n", ret,
- p.v1.sampling_rate,p.v1.samples_per_line, p.v1.sample_format,
- p.v1.start[0],p.v1.start[1],p.v1.count[0],p.v1.count[1],p.v1.flags);
-#endif
-
-
- /* V4L2 call */
- memset(&p,0,sizeof(p));
- p.v2.type=V4L2_BUF_TYPE_VBI_CAPTURE;
- ret=ioctl(fd,VIDIOC_G_FMT, (void *) &p);
-
- printf ("V4L2 call: ret=%i: sampling_rate=%d, samples_per_line=%d, "
- "sample_format=%d, offset=%d, start=%d/%d, count=%d/%d\n", ret,
- p.v2.fmt.vbi.sampling_rate,p.v2.fmt.vbi.samples_per_line,
- p.v2.fmt.vbi.sample_format,p.v2.fmt.vbi.offset,
- p.v2.fmt.vbi.start[0],p.v2.fmt.vbi.start[1],
- p.v2.fmt.vbi.count[0],p.v2.fmt.vbi.count[1]);
-
- close (fd);
-
- return (0);
-}
diff --git a/contrib/tm6000/parse_tm6000.pl b/contrib/tm6000/parse_tm6000.pl
index 1b5c5e69..1b5c5e69 100644..100755
--- a/contrib/tm6000/parse_tm6000.pl
+++ b/contrib/tm6000/parse_tm6000.pl
diff --git a/contrib/usb_parse/parse_usb.pl b/contrib/usb_parse/parse_usb.pl
index 5af64084..5af64084 100644..100755
--- a/contrib/usb_parse/parse_usb.pl
+++ b/contrib/usb_parse/parse_usb.pl
diff --git a/contrib/usbmon2usbsnoop.pl b/contrib/usbmon2usbsnoop.pl
index c6566873..c6566873 100644..100755
--- a/contrib/usbmon2usbsnoop.pl
+++ b/contrib/usbmon2usbsnoop.pl
diff --git a/include/linux/v4l2-common.h b/include/linux/v4l2-common.h
index 270db891..2f6f8caf 100644
--- a/include/linux/v4l2-common.h
+++ b/include/linux/v4l2-common.h
@@ -29,6 +29,8 @@
#ifndef __V4L2_COMMON__
#define __V4L2_COMMON__
+#include <linux/types.h>
+
/*
*
* Selection interface definitions
@@ -73,7 +75,7 @@ struct v4l2_edid {
__u32 start_block;
__u32 blocks;
__u32 reserved[5];
- __u8 __user *edid;
+ __u8 *edid;
};
#endif /* __V4L2_COMMON__ */
diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
new file mode 100644
index 00000000..1445e858
--- /dev/null
+++ b/include/linux/v4l2-mediabus.h
@@ -0,0 +1,147 @@
+/*
+ * Media Bus API header
+ *
+ * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_V4L2_MEDIABUS_H
+#define __LINUX_V4L2_MEDIABUS_H
+
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+/*
+ * These pixel codes uniquely identify data formats on the media bus. Mostly
+ * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is
+ * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the
+ * data format is fixed. Additionally, "2X8" means that one pixel is transferred
+ * in two 8-bit samples, "BE" or "LE" specify in which order those samples are
+ * transferred over the bus: "LE" means that the least significant bits are
+ * transferred first, "BE" means that the most significant bits are transferred
+ * first, and "PADHI" and "PADLO" define which bits - low or high, in the
+ * incomplete high byte, are filled with padding bits.
+ *
+ * The pixel codes are grouped by type, bus_width, bits per component, samples
+ * per pixel and order of subsamples. Numerical values are sorted using generic
+ * numerical sort order (8 thus comes before 10).
+ *
+ * As their value can't change when a new pixel code is inserted in the
+ * enumeration, the pixel codes are explicitly given a numerical value. The next
+ * free values for each category are listed below, update them when inserting
+ * new pixel codes.
+ */
+enum v4l2_mbus_pixelcode {
+ V4L2_MBUS_FMT_FIXED = 0x0001,
+
+ /* RGB - next is 0x100e */
+ V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE = 0x1001,
+ V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE = 0x1002,
+ V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE = 0x1003,
+ V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE = 0x1004,
+ V4L2_MBUS_FMT_BGR565_2X8_BE = 0x1005,
+ V4L2_MBUS_FMT_BGR565_2X8_LE = 0x1006,
+ V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
+ V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
+ V4L2_MBUS_FMT_RGB666_1X18 = 0x1009,
+ V4L2_MBUS_FMT_RGB888_1X24 = 0x100a,
+ V4L2_MBUS_FMT_RGB888_2X12_BE = 0x100b,
+ V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c,
+ V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d,
+
+ /* YUV (including grey) - next is 0x2024 */
+ V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
+ V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
+ V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
+ V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
+ V4L2_MBUS_FMT_YUYV8_1_5X8 = 0x2004,
+ V4L2_MBUS_FMT_YVYU8_1_5X8 = 0x2005,
+ V4L2_MBUS_FMT_UYVY8_2X8 = 0x2006,
+ V4L2_MBUS_FMT_VYUY8_2X8 = 0x2007,
+ V4L2_MBUS_FMT_YUYV8_2X8 = 0x2008,
+ V4L2_MBUS_FMT_YVYU8_2X8 = 0x2009,
+ V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
+ V4L2_MBUS_FMT_UYVY10_2X10 = 0x2018,
+ V4L2_MBUS_FMT_VYUY10_2X10 = 0x2019,
+ V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
+ V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
+ V4L2_MBUS_FMT_Y12_1X12 = 0x2013,
+ V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f,
+ V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
+ V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
+ V4L2_MBUS_FMT_YVYU8_1X16 = 0x2012,
+ V4L2_MBUS_FMT_YDYUYDYV8_1X16 = 0x2014,
+ V4L2_MBUS_FMT_UYVY10_1X20 = 0x201a,
+ V4L2_MBUS_FMT_VYUY10_1X20 = 0x201b,
+ V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
+ V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
+ V4L2_MBUS_FMT_YUV10_1X30 = 0x2016,
+ V4L2_MBUS_FMT_AYUV8_1X32 = 0x2017,
+ V4L2_MBUS_FMT_UYVY12_2X12 = 0x201c,
+ V4L2_MBUS_FMT_VYUY12_2X12 = 0x201d,
+ V4L2_MBUS_FMT_YUYV12_2X12 = 0x201e,
+ V4L2_MBUS_FMT_YVYU12_2X12 = 0x201f,
+ V4L2_MBUS_FMT_UYVY12_1X24 = 0x2020,
+ V4L2_MBUS_FMT_VYUY12_1X24 = 0x2021,
+ V4L2_MBUS_FMT_YUYV12_1X24 = 0x2022,
+ V4L2_MBUS_FMT_YVYU12_1X24 = 0x2023,
+
+ /* Bayer - next is 0x3019 */
+ V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
+ V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013,
+ V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
+ V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014,
+ V4L2_MBUS_FMT_SBGGR10_ALAW8_1X8 = 0x3015,
+ V4L2_MBUS_FMT_SGBRG10_ALAW8_1X8 = 0x3016,
+ V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8 = 0x3017,
+ V4L2_MBUS_FMT_SRGGB10_ALAW8_1X8 = 0x3018,
+ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
+ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
+ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
+ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 = 0x300d,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE = 0x3003,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE = 0x3004,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE = 0x3005,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE = 0x3006,
+ V4L2_MBUS_FMT_SBGGR10_1X10 = 0x3007,
+ V4L2_MBUS_FMT_SGBRG10_1X10 = 0x300e,
+ V4L2_MBUS_FMT_SGRBG10_1X10 = 0x300a,
+ V4L2_MBUS_FMT_SRGGB10_1X10 = 0x300f,
+ V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008,
+ V4L2_MBUS_FMT_SGBRG12_1X12 = 0x3010,
+ V4L2_MBUS_FMT_SGRBG12_1X12 = 0x3011,
+ V4L2_MBUS_FMT_SRGGB12_1X12 = 0x3012,
+
+ /* JPEG compressed formats - next is 0x4002 */
+ V4L2_MBUS_FMT_JPEG_1X8 = 0x4001,
+
+ /* Vendor specific formats - next is 0x5002 */
+
+ /* S5C73M3 sensor specific interleaved UYVY and JPEG */
+ V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8 = 0x5001,
+
+ /* HSV - next is 0x6002 */
+ V4L2_MBUS_FMT_AHSV8888_1X32 = 0x6001,
+};
+
+/**
+ * struct v4l2_mbus_framefmt - frame format on the media bus
+ * @width: frame width
+ * @height: frame height
+ * @code: data format code (from enum v4l2_mbus_pixelcode)
+ * @field: used interlacing type (from enum v4l2_field)
+ * @colorspace: colorspace of the data (from enum v4l2_colorspace)
+ */
+struct v4l2_mbus_framefmt {
+ __u32 width;
+ __u32 height;
+ __u32 code;
+ __u32 field;
+ __u32 colorspace;
+ __u32 reserved[7];
+};
+
+#endif
diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
index 87e05159..a619cdd3 100644
--- a/include/linux/v4l2-subdev.h
+++ b/include/linux/v4l2-subdev.h
@@ -151,26 +151,24 @@ struct v4l2_subdev_selection {
/* Backwards compatibility define --- to be removed */
#define v4l2_subdev_edid v4l2_edid
-#define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format)
-#define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format)
-#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \
- _IOWR('V', 21, struct v4l2_subdev_frame_interval)
-#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \
- _IOWR('V', 22, struct v4l2_subdev_frame_interval)
-#define VIDIOC_SUBDEV_ENUM_MBUS_CODE \
- _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum)
-#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \
- _IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
-#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
- _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum)
-#define VIDIOC_SUBDEV_G_CROP _IOWR('V', 59, struct v4l2_subdev_crop)
-#define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop)
-#define VIDIOC_SUBDEV_G_SELECTION \
- _IOWR('V', 61, struct v4l2_subdev_selection)
-#define VIDIOC_SUBDEV_S_SELECTION \
- _IOWR('V', 62, struct v4l2_subdev_selection)
-/* These two G/S_EDID ioctls are identical to the ioctls in videodev2.h */
-#define VIDIOC_SUBDEV_G_EDID _IOWR('V', 40, struct v4l2_edid)
-#define VIDIOC_SUBDEV_S_EDID _IOWR('V', 41, struct v4l2_edid)
+#define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format)
+#define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format)
+#define VIDIOC_SUBDEV_G_FRAME_INTERVAL _IOWR('V', 21, struct v4l2_subdev_frame_interval)
+#define VIDIOC_SUBDEV_S_FRAME_INTERVAL _IOWR('V', 22, struct v4l2_subdev_frame_interval)
+#define VIDIOC_SUBDEV_ENUM_MBUS_CODE _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum)
+#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE _IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
+#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum)
+#define VIDIOC_SUBDEV_G_CROP _IOWR('V', 59, struct v4l2_subdev_crop)
+#define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop)
+#define VIDIOC_SUBDEV_G_SELECTION _IOWR('V', 61, struct v4l2_subdev_selection)
+#define VIDIOC_SUBDEV_S_SELECTION _IOWR('V', 62, struct v4l2_subdev_selection)
+/* The following ioctls are identical to the ioctls in videodev2.h */
+#define VIDIOC_SUBDEV_G_EDID _IOWR('V', 40, struct v4l2_edid)
+#define VIDIOC_SUBDEV_S_EDID _IOWR('V', 41, struct v4l2_edid)
+#define VIDIOC_SUBDEV_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings)
+#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap)
#endif
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index e35ad6ca..168ff507 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -649,7 +649,6 @@ struct v4l2_plane {
* @length: size in bytes of the buffer (NOT its payload) for single-plane
* buffers (when type != *_MPLANE); number of elements in the
* planes array for multi-plane buffers
- * @input: input number from which the video data has has been captured
*
* Contains data exchanged by application and driver using one of the Streaming
* I/O methods.
@@ -1080,14 +1079,14 @@ struct v4l2_bt_timings {
/* A few useful defines to calculate the total blanking and frame sizes */
#define V4L2_DV_BT_BLANKING_WIDTH(bt) \
- (bt->hfrontporch + bt->hsync + bt->hbackporch)
+ ((bt)->hfrontporch + (bt)->hsync + (bt)->hbackporch)
#define V4L2_DV_BT_FRAME_WIDTH(bt) \
- (bt->width + V4L2_DV_BT_BLANKING_WIDTH(bt))
+ ((bt)->width + V4L2_DV_BT_BLANKING_WIDTH(bt))
#define V4L2_DV_BT_BLANKING_HEIGHT(bt) \
- (bt->vfrontporch + bt->vsync + bt->vbackporch + \
- bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch)
+ ((bt)->vfrontporch + (bt)->vsync + (bt)->vbackporch + \
+ (bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch)
#define V4L2_DV_BT_FRAME_HEIGHT(bt) \
- (bt->height + V4L2_DV_BT_BLANKING_HEIGHT(bt))
+ ((bt)->height + V4L2_DV_BT_BLANKING_HEIGHT(bt))
/** struct v4l2_dv_timings - DV timings
* @type: the type of the timings
@@ -1107,12 +1106,15 @@ struct v4l2_dv_timings {
/** struct v4l2_enum_dv_timings - DV timings enumeration
* @index: enumeration index
+ * @pad: the pad number for which to enumerate timings (used with
+ * v4l-subdev nodes only)
* @reserved: must be zeroed
* @timings: the timings for the given index
*/
struct v4l2_enum_dv_timings {
__u32 index;
- __u32 reserved[3];
+ __u32 pad;
+ __u32 reserved[2];
struct v4l2_dv_timings timings;
};
@@ -1150,11 +1152,14 @@ struct v4l2_bt_timings_cap {
/** struct v4l2_dv_timings_cap - DV timings capabilities
* @type: the type of the timings (same as in struct v4l2_dv_timings)
+ * @pad: the pad number for which to query capabilities (used with
+ * v4l-subdev nodes only)
* @bt: the BT656/1120 timings capabilities
*/
struct v4l2_dv_timings_cap {
__u32 type;
- __u32 reserved[3];
+ __u32 pad;
+ __u32 reserved[2];
union {
struct v4l2_bt_timings_cap bt;
__u32 raw_data[32];
@@ -1765,6 +1770,7 @@ struct v4l2_streamparm {
#define V4L2_EVENT_EOS 2
#define V4L2_EVENT_CTRL 3
#define V4L2_EVENT_FRAME_SYNC 4
+#define V4L2_EVENT_SOURCE_CHANGE 5
#define V4L2_EVENT_PRIVATE_START 0x08000000
/* Payload for V4L2_EVENT_VSYNC */
@@ -1796,12 +1802,19 @@ struct v4l2_event_frame_sync {
__u32 frame_sequence;
};
+#define V4L2_EVENT_SRC_CH_RESOLUTION (1 << 0)
+
+struct v4l2_event_src_change {
+ __u32 changes;
+};
+
struct v4l2_event {
__u32 type;
union {
struct v4l2_event_vsync vsync;
struct v4l2_event_ctrl ctrl;
struct v4l2_event_frame_sync frame_sync;
+ struct v4l2_event_src_change src_change;
__u8 data[64];
} u;
__u32 pending;
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 40fba504..3a0e19c8 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,6 +2,10 @@ SUBDIRS = \
libv4lconvert \
libv4l2 \
libv4l1 \
- libdvbv5 \
libv4l2rds \
libv4l-mplane
+
+if LINUX_OS
+SUBDIRS += \
+ libdvbv5
+endif \ No newline at end of file
diff --git a/lib/include/libdvbv5/atsc_eit.h b/lib/include/libdvbv5/atsc_eit.h
index 0c0d830e..5116a3d0 100644
--- a/lib/include/libdvbv5/atsc_eit.h
+++ b/lib/include/libdvbv5/atsc_eit.h
@@ -26,7 +26,6 @@
#include <time.h>
#include <libdvbv5/atsc_header.h>
-#include <libdvbv5/descriptors.h>
#define ATSC_TABLE_EIT 0xCB
@@ -64,7 +63,7 @@ union atsc_table_eit_desc_length {
} __attribute__((packed));
struct atsc_table_eit {
- struct atsc_table_header header;
+ ATSC_HEADER();
uint8_t events;
struct atsc_table_eit_event *event;
} __attribute__((packed));
@@ -78,7 +77,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void atsc_table_eit_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t atsc_table_eit_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct atsc_table_eit **table);
void atsc_table_eit_free(struct atsc_table_eit *eit);
void atsc_table_eit_print(struct dvb_v5_fe_parms *parms, struct atsc_table_eit *eit);
void atsc_time(const uint32_t start_time, struct tm *tm);
diff --git a/lib/include/libdvbv5/atsc_header.h b/lib/include/libdvbv5/atsc_header.h
index 9685b37e..96bfc119 100644
--- a/lib/include/libdvbv5/atsc_header.h
+++ b/lib/include/libdvbv5/atsc_header.h
@@ -24,40 +24,17 @@
#include <stdint.h>
#include <unistd.h> /* ssize_t */
+#include <libdvbv5/header.h>
+
#define ATSC_BASE_PID 0x1FFB
-struct atsc_table_header {
- uint8_t table_id;
- union {
- uint16_t bitfield;
- struct {
- uint16_t section_length:12;
- uint16_t one:2;
- uint16_t priv:1;
- uint16_t syntax:1;
- } __attribute__((packed));
- } __attribute__((packed));
- uint16_t id;
- uint8_t current_next:1;
- uint8_t version:5;
- uint8_t one2:2;
-
- uint8_t section_id;
- uint8_t last_section;
- uint8_t protocol_version;
-} __attribute__((packed));
-
-struct dvb_v5_fe_parms;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#define ATSC_HEADER() \
+ struct dvb_table_header header; \
+ uint8_t protocol_version; \
-int atsc_table_header_init (struct atsc_table_header *t);
-void atsc_table_header_print(struct dvb_v5_fe_parms *parms, const struct atsc_table_header *t);
+#define ATSC_TABLE_HEADER_PRINT(_parms, _table) \
+ dvb_table_header_print(_parms, &_table->header); \
+ dvb_loginfo("| protocol_version %d", _table->protocol_version); \
-#ifdef __cplusplus
-}
-#endif
#endif
diff --git a/lib/include/libdvbv5/cat.h b/lib/include/libdvbv5/cat.h
index 4c442a81..134e3e5c 100644
--- a/lib/include/libdvbv5/cat.h
+++ b/lib/include/libdvbv5/cat.h
@@ -40,7 +40,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_table_cat_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t dvb_table_cat_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct dvb_table_cat **table);
void dvb_table_cat_free(struct dvb_table_cat *cat);
void dvb_table_cat_print(struct dvb_v5_fe_parms *parms, struct dvb_table_cat *t);
diff --git a/lib/libdvbv5/crc32.h b/lib/include/libdvbv5/crc32.h
index d1968e8a..d1968e8a 100644
--- a/lib/libdvbv5/crc32.h
+++ b/lib/include/libdvbv5/crc32.h
diff --git a/lib/include/libdvbv5/desc_atsc_service_location.h b/lib/include/libdvbv5/desc_atsc_service_location.h
index 1ff2341d..310efa39 100644
--- a/lib/include/libdvbv5/desc_atsc_service_location.h
+++ b/lib/include/libdvbv5/desc_atsc_service_location.h
@@ -21,8 +21,7 @@
#ifndef _ATSC_SERVICE_LOCATION_H
#define _ATSC_SERVICE_LOCATION_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct atsc_desc_service_location_elementary {
uint8_t stream_type;
@@ -37,9 +36,7 @@ struct atsc_desc_service_location_elementary {
} __attribute__((packed));
struct atsc_desc_service_location {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
struct atsc_desc_service_location_elementary *elementary;
@@ -60,7 +57,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void atsc_desc_service_location_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int atsc_desc_service_location_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void atsc_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void atsc_desc_service_location_free(struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_ca.h b/lib/include/libdvbv5/desc_ca.h
index 12f4ff34..34723d79 100644
--- a/lib/include/libdvbv5/desc_ca.h
+++ b/lib/include/libdvbv5/desc_ca.h
@@ -22,13 +22,10 @@
#ifndef _CA_H
#define _CA_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_ca {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint16_t ca_id;
union {
@@ -52,7 +49,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_ca_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_ca_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_ca_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_ca_free (struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_ca_identifier.h b/lib/include/libdvbv5/desc_ca_identifier.h
index 18df191a..a4b85378 100644
--- a/lib/include/libdvbv5/desc_ca_identifier.h
+++ b/lib/include/libdvbv5/desc_ca_identifier.h
@@ -22,13 +22,10 @@
#ifndef _CA_IDENTIFIER_H
#define _CA_IDENTIFIER_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_ca_identifier {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint8_t caid_count;
uint16_t *caids;
@@ -44,7 +41,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_ca_identifier_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_ca_identifier_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_ca_identifier_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_ca_identifier_free (struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_cable_delivery.h b/lib/include/libdvbv5/desc_cable_delivery.h
index 7abe920d..b6ffaea0 100644
--- a/lib/include/libdvbv5/desc_cable_delivery.h
+++ b/lib/include/libdvbv5/desc_cable_delivery.h
@@ -23,13 +23,10 @@
#ifndef _CABLE_DELIVERY_H
#define _CABLE_DELIVERY_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_cable_delivery {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint32_t frequency;
union {
@@ -55,7 +52,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_cable_delivery_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_cable_delivery_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_cable_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
extern const unsigned dvbc_modulation_table[];
diff --git a/lib/include/libdvbv5/desc_event_extended.h b/lib/include/libdvbv5/desc_event_extended.h
index 286f91d2..6e07064b 100644
--- a/lib/include/libdvbv5/desc_event_extended.h
+++ b/lib/include/libdvbv5/desc_event_extended.h
@@ -22,13 +22,10 @@
#ifndef _DESC_EVENT_EXTENDED_H
#define _DESC_EVENT_EXTENDED_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_event_extended {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
union {
struct {
@@ -49,7 +46,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_event_extended_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_event_extended_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_event_extended_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_event_extended_free (struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_event_short.h b/lib/include/libdvbv5/desc_event_short.h
index b2c979a6..eac7e967 100644
--- a/lib/include/libdvbv5/desc_event_short.h
+++ b/lib/include/libdvbv5/desc_event_short.h
@@ -22,13 +22,10 @@
#ifndef _DESC_EVENT_SHORT_H
#define _DESC_EVENT_SHORT_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_event_short {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
unsigned char language[4];
char *name;
@@ -43,7 +40,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_event_short_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_event_short_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_event_short_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_event_short_free (struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_extension.h b/lib/include/libdvbv5/desc_extension.h
index 5921cba0..8b2606a5 100644
--- a/lib/include/libdvbv5/desc_extension.h
+++ b/lib/include/libdvbv5/desc_extension.h
@@ -21,8 +21,7 @@
#ifndef _EXTENSION_DESC_H
#define _EXTENSION_DESC_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_v5_fe_parms;
@@ -42,9 +41,7 @@ enum extension_descriptors {
};
struct dvb_extension_descriptor {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint8_t extension_code;
@@ -52,7 +49,7 @@ struct dvb_extension_descriptor {
} __attribute__((packed));
-typedef void (*dvb_desc_ext_init_func) (struct dvb_v5_fe_parms *parms,
+typedef int (*dvb_desc_ext_init_func) (struct dvb_v5_fe_parms *parms,
const uint8_t *buf,
struct dvb_extension_descriptor *ext,
void *desc);
@@ -74,7 +71,7 @@ struct dvb_ext_descriptor {
extern "C" {
#endif
-void extension_descriptor_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int extension_descriptor_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void extension_descriptor_free(struct dvb_desc *descriptor);
void extension_descriptor_print(struct dvb_v5_fe_parms *parms,
const struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_frequency_list.h b/lib/include/libdvbv5/desc_frequency_list.h
index a138e563..b974fc85 100644
--- a/lib/include/libdvbv5/desc_frequency_list.h
+++ b/lib/include/libdvbv5/desc_frequency_list.h
@@ -22,13 +22,10 @@
#ifndef _DESC_FREQUENCY_LIST_H
#define _DESC_FREQUENCY_LIST_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_frequency_list {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint8_t frequencies;
uint32_t *frequency;
@@ -48,7 +45,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_frequency_list_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_frequency_list_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_frequency_list_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
#ifdef __cplusplus
diff --git a/lib/include/libdvbv5/desc_hierarchy.h b/lib/include/libdvbv5/desc_hierarchy.h
index 30bf0822..51075c03 100644
--- a/lib/include/libdvbv5/desc_hierarchy.h
+++ b/lib/include/libdvbv5/desc_hierarchy.h
@@ -22,12 +22,10 @@
#ifndef _HIERARCHY_H
#define _HIERARCHY_H
-#include <stdint.h>
+#include <libdvbv5/descriptors.h>
struct dvb_desc_hierarchy {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint8_t hierarchy_type:4;
uint8_t reserved:4;
@@ -48,7 +46,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_hierarchy_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_hierarchy_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_hierarchy_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
#ifdef __cplusplus
diff --git a/lib/include/libdvbv5/desc_isdbt_delivery.h b/lib/include/libdvbv5/desc_isdbt_delivery.h
index 5bac1780..5d1e2b5f 100644
--- a/lib/include/libdvbv5/desc_isdbt_delivery.h
+++ b/lib/include/libdvbv5/desc_isdbt_delivery.h
@@ -22,14 +22,12 @@
#ifndef _ISDBT_DELIVERY_H
#define _ISDBT_DELIVERY_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct isdbt_desc_terrestrial_delivery_system {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
- uint16_t *frequency;
+ DVB_DESC_HEADER();
+
+ uint32_t *frequency;
unsigned num_freqs;
union {
@@ -37,7 +35,7 @@ struct isdbt_desc_terrestrial_delivery_system {
struct {
uint16_t transmission_mode:2;
uint16_t guard_interval:2;
- uint16_t area_code:6;
+ uint16_t area_code:12;
} __attribute__((packed));
} __attribute__((packed));
} __attribute__((packed));
@@ -48,7 +46,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void isdbt_desc_delivery_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int isdbt_desc_delivery_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void isdbt_desc_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void isdbt_desc_delivery_free(struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_language.h b/lib/include/libdvbv5/desc_language.h
index 28738a3c..62726800 100644
--- a/lib/include/libdvbv5/desc_language.h
+++ b/lib/include/libdvbv5/desc_language.h
@@ -22,13 +22,10 @@
#ifndef _DESC_LANGUAGE_H
#define _DESC_LANGUAGE_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_language {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
unsigned char language[4];
uint8_t audio_type;
@@ -40,7 +37,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_language_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_language_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_language_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
#ifdef __cplusplus
diff --git a/lib/include/libdvbv5/desc_logical_channel.h b/lib/include/libdvbv5/desc_logical_channel.h
index bbccb819..83d44e56 100644
--- a/lib/include/libdvbv5/desc_logical_channel.h
+++ b/lib/include/libdvbv5/desc_logical_channel.h
@@ -25,8 +25,7 @@
#ifndef _LCN_DESC_H
#define _LCN_DESC_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_logical_channel_number {
uint16_t service_id;
@@ -41,9 +40,7 @@ struct dvb_desc_logical_channel_number {
} __attribute__((packed));
struct dvb_desc_logical_channel {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
struct dvb_desc_logical_channel_number *lcn;
} __attribute__((packed));
@@ -54,7 +51,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_logical_channel_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_logical_channel_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_logical_channel_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_logical_channel_free(struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_network_name.h b/lib/include/libdvbv5/desc_network_name.h
index 1ddc86b0..7ab2296d 100644
--- a/lib/include/libdvbv5/desc_network_name.h
+++ b/lib/include/libdvbv5/desc_network_name.h
@@ -22,13 +22,10 @@
#ifndef _DESC_NETWORK_NAME_H
#define _DESC_NETWORK_NAME_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_network_name {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
char *network_name;
char *network_name_emph;
@@ -40,7 +37,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_network_name_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_network_name_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_network_name_free (struct dvb_desc *desc);
void dvb_desc_network_name_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_partial_reception.h b/lib/include/libdvbv5/desc_partial_reception.h
index c6c45f7a..05230e7a 100644
--- a/lib/include/libdvbv5/desc_partial_reception.h
+++ b/lib/include/libdvbv5/desc_partial_reception.h
@@ -25,17 +25,14 @@
#ifndef _PARTIAL_RECEPTION_H
#define _PARTIAL_RECEPTION_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct isdb_partial_reception_service_id {
uint16_t service_id;
} __attribute__((packed));
struct isdb_desc_partial_reception {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
struct isdb_partial_reception_service_id *partial_reception;
} __attribute__((packed));
@@ -46,7 +43,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void isdb_desc_partial_reception_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int isdb_desc_partial_reception_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void isdb_desc_partial_reception_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void isdb_desc_partial_reception_free(struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_sat.h b/lib/include/libdvbv5/desc_sat.h
index cf6393f1..86d9cfb7 100644
--- a/lib/include/libdvbv5/desc_sat.h
+++ b/lib/include/libdvbv5/desc_sat.h
@@ -22,13 +22,10 @@
#ifndef _SAT_H
#define _SAT_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_sat {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint32_t frequency;
uint16_t orbit;
@@ -52,7 +49,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_sat_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_sat_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_sat_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
extern const unsigned dvbs_dvbc_dvbs_freq_inner[];
diff --git a/lib/include/libdvbv5/desc_service.h b/lib/include/libdvbv5/desc_service.h
index eea27ae5..da4423c8 100644
--- a/lib/include/libdvbv5/desc_service.h
+++ b/lib/include/libdvbv5/desc_service.h
@@ -22,13 +22,10 @@
#ifndef _DESC_SERVICE_H
#define _DESC_SERVICE_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_service {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint8_t service_type;
char *name;
@@ -43,7 +40,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_service_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_service_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_service_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_service_free (struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_service_list.h b/lib/include/libdvbv5/desc_service_list.h
index bffce0ee..e71e3211 100644
--- a/lib/include/libdvbv5/desc_service_list.h
+++ b/lib/include/libdvbv5/desc_service_list.h
@@ -22,8 +22,7 @@
#ifndef _DESC_SERVICE_LIST_H
#define _DESC_SERVICE_LIST_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_service_list_table {
uint16_t service_id;
@@ -31,9 +30,7 @@ struct dvb_desc_service_list_table {
} __attribute__((packed));
struct dvb_desc_service_list {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
//struct dvb_desc_service_list_table services[];
} __attribute__((packed));
@@ -44,7 +41,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_service_list_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_service_list_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_service_list_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
#ifdef __cplusplus
diff --git a/lib/include/libdvbv5/desc_service_location.h b/lib/include/libdvbv5/desc_service_location.h
index 78490bd0..af3379bc 100644
--- a/lib/include/libdvbv5/desc_service_location.h
+++ b/lib/include/libdvbv5/desc_service_location.h
@@ -21,7 +21,7 @@
#ifndef _SERVICE_LOCATION_H
#define _SERVICE_LOCATION_H
-#include <stdint.h>
+#include <libdvbv5/descriptors.h>
struct dvb_desc_service_location_element {
uint8_t stream_type;
@@ -36,9 +36,7 @@ struct dvb_desc_service_location_element {
} __attribute__((packed));
struct dvb_desc_service_location {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
union {
uint16_t bitfield;
@@ -57,7 +55,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_service_location_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_service_location_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_service_location_free (struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/desc_t2_delivery.h b/lib/include/libdvbv5/desc_t2_delivery.h
index a51f8979..55c967db 100644
--- a/lib/include/libdvbv5/desc_t2_delivery.h
+++ b/lib/include/libdvbv5/desc_t2_delivery.h
@@ -22,8 +22,7 @@
#ifndef _T2_DELIVERY_H
#define _T2_DELIVERY_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_t2_delivery_subcell {
uint8_t cell_id_extension;
@@ -31,6 +30,8 @@ struct dvb_desc_t2_delivery_subcell {
} __attribute__((packed));
struct dvb_desc_t2_delivery {
+ /* extended descriptor */
+
uint8_t plp_id;
uint16_t system_id;
union {
@@ -58,7 +59,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
+int dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf,
struct dvb_extension_descriptor *ext,
void *desc);
diff --git a/lib/include/libdvbv5/desc_terrestrial_delivery.h b/lib/include/libdvbv5/desc_terrestrial_delivery.h
index b6f039d5..1c711890 100644
--- a/lib/include/libdvbv5/desc_terrestrial_delivery.h
+++ b/lib/include/libdvbv5/desc_terrestrial_delivery.h
@@ -24,13 +24,10 @@
#ifndef _TERRESTRIAL_DELIVERY_H
#define _TERRESTRIAL_DELIVERY_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_terrestrial_delivery {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint32_t centre_frequency;
uint8_t reserved_future_use1:2;
@@ -54,7 +51,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_terrestrial_delivery_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_terrestrial_delivery_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_terrestrial_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
extern const unsigned dvbt_bw[];
extern const unsigned dvbt_modulation[];
diff --git a/lib/include/libdvbv5/desc_ts_info.h b/lib/include/libdvbv5/desc_ts_info.h
index 523aa047..a34a7215 100644
--- a/lib/include/libdvbv5/desc_ts_info.h
+++ b/lib/include/libdvbv5/desc_ts_info.h
@@ -22,8 +22,7 @@
#ifndef _TS_INFO_H
#define _TS_INFO_H
-#include <stdint.h>
-#include <unistd.h> /* ssize_t */
+#include <libdvbv5/descriptors.h>
struct dvb_desc_ts_info_transmission_type {
uint8_t transmission_type_info;
@@ -31,9 +30,7 @@ struct dvb_desc_ts_info_transmission_type {
} __attribute__((packed));
struct dvb_desc_ts_info {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
char *ts_name, *ts_name_emph;
struct dvb_desc_ts_info_transmission_type transmission_type;
@@ -55,7 +52,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_desc_ts_info_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+int dvb_desc_ts_info_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
void dvb_desc_ts_info_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
void dvb_desc_ts_info_free(struct dvb_desc *desc);
diff --git a/lib/include/libdvbv5/descriptors.h b/lib/include/libdvbv5/descriptors.h
index f4d92880..94d85a91 100644
--- a/lib/include/libdvbv5/descriptors.h
+++ b/lib/include/libdvbv5/descriptors.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2011-2012 - Mauro Carvalho Chehab
+ * Copyright (c) 2012-2014 - Andre Roth <neolynx@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -30,19 +31,13 @@
#include <stdint.h>
#define DVB_MAX_PAYLOAD_PACKET_SIZE 4096
-#define DVB_PID_SDT 17
-#define DVB_PMT_TABLE_ID 2
+#define DVB_CRC_SIZE 4
struct dvb_v5_fe_parms;
-typedef void (*dvb_table_init_func)(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+typedef void (*dvb_table_init_func)(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, void **table);
-struct dvb_table_init {
- dvb_table_init_func init;
- ssize_t size;
-};
-
-extern const struct dvb_table_init dvb_table_initializers[];
+extern const dvb_table_init_func dvb_table_initializers[256];
extern char *default_charset;
extern char *output_charset;
@@ -54,22 +49,17 @@ extern char *output_charset;
b = ntohl(b); \
} while (0)
+#define DVB_DESC_HEADER() \
+ uint8_t type; \
+ uint8_t length; \
+ struct dvb_desc *next
+
struct dvb_desc {
- uint8_t type;
- uint8_t length;
- struct dvb_desc *next;
+ DVB_DESC_HEADER();
uint8_t data[];
} __attribute__((packed));
-void dvb_desc_default_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
-#ifdef __cplusplus
-extern "C" {
-#endif
-void dvb_desc_default_print (struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
-#ifdef __cplusplus
-}
-#endif
#define dvb_desc_foreach( _desc, _tbl ) \
for( struct dvb_desc *_desc = _tbl->descriptor; _desc; _desc = _desc->next ) \
@@ -78,17 +68,25 @@ void dvb_desc_default_print (struct dvb_v5_fe_parms *parms, const struct dvb_de
for( _struct *_desc = (_struct *) _tbl->descriptor; _desc; _desc = (_struct *) _desc->next ) \
if(_desc->type == _type) \
+#ifdef __cplusplus
+extern "C" {
+#endif
+
uint32_t bcd(uint32_t bcd);
void hexdump(struct dvb_v5_fe_parms *parms, const char *prefix, const unsigned char *buf, int len);
-void dvb_parse_descriptors(struct dvb_v5_fe_parms *parms, const uint8_t *buf, uint16_t section_length, struct dvb_desc **head_desc);
-void dvb_free_descriptors(struct dvb_desc **list);
-void dvb_print_descriptors(struct dvb_v5_fe_parms *parms, struct dvb_desc *desc);
+int dvb_desc_parse(struct dvb_v5_fe_parms *parms, const uint8_t *buf, uint16_t section_length, struct dvb_desc **head_desc);
+void dvb_desc_free (struct dvb_desc **list);
+void dvb_desc_print(struct dvb_v5_fe_parms *parms, struct dvb_desc *desc);
+
+#ifdef __cplusplus
+}
+#endif
struct dvb_v5_fe_parms;
-typedef void (*dvb_desc_init_func) (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
+typedef int (*dvb_desc_init_func) (struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc);
typedef void (*dvb_desc_print_func)(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc);
typedef void (*dvb_desc_free_func) (struct dvb_desc *desc);
@@ -102,15 +100,6 @@ struct dvb_descriptor {
extern const struct dvb_descriptor dvb_descriptors[];
-enum dvb_tables {
- PAT,
- PMT,
- NIT,
- SDT,
- TVCT,
- CVCT,
-};
-
enum descriptors {
/* ISO/IEC 13818-1 */
video_stream_descriptor = 0x02,
diff --git a/lib/include/libdvbv5/dvb-scan.h b/lib/include/libdvbv5/dvb-scan.h
index 9c47c95d..8f0e553c 100644
--- a/lib/include/libdvbv5/dvb-scan.h
+++ b/lib/include/libdvbv5/dvb-scan.h
@@ -57,12 +57,61 @@ struct dvb_v5_descriptors {
unsigned num_program;
};
-int dvb_read_section(struct dvb_v5_fe_parms *parms, int dmx_fd, unsigned char tid, uint16_t pid, unsigned char **table,
+struct dvb_table_filter {
+ /* Input data */
+ unsigned char tid;
+ uint16_t pid;
+ int ts_id;
+ void **table;
+
+ int allow_section_gaps;
+
+ /*
+ * Private temp data used by dvb_read_sections().
+ * Should not be filled outside dvb-scan.c, as they'll be
+ * overrided
+ */
+ void *priv;
+};
+
+void dvb_table_filter_free(struct dvb_table_filter *sect);
+
+/* Read DVB table sections
+ *
+ * The following functions can be used to read DVB table sections by
+ * specifying a table ID and a program ID. Optionally a transport
+ * stream ID can be specified as well. The function will read on the
+ * specified demux and return when reading is done or an error has
+ * occurred. If table is not NULL after the call, it has to be freed
+ * with the apropriate free table function (even if an error has
+ * occurred).
+ *
+ * Returns 0 on success or a negative error code.
+ *
+ * Example usage:
+ *
+ * struct dvb_table_pat *pat;
+ * int r = dvb_read_section( parms, dmx_fd, DVB_TABLE_PAT, DVB_TABLE_PAT_PID, (void **) &pat, 5 );
+ * if (r < 0)
+ * dvb_logerr("error reading PAT table");
+ * else {
+ * // do something with pat
+ * }
+ * if (pat)
+ * dvb_table_pat_free( pat );
+ *
+ */
+
+int dvb_read_section(struct dvb_v5_fe_parms *parms, int dmx_fd, unsigned char tid, uint16_t pid, void **table,
unsigned timeout);
-int dvb_read_section_with_id(struct dvb_v5_fe_parms *parms, int dmx_fd, unsigned char tid, uint16_t pid, int id, uint8_t **table,
+int dvb_read_section_with_id(struct dvb_v5_fe_parms *parms, int dmx_fd, unsigned char tid, uint16_t pid, int ts_id, void **table,
unsigned timeout);
+int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
+ struct dvb_table_filter *sect,
+ unsigned timeout);
+
struct dvb_v5_descriptors *dvb_scan_alloc_handler_table(uint32_t delivery_system,
int verbose);
diff --git a/lib/include/libdvbv5/eit.h b/lib/include/libdvbv5/eit.h
index 62e070d8..97fbf368 100644
--- a/lib/include/libdvbv5/eit.h
+++ b/lib/include/libdvbv5/eit.h
@@ -27,7 +27,6 @@
#include <time.h>
#include <libdvbv5/header.h>
-#include <libdvbv5/descriptors.h>
#define DVB_TABLE_EIT 0x4E
#define DVB_TABLE_EIT_OTHER 0x4F
@@ -47,7 +46,7 @@ struct dvb_table_eit_event {
union {
uint16_t bitfield2;
struct {
- uint16_t section_length:12;
+ uint16_t desc_length:12;
uint16_t free_CA_mode:1;
uint16_t running_status:3;
} __attribute__((packed));
@@ -79,7 +78,7 @@ extern const char *dvb_eit_running_status_name[8];
extern "C" {
#endif
-void dvb_table_eit_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t dvb_table_eit_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct dvb_table_eit **table);
void dvb_table_eit_free(struct dvb_table_eit *eit);
void dvb_table_eit_print(struct dvb_v5_fe_parms *parms, struct dvb_table_eit *eit);
void dvb_time(const uint8_t data[5], struct tm *tm);
diff --git a/lib/include/libdvbv5/header.h b/lib/include/libdvbv5/header.h
index 67b7694f..856e4dc4 100644
--- a/lib/include/libdvbv5/header.h
+++ b/lib/include/libdvbv5/header.h
@@ -50,10 +50,9 @@ struct dvb_table_header {
union {
uint16_t bitfield;
struct {
- uint16_t section_length:10;
- uint8_t zero:2;
+ uint16_t section_length:12;
uint8_t one:2;
- uint8_t zero2:1;
+ uint8_t zero:1;
uint8_t syntax:1;
} __attribute__((packed));
} __attribute__((packed));
@@ -72,7 +71,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-int dvb_table_header_init (struct dvb_table_header *t);
+void dvb_table_header_init (struct dvb_table_header *t);
void dvb_table_header_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_header *t);
#ifdef __cplusplus
diff --git a/lib/include/libdvbv5/mgt.h b/lib/include/libdvbv5/mgt.h
index 346cbb5c..eb4403ed 100644
--- a/lib/include/libdvbv5/mgt.h
+++ b/lib/include/libdvbv5/mgt.h
@@ -25,7 +25,6 @@
#include <unistd.h> /* ssize_t */
#include <libdvbv5/atsc_header.h>
-#include <libdvbv5/descriptors.h>
#define ATSC_TABLE_MGT 0xC7
@@ -53,7 +52,7 @@ struct atsc_table_mgt_table {
} __attribute__((packed));
struct atsc_table_mgt {
- struct atsc_table_header header;
+ ATSC_HEADER();
uint16_t tables;
struct atsc_table_mgt_table *table;
struct dvb_desc *descriptor;
@@ -68,7 +67,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void atsc_table_mgt_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t atsc_table_mgt_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct atsc_table_mgt **table);
void atsc_table_mgt_free(struct atsc_table_mgt *mgt);
void atsc_table_mgt_print(struct dvb_v5_fe_parms *parms, struct atsc_table_mgt *mgt);
diff --git a/lib/include/libdvbv5/nit.h b/lib/include/libdvbv5/nit.h
index af579315..63ffcd57 100644
--- a/lib/include/libdvbv5/nit.h
+++ b/lib/include/libdvbv5/nit.h
@@ -46,7 +46,7 @@ struct dvb_table_nit_transport {
union {
uint16_t bitfield;
struct {
- uint16_t section_length:12;
+ uint16_t desc_length:12;
uint16_t reserved:4;
} __attribute__((packed));
} __attribute__((packed));
@@ -85,7 +85,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_table_nit_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t dvb_table_nit_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct dvb_table_nit **table);
void dvb_table_nit_free(struct dvb_table_nit *nit);
void dvb_table_nit_print(struct dvb_v5_fe_parms *parms, struct dvb_table_nit *nit);
diff --git a/lib/include/libdvbv5/pat.h b/lib/include/libdvbv5/pat.h
index 4c1fd4de..a2180d5e 100644
--- a/lib/include/libdvbv5/pat.h
+++ b/lib/include/libdvbv5/pat.h
@@ -27,8 +27,8 @@
#include <libdvbv5/header.h>
-#define DVB_TABLE_PAT 0
-#define DVB_TABLE_PAT_PID 0
+#define DVB_TABLE_PAT 0x00
+#define DVB_TABLE_PAT_PID 0x0000
struct dvb_table_pat_program {
uint16_t service_id;
@@ -57,7 +57,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_table_pat_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t dvb_table_pat_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct dvb_table_pat **table);
void dvb_table_pat_free(struct dvb_table_pat *pat);
void dvb_table_pat_print(struct dvb_v5_fe_parms *parms, struct dvb_table_pat *t);
diff --git a/lib/include/libdvbv5/pmt.h b/lib/include/libdvbv5/pmt.h
index e6273f01..150b45a0 100644
--- a/lib/include/libdvbv5/pmt.h
+++ b/lib/include/libdvbv5/pmt.h
@@ -112,7 +112,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_table_pmt_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t dvb_table_pmt_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct dvb_table_pmt **table);
void dvb_table_pmt_free(struct dvb_table_pmt *pmt);
void dvb_table_pmt_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_pmt *pmt);
diff --git a/lib/include/libdvbv5/sdt.h b/lib/include/libdvbv5/sdt.h
index 2b3e8e0a..8455080e 100644
--- a/lib/include/libdvbv5/sdt.h
+++ b/lib/include/libdvbv5/sdt.h
@@ -26,11 +26,10 @@
#include <unistd.h> /* ssize_t */
#include <libdvbv5/header.h>
-#include <libdvbv5/descriptors.h>
#define DVB_TABLE_SDT 0x42
#define DVB_TABLE_SDT2 0x46
-#define DVB_TABLE_SDT_PID 0x11
+#define DVB_TABLE_SDT_PID 0x0011
struct dvb_table_sdt_service {
uint16_t service_id;
@@ -40,7 +39,7 @@ struct dvb_table_sdt_service {
union {
uint16_t bitfield;
struct {
- uint16_t section_length:12;
+ uint16_t desc_length:12;
uint16_t free_CA_mode:1;
uint16_t running_status:3;
} __attribute__((packed));
@@ -65,7 +64,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void dvb_table_sdt_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t dvb_table_sdt_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct dvb_table_sdt **table);
void dvb_table_sdt_free(struct dvb_table_sdt *sdt);
void dvb_table_sdt_print(struct dvb_v5_fe_parms *parms, struct dvb_table_sdt *sdt);
diff --git a/lib/include/libdvbv5/vct.h b/lib/include/libdvbv5/vct.h
index fd7b8450..383c5b19 100644
--- a/lib/include/libdvbv5/vct.h
+++ b/lib/include/libdvbv5/vct.h
@@ -26,7 +26,6 @@
#include <unistd.h> /* ssize_t */
#include <libdvbv5/atsc_header.h>
-#include <libdvbv5/descriptors.h>
#define ATSC_TABLE_TVCT 0xc8
#define ATSC_TABLE_CVCT 0xc9
@@ -85,7 +84,7 @@ struct atsc_table_vct_channel {
} __attribute__((packed));
struct atsc_table_vct {
- struct atsc_table_header header;
+ ATSC_HEADER();
uint8_t num_channels_in_section;
@@ -115,7 +114,7 @@ struct dvb_v5_fe_parms;
extern "C" {
#endif
-void atsc_table_vct_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length);
+ssize_t atsc_table_vct_init (struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, struct atsc_table_vct **table);
void atsc_table_vct_free(struct atsc_table_vct *vct);
void atsc_table_vct_print(struct dvb_v5_fe_parms *parms, struct atsc_table_vct *vct);
diff --git a/lib/include/libv4lconvert.h b/lib/include/libv4lconvert.h
index 2c1f199c..e94d3bd8 100644
--- a/lib/include/libv4lconvert.h
+++ b/lib/include/libv4lconvert.h
@@ -132,6 +132,12 @@ LIBV4L_PUBLIC int v4lconvert_vidioc_g_ctrl(struct v4lconvert_data *data,
void *arg);
LIBV4L_PUBLIC int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data *data,
void *arg);
+LIBV4L_PUBLIC int v4lconvert_vidioc_g_ext_ctrls(struct v4lconvert_data *data,
+ void *arg);
+LIBV4L_PUBLIC int v4lconvert_vidioc_try_ext_ctrls(struct v4lconvert_data *data,
+ void *arg);
+LIBV4L_PUBLIC int v4lconvert_vidioc_s_ext_ctrls(struct v4lconvert_data *data,
+ void *arg);
/* Is the passed in pixelformat supported as destination format? */
LIBV4L_PUBLIC int v4lconvert_supported_dst_format(unsigned int pixelformat);
diff --git a/lib/libdvbv5/Makefile.am b/lib/libdvbv5/Makefile.am
index 667a1afe..969e766f 100644
--- a/lib/libdvbv5/Makefile.am
+++ b/lib/libdvbv5/Makefile.am
@@ -6,6 +6,7 @@ otherinclude_HEADERS = \
../include/libdvbv5/dvb-demux.h \
../include/libdvbv5/dvb-v5-std.h \
../include/libdvbv5/dvb-file.h \
+ ../include/libdvbv5/crc32.h \
../include/libdvbv5/dvb-frontend.h \
../include/libdvbv5/dvb-fe.h \
../include/libdvbv5/dvb-sat.h \
@@ -59,31 +60,35 @@ libdvbv5_la_SOURCES = \
dvb-legacy-channel-format.c \
dvb-zap-format.c \
dvb-v5.c \
+ dvb-v5.h \
parse_string.c \
+ parse_string.h \
dvb-demux.c \
dvb-fe.c \
- dvb-log.c \
- dvb-file.c \
- dvb-v5-std.c \
- dvb-sat.c \
- dvb-scan.c \
- descriptors.c \
- descriptors/header.c \
- descriptors/atsc_header.c \
- descriptors/pat.c \
- descriptors/pmt.c \
- descriptors/nit.c \
- descriptors/sdt.c \
- descriptors/vct.c \
- descriptors/mgt.c \
- descriptors/eit.c \
- descriptors/cat.c \
- descriptors/atsc_eit.c \
+ dvb-log.c \
+ dvb-file.c \
+ dvb-v5-std.c \
+ dvb-sat.c \
+ dvb-scan.c \
+ descriptors.c \
+ tables/header.c \
+ tables/pat.c \
+ tables/pmt.c \
+ tables/nit.c \
+ tables/sdt.c \
+ tables/vct.c \
+ tables/mgt.c \
+ tables/eit.c \
+ tables/cat.c \
+ tables/atsc_eit.c \
+ tables/mpeg_ts.c \
+ tables/mpeg_pes.c \
+ tables/mpeg_es.c \
descriptors/desc_language.c \
descriptors/desc_network_name.c \
descriptors/desc_cable_delivery.c \
descriptors/desc_sat.c \
- descriptors/desc_terrestrial_delivery.c \
+ descriptors/desc_terrestrial_delivery.c \
descriptors/desc_t2_delivery.c \
descriptors/desc_service.c \
descriptors/desc_frequency_list.c \
@@ -99,10 +104,7 @@ libdvbv5_la_SOURCES = \
descriptors/desc_partial_reception.c \
descriptors/desc_service_location.c \
descriptors/desc_ca.c \
- descriptors/desc_ca_identifier.c \
- descriptors/mpeg_ts.c \
- descriptors/mpeg_pes.c \
- descriptors/mpeg_es.c
+ descriptors/desc_ca_identifier.c
libdvbv5_la_CPPFLAGS = -I../.. $(ENFORCE_LIBDVBV5_STATIC)
libdvbv5_la_LDFLAGS = $(LIBDVBV5_VERSION) $(ENFORCE_LIBDVBV5_STATIC) -lm
@@ -111,4 +113,4 @@ libdvbv5_la_LIBADD = $(LTLIBICONV)
EXTRA_DIST = README gen_dvb_structs.pl
sync-with-kernel:
- ./gen_dvb_structs.pl $(KERNEL_DIR)/include/
+ ./gen_dvb_structs.pl $(KERNEL_DIR)/usr/include/
diff --git a/lib/libdvbv5/crc32.c b/lib/libdvbv5/crc32.c
index f14dbe1b..69d0be30 100644
--- a/lib/libdvbv5/crc32.c
+++ b/lib/libdvbv5/crc32.c
@@ -19,7 +19,7 @@
*
*/
-#include "crc32.h"
+#include <libdvbv5/crc32.h>
static uint32_t crctab[256] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
diff --git a/lib/libdvbv5/descriptors.c b/lib/libdvbv5/descriptors.c
index 15696f04..bfbf529a 100644
--- a/lib/libdvbv5/descriptors.c
+++ b/lib/libdvbv5/descriptors.c
@@ -66,37 +66,40 @@ static void dvb_desc_init(uint8_t type, uint8_t length, struct dvb_desc *desc)
desc->next = NULL;
}
-void dvb_desc_default_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+static int dvb_desc_default_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
memcpy(desc->data, buf, desc->length);
+ return 0;
}
-void dvb_desc_default_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
+static void dvb_desc_default_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
if (!parms)
parms = dvb_fe_dummy();
- dvb_log("| %s (0x%02x)", dvb_descriptors[desc->type].name, desc->type);
- hexdump(parms, "| ", desc->data, desc->length);
+ hexdump(parms, "| ", desc->data, desc->length);
}
-const struct dvb_table_init dvb_table_initializers[] = {
- [DVB_TABLE_PAT] = { dvb_table_pat_init, sizeof(struct dvb_table_pat) },
- [DVB_TABLE_CAT] = { dvb_table_cat_init, sizeof(struct dvb_table_cat) },
- [DVB_TABLE_PMT] = { dvb_table_pmt_init, sizeof(struct dvb_table_pmt) },
- [DVB_TABLE_NIT] = { dvb_table_nit_init, sizeof(struct dvb_table_nit) },
- [DVB_TABLE_SDT] = { dvb_table_sdt_init, sizeof(struct dvb_table_sdt) },
- [DVB_TABLE_EIT] = { dvb_table_eit_init, sizeof(struct dvb_table_eit) },
- [DVB_TABLE_EIT_SCHEDULE] = { dvb_table_eit_init, sizeof(struct dvb_table_eit) },
- [ATSC_TABLE_MGT] = { atsc_table_mgt_init, sizeof(struct atsc_table_mgt) },
- [ATSC_TABLE_EIT] = { atsc_table_eit_init, sizeof(struct atsc_table_eit) },
- [ATSC_TABLE_TVCT] = { atsc_table_vct_init, sizeof(struct atsc_table_vct) },
- [ATSC_TABLE_CVCT] = { atsc_table_vct_init, sizeof(struct atsc_table_vct) },
+#define TABLE_INIT(_x) (dvb_table_init_func) _x##_init
+
+const dvb_table_init_func dvb_table_initializers[256] = {
+ [0 ... 255] = NULL,
+ [DVB_TABLE_PAT] = TABLE_INIT(dvb_table_pat),
+ [DVB_TABLE_CAT] = TABLE_INIT(dvb_table_cat),
+ [DVB_TABLE_PMT] = TABLE_INIT(dvb_table_pmt),
+ [DVB_TABLE_NIT] = TABLE_INIT(dvb_table_nit),
+ [DVB_TABLE_SDT] = TABLE_INIT(dvb_table_sdt),
+ [DVB_TABLE_EIT] = TABLE_INIT(dvb_table_eit),
+ [DVB_TABLE_EIT_SCHEDULE] = TABLE_INIT(dvb_table_eit),
+ [ATSC_TABLE_MGT] = TABLE_INIT(atsc_table_mgt),
+ [ATSC_TABLE_EIT] = TABLE_INIT(atsc_table_eit),
+ [ATSC_TABLE_TVCT] = TABLE_INIT(atsc_table_vct),
+ [ATSC_TABLE_CVCT] = TABLE_INIT(atsc_table_vct),
};
char *default_charset = "iso-8859-1";
char *output_charset = "utf-8";
-void dvb_parse_descriptors(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+int dvb_desc_parse(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
uint16_t buflen, struct dvb_desc **head_desc)
{
const uint8_t *ptr = buf, *endbuf = buf + buflen;
@@ -110,12 +113,17 @@ void dvb_parse_descriptors(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
uint8_t desc_len = ptr[1];
size_t size;
+ if (desc_type == 0xff ) {
+ dvb_logwarn("%s: stopping at invalid descriptor 0xff", __func__);
+ return 0;
+ }
+
ptr += 2; /* skip type and length */
if (ptr + desc_len > endbuf) {
- dvb_logerr("short read of %zd/%d bytes parsing descriptor %#02x",
- endbuf - ptr, desc_len, desc_type);
- return;
+ dvb_logerr("%s: short read of %zd/%d bytes parsing descriptor %#02x",
+ __func__, endbuf - ptr, desc_len, desc_type);
+ return -1;
}
switch (parms->verbose) {
@@ -142,16 +150,19 @@ void dvb_parse_descriptors(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
}
if (!size) {
dvb_logerr("descriptor type 0x%02x has no size defined", desc_type);
- return;
+ return -2;
}
current = calloc(1, size);
if (!current) {
- dvb_perror("Out of memory");
- return;
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
}
dvb_desc_init(desc_type, desc_len, current); /* initialize the standard header */
- init(parms, ptr, current);
+ if (init(parms, ptr, current) != 0) {
+ free(current);
+ return -4;
+ }
if (!*head_desc)
*head_desc = current;
if (last)
@@ -159,20 +170,22 @@ void dvb_parse_descriptors(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
last = current;
ptr += current->length; /* standard descriptor header plus descriptor length */
}
+ return 0;
}
-void dvb_print_descriptors(struct dvb_v5_fe_parms *parms, struct dvb_desc *desc)
+void dvb_desc_print(struct dvb_v5_fe_parms *parms, struct dvb_desc *desc)
{
while (desc) {
dvb_desc_print_func print = dvb_descriptors[desc->type].print;
if (!print)
print = dvb_desc_default_print;
+ dvb_loginfo("| 0x%02x: %s", desc->type, dvb_descriptors[desc->type].name);
print(parms, desc);
desc = desc->next;
}
}
-void dvb_free_descriptors(struct dvb_desc **list)
+void dvb_desc_free(struct dvb_desc **list)
{
struct dvb_desc *desc = *list;
while (desc) {
@@ -1362,6 +1375,6 @@ void hexdump(struct dvb_v5_fe_parms *parms, const char *prefix, const unsigned c
for (i = strlen(hex); i < 49; i++)
strncat(spaces, " ", sizeof(spaces));
ascii[j] = '\0';
- dvb_log("%s %s %s %s", prefix, hex, spaces, ascii);
+ dvb_loginfo("%s%s %s %s", prefix, hex, spaces, ascii);
}
}
diff --git a/lib/libdvbv5/descriptors/atsc_header.c b/lib/libdvbv5/descriptors/atsc_header.c
deleted file mode 100644
index 06d1bb1d..00000000
--- a/lib/libdvbv5/descriptors/atsc_header.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2013 - Andre Roth <neolynx@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- *
- */
-
-#include <libdvbv5/atsc_header.h>
-#include <libdvbv5/descriptors.h>
-#include <libdvbv5/dvb-fe.h>
-
-int atsc_table_header_init(struct atsc_table_header *t)
-{
- bswap16(t->bitfield);
- bswap16(t->id);
- return 0;
-}
-
-void atsc_table_header_print(struct dvb_v5_fe_parms *parms, const struct atsc_table_header *t)
-{
- dvb_log("| table_id %02x", t->table_id);
- dvb_log("| section_length %d", t->section_length);
- dvb_log("| syntax %d", t->syntax);
- dvb_log("| priv %d", t->priv);
- dvb_log("| one %d", t->one);
- dvb_log("| id %d", t->id);
- dvb_log("| one2 %d", t->one2);
- dvb_log("| version %d", t->version);
- dvb_log("| current_next %d", t->current_next);
- dvb_log("| section_id %d", t->section_id);
- dvb_log("| last_section %d", t->last_section);
- dvb_log("| protocol_version %d", t->protocol_version);
-}
-
diff --git a/lib/libdvbv5/descriptors/cat.c b/lib/libdvbv5/descriptors/cat.c
deleted file mode 100644
index 40699238..00000000
--- a/lib/libdvbv5/descriptors/cat.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2013 - Andre Roth <neolynx@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- *
- */
-
-#include <libdvbv5/cat.h>
-#include <libdvbv5/descriptors.h>
-#include <libdvbv5/dvb-fe.h>
-
-void dvb_table_cat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
- ssize_t buflen, uint8_t *table, ssize_t *table_length)
-{
- struct dvb_table_cat *cat = (void *)table;
- struct dvb_desc **head_desc = &cat->descriptor;
- const uint8_t *p = buf, *endbuf = buf + buflen - 4;
- size_t size;
-
- if (buf[0] != DVB_TABLE_CAT) {
- dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x", __func__, buf[0], DVB_TABLE_CAT);
- *table_length = 0;
- return;
- }
-
- if (*table_length > 0) {
- /* find end of current lists */
- while (*head_desc != NULL)
- head_desc = &(*head_desc)->next;
- }
-
- size = offsetof(struct dvb_table_cat, descriptor);
- if (p + size > endbuf) {
- dvb_logerr("CAT table was truncated while filling dvb_table_cat. Need %zu bytes, but has only %zu.",
- size, buflen);
- return;
- }
-
- memcpy(table, p, size);
- p += size;
- *table_length = sizeof(struct dvb_table_cat);
-
- size = endbuf - p;
- dvb_parse_descriptors(parms, p, size, head_desc);
-}
-
-void dvb_table_cat_free(struct dvb_table_cat *cat)
-{
- dvb_free_descriptors((struct dvb_desc **) &cat->descriptor);
- free(cat);
-}
-
-void dvb_table_cat_print(struct dvb_v5_fe_parms *parms, struct dvb_table_cat *cat)
-{
- dvb_log("cat");
- dvb_table_header_print(parms, &cat->header);
- dvb_print_descriptors(parms, cat->descriptor);
-}
-
diff --git a/lib/libdvbv5/descriptors/desc_atsc_service_location.c b/lib/libdvbv5/descriptors/desc_atsc_service_location.c
index 5e3f461e..3f19e720 100644
--- a/lib/libdvbv5/descriptors/desc_atsc_service_location.c
+++ b/lib/libdvbv5/descriptors/desc_atsc_service_location.c
@@ -18,11 +18,10 @@
*
*/
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/desc_atsc_service_location.h>
#include <libdvbv5/dvb-fe.h>
-void atsc_desc_service_location_init(struct dvb_v5_fe_parms *parms,
+int atsc_desc_service_location_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf, struct dvb_desc *desc)
{
struct atsc_desc_service_location *s_loc = (struct atsc_desc_service_location *)desc;
@@ -41,7 +40,7 @@ void atsc_desc_service_location_init(struct dvb_v5_fe_parms *parms,
s_loc->elementary = malloc(s_loc->number_elements * sizeof(*s_loc->elementary));
if (!s_loc->elementary) {
dvb_perror("Can't allocate space for ATSC service location elementary data");
- return;
+ return -1;
}
el = s_loc->elementary;
@@ -56,6 +55,7 @@ void atsc_desc_service_location_init(struct dvb_v5_fe_parms *parms,
} else {
s_loc->elementary = NULL;
}
+ return 0;
}
void atsc_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
@@ -64,14 +64,13 @@ void atsc_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struc
struct atsc_desc_service_location_elementary *el = s_loc->elementary;
int i;
- dvb_log("| service location");
- dvb_log("| pcr PID %d", s_loc->pcr_pid);
- dvb_log("|\\ elementary service - %d elementaries", s_loc->number_elements);
+ dvb_loginfo("| pcr PID %d", s_loc->pcr_pid);
+ dvb_loginfo("|\\ elementary service - %d elementaries", s_loc->number_elements);
for (i = 0; i < s_loc->number_elements; i++) {
- dvb_log("|- elementary %d", i);
- dvb_log("|- | stream type 0x%02x", el[i].stream_type);
- dvb_log("|- | PID %d", el[i].elementary_pid);
- dvb_log("|- | Language %c%c%c",
+ dvb_loginfo("|- elementary %d", i);
+ dvb_loginfo("|- | stream type 0x%02x", el[i].stream_type);
+ dvb_loginfo("|- | PID %d", el[i].elementary_pid);
+ dvb_loginfo("|- | Language %c%c%c",
el[i].ISO_639_language_code[0],
el[i].ISO_639_language_code[1],
el[i].ISO_639_language_code[2]);
diff --git a/lib/libdvbv5/descriptors/desc_ca.c b/lib/libdvbv5/descriptors/desc_ca.c
index 6b481758..fa18814a 100644
--- a/lib/libdvbv5/descriptors/desc_ca.c
+++ b/lib/libdvbv5/descriptors/desc_ca.c
@@ -20,10 +20,9 @@
*/
#include <libdvbv5/desc_ca.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_ca_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_ca_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
size_t size = offsetof(struct dvb_desc_ca, dvb_desc_ca_field_last) - offsetof(struct dvb_desc_ca, dvb_desc_ca_field_first);
struct dvb_desc_ca *d = (struct dvb_desc_ca *) desc;
@@ -43,14 +42,15 @@ void dvb_desc_ca_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct
}
/*hexdump(parms, "desc ca ", buf, desc->length);*/
/*dvb_desc_ca_print(parms, desc);*/
+ return 0;
}
void dvb_desc_ca_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_ca *d = (const struct dvb_desc_ca *) desc;
- dvb_log("| ca_id %04x", d->ca_id);
- dvb_log("| ca_pid %04x", d->ca_pid);
- dvb_log("| privdata length %d", d->privdata_len);
+ dvb_loginfo("| ca_id 0x%04x", d->ca_id);
+ dvb_loginfo("| ca_pid 0x%04x", d->ca_pid);
+ dvb_loginfo("| privdata length %d", d->privdata_len);
if (d->privdata)
hexdump(parms, "| privdata ", d->privdata, d->privdata_len);
}
diff --git a/lib/libdvbv5/descriptors/desc_ca_identifier.c b/lib/libdvbv5/descriptors/desc_ca_identifier.c
index 4740a017..23c8e897 100644
--- a/lib/libdvbv5/descriptors/desc_ca_identifier.c
+++ b/lib/libdvbv5/descriptors/desc_ca_identifier.c
@@ -20,10 +20,9 @@
*/
#include <libdvbv5/desc_ca_identifier.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_ca_identifier_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_ca_identifier_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_ca_identifier *d = (struct dvb_desc_ca_identifier *) desc;
int i;
@@ -32,12 +31,13 @@ void dvb_desc_ca_identifier_init(struct dvb_v5_fe_parms *parms, const uint8_t *b
d->caids = malloc(d->length);
if (!d->caids) {
dvb_logerr("dvb_desc_ca_identifier_init: out of memory");
- return;
+ return -1;
}
for (i = 0; i < d->caid_count; i++) {
d->caids[i] = ((uint16_t *) buf)[i];
bswap16(d->caids[i]);
}
+ return 0;
}
void dvb_desc_ca_identifier_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
@@ -46,7 +46,7 @@ void dvb_desc_ca_identifier_print(struct dvb_v5_fe_parms *parms, const struct dv
int i;
for (i = 0; i < d->caid_count; i++)
- dvb_log("| caid %d %04x", i, d->caids[i]);
+ dvb_loginfo("| caid %d 0x%04x", i, d->caids[i]);
}
void dvb_desc_ca_identifier_free(struct dvb_desc *desc)
diff --git a/lib/libdvbv5/descriptors/desc_cable_delivery.c b/lib/libdvbv5/descriptors/desc_cable_delivery.c
index 2cfc679b..852c79e4 100644
--- a/lib/libdvbv5/descriptors/desc_cable_delivery.c
+++ b/lib/libdvbv5/descriptors/desc_cable_delivery.c
@@ -21,10 +21,9 @@
*/
#include <libdvbv5/desc_cable_delivery.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_cable_delivery_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_cable_delivery_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_cable_delivery *cable = (struct dvb_desc_cable_delivery *) desc;
/* copy only the data - length already initialize */
@@ -36,18 +35,18 @@ void dvb_desc_cable_delivery_init(struct dvb_v5_fe_parms *parms, const uint8_t *
bswap32(cable->bitfield2);
cable->frequency = bcd(cable->frequency) * 100;
cable->symbol_rate = bcd(cable->symbol_rate) * 100;
+ return 0;
}
void dvb_desc_cable_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_cable_delivery *cable = (const struct dvb_desc_cable_delivery *) desc;
- dvb_log("| cable delivery");
- dvb_log("| length %d", cable->length);
- dvb_log("| frequency %d", cable->frequency);
- dvb_log("| fec outer %d", cable->fec_outer);
- dvb_log("| modulation %d", cable->modulation);
- dvb_log("| symbol_rate %d", cable->symbol_rate);
- dvb_log("| fec inner %d", cable->fec_inner);
+ dvb_loginfo("| length %d", cable->length);
+ dvb_loginfo("| frequency %d", cable->frequency);
+ dvb_loginfo("| fec outer %d", cable->fec_outer);
+ dvb_loginfo("| modulation %d", cable->modulation);
+ dvb_loginfo("| symbol_rate %d", cable->symbol_rate);
+ dvb_loginfo("| fec inner %d", cable->fec_inner);
}
const unsigned dvbc_fec_table[] = {
diff --git a/lib/libdvbv5/descriptors/desc_event_extended.c b/lib/libdvbv5/descriptors/desc_event_extended.c
index 51c7d2bd..d0865f9a 100644
--- a/lib/libdvbv5/descriptors/desc_event_extended.c
+++ b/lib/libdvbv5/descriptors/desc_event_extended.c
@@ -20,11 +20,10 @@
*/
#include <libdvbv5/desc_event_extended.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
#include <parse_string.h>
-void dvb_desc_event_extended_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_event_extended_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_event_extended *event = (struct dvb_desc_event_extended *) desc;
uint8_t len; /* the length of the string in the input data */
@@ -62,6 +61,7 @@ void dvb_desc_event_extended_init(struct dvb_v5_fe_parms *parms, const uint8_t *
buf++;
parse_string(parms, &event->text, &event->text_emph, buf, len1, default_charset, output_charset);
buf += len;
+ return 0;
}
void dvb_desc_event_extended_free(struct dvb_desc *desc)
@@ -74,6 +74,6 @@ void dvb_desc_event_extended_free(struct dvb_desc *desc)
void dvb_desc_event_extended_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_event_extended *event = (const struct dvb_desc_event_extended *) desc;
- dvb_log("| Description '%s'", event->text);
+ dvb_loginfo("| '%s'", event->text);
}
diff --git a/lib/libdvbv5/descriptors/desc_event_short.c b/lib/libdvbv5/descriptors/desc_event_short.c
index 85255799..535e656d 100644
--- a/lib/libdvbv5/descriptors/desc_event_short.c
+++ b/lib/libdvbv5/descriptors/desc_event_short.c
@@ -20,11 +20,10 @@
*/
#include <libdvbv5/desc_event_short.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
#include <parse_string.h>
-void dvb_desc_event_short_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_event_short_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_event_short *event = (struct dvb_desc_event_short *) desc;
uint8_t len; /* the length of the string in the input data */
@@ -53,6 +52,7 @@ void dvb_desc_event_short_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf
buf++;
parse_string(parms, &event->text, &event->text_emph, buf, len2, default_charset, output_charset);
buf += len;
+ return 0;
}
void dvb_desc_event_short_free(struct dvb_desc *desc)
@@ -67,8 +67,8 @@ void dvb_desc_event_short_free(struct dvb_desc *desc)
void dvb_desc_event_short_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_event_short *event = (const struct dvb_desc_event_short *) desc;
- dvb_log("| Name '%s'", event->name);
- dvb_log("| Language '%s'", event->language);
- dvb_log("| Description '%s'", event->text);
+ dvb_loginfo("| name '%s'", event->name);
+ dvb_loginfo("| language '%s'", event->language);
+ dvb_loginfo("| sescription '%s'", event->text);
}
diff --git a/lib/libdvbv5/descriptors/desc_extension.c b/lib/libdvbv5/descriptors/desc_extension.c
index 400372f1..7d9337cd 100644
--- a/lib/libdvbv5/descriptors/desc_extension.c
+++ b/lib/libdvbv5/descriptors/desc_extension.c
@@ -18,7 +18,6 @@
*
*/
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/desc_extension.h>
#include <libdvbv5/desc_t2_delivery.h>
#include <libdvbv5/dvb-fe.h>
@@ -117,7 +116,7 @@ const struct dvb_ext_descriptor dvb_ext_descriptors[] = {
},
};
-void extension_descriptor_init(struct dvb_v5_fe_parms *parms,
+int extension_descriptor_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_extension_descriptor *ext = (void *)desc;
@@ -139,7 +138,7 @@ void extension_descriptor_init(struct dvb_v5_fe_parms *parms,
break;
/* fall through */
case 3:
- dvb_log("%sextension descriptor %s type 0x%02x, size %d",
+ dvb_logwarn("%sextension descriptor %s type 0x%02x, size %d",
dvb_ext_descriptors[desc_type].init ? "" : "Not handled ",
dvb_ext_descriptors[desc_type].name, desc_type, desc_len);
hexdump(parms, "content: ", p, desc_len);
@@ -153,10 +152,13 @@ void extension_descriptor_init(struct dvb_v5_fe_parms *parms,
ext->descriptor = calloc(1, size);
- if (init)
- init(parms, p, ext, ext->descriptor);
+ if (init) {
+ if (init(parms, p, ext, ext->descriptor) != 0)
+ return -1;
+ }
else
memcpy(ext->descriptor, p, size);
+ return 0;
}
void extension_descriptor_free(struct dvb_desc *descriptor)
@@ -178,7 +180,7 @@ void extension_descriptor_print(struct dvb_v5_fe_parms *parms,
{
struct dvb_extension_descriptor *ext = (void *)desc;
uint8_t type = ext->extension_code;
- dvb_log("Extension descriptor %s type 0x%02x",
+ dvb_loginfo("| descriptor %s type 0x%02x",
dvb_ext_descriptors[type].name, type);
if (dvb_ext_descriptors[type].print)
diff --git a/lib/libdvbv5/descriptors/desc_frequency_list.c b/lib/libdvbv5/descriptors/desc_frequency_list.c
index 9a911a30..5b235d45 100644
--- a/lib/libdvbv5/descriptors/desc_frequency_list.c
+++ b/lib/libdvbv5/descriptors/desc_frequency_list.c
@@ -20,10 +20,9 @@
*/
#include <libdvbv5/desc_frequency_list.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_frequency_list_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_frequency_list_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_frequency_list *d = (struct dvb_desc_frequency_list *) desc;
size_t len;
@@ -54,16 +53,17 @@ void dvb_desc_frequency_list_init(struct dvb_v5_fe_parms *parms, const uint8_t *
break;
}
}
+ return 0;
}
void dvb_desc_frequency_list_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_frequency_list *d = (const struct dvb_desc_frequency_list *) desc;
- dvb_log("| frequency list type: %d", d->freq_type);
+ dvb_loginfo("| type: %d", d->freq_type);
int i = 0;
for (i = 0; i < d->frequencies; i++) {
- dvb_log("| frequency : %u", d->frequency[i]);
+ dvb_loginfo("| frequency : %u", d->frequency[i]);
}
}
diff --git a/lib/libdvbv5/descriptors/desc_hierarchy.c b/lib/libdvbv5/descriptors/desc_hierarchy.c
index b6e0adc6..773068f2 100644
--- a/lib/libdvbv5/descriptors/desc_hierarchy.c
+++ b/lib/libdvbv5/descriptors/desc_hierarchy.c
@@ -20,25 +20,24 @@
*/
#include <libdvbv5/desc_hierarchy.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_hierarchy_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_hierarchy_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_hierarchy *hierarchy = (struct dvb_desc_hierarchy *) desc;
/* copy from .length */
memcpy(((uint8_t *) hierarchy ) + sizeof(hierarchy->type) + sizeof(hierarchy->length) + sizeof(hierarchy->next),
buf,
hierarchy->length);
+ return 0;
}
void dvb_desc_hierarchy_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_hierarchy *hierarchy = (const struct dvb_desc_hierarchy *) desc;
- dvb_log("| Hierarchy");
- dvb_log("| type %d", hierarchy->hierarchy_type);
- dvb_log("| layer %d", hierarchy->layer);
- dvb_log("| embedded_layer %d", hierarchy->embedded_layer);
- dvb_log("| channel %d", hierarchy->channel);
+ dvb_loginfo("| type %d", hierarchy->hierarchy_type);
+ dvb_loginfo("| layer %d", hierarchy->layer);
+ dvb_loginfo("| embedded_layer %d", hierarchy->embedded_layer);
+ dvb_loginfo("| channel %d", hierarchy->channel);
}
diff --git a/lib/libdvbv5/descriptors/desc_isdbt_delivery.c b/lib/libdvbv5/descriptors/desc_isdbt_delivery.c
index df04580c..df5abed6 100644
--- a/lib/libdvbv5/descriptors/desc_isdbt_delivery.c
+++ b/lib/libdvbv5/descriptors/desc_isdbt_delivery.c
@@ -18,17 +18,18 @@
*
*/
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/desc_isdbt_delivery.h>
#include <libdvbv5/dvb-fe.h>
+#include <inttypes.h>
-void isdbt_desc_delivery_init(struct dvb_v5_fe_parms *parms,
+int isdbt_desc_delivery_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf, struct dvb_desc *desc)
{
struct isdbt_desc_terrestrial_delivery_system *d = (void *)desc;
unsigned char *p = (unsigned char *) buf;
int i;
size_t len;
+ uint16_t frq;
len = sizeof(*d) - offsetof(struct isdbt_desc_terrestrial_delivery_system, bitfield);
memcpy(&d->bitfield, p, len);
@@ -36,18 +37,24 @@ void isdbt_desc_delivery_init(struct dvb_v5_fe_parms *parms,
bswap16(d->bitfield);
- d->num_freqs = d->length / 2;
- if (!len)
- return;
+ d->num_freqs = d->length / sizeof(uint16_t);
+ if (!d->num_freqs)
+ return 0;
d->frequency = malloc(d->num_freqs * sizeof(*d->frequency));
if (!d->frequency) {
dvb_perror("Can't allocate space for ISDB-T frequencies");
- return;
+ return -2;
}
- memcpy(d->frequency, p, d->num_freqs * sizeof(*d->frequency));
- for (i = 0; i < d->num_freqs; i++)
- bswap16(d->frequency[i]);
+ for (i = 0; i < d->num_freqs; i++) {
+ frq = *(uint16_t *)p;
+ p += sizeof(uint16_t);
+
+ bswap16(frq);
+
+ d->frequency[i] = (uint32_t)((((uint64_t)frq) * 1000000ul) / 7);
+ }
+ return 0;
}
static const char *interval_name[] = {
@@ -83,15 +90,14 @@ void isdbt_desc_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_d
const struct isdbt_desc_terrestrial_delivery_system *d = (const void *) desc;
int i;
- dvb_log("| ISDB-T delivery");
- dvb_log("| transmission mode %s (%d)",
+ dvb_loginfo("| transmission mode %s (%d)",
tm_name[d->transmission_mode], d->transmission_mode);
- dvb_log("| guard interval %s (%d)",
+ dvb_loginfo("| guard interval %s (%d)",
interval_name[d->guard_interval], d->guard_interval);
- dvb_log("| area code %d", d->area_code);
+ dvb_loginfo("| area code %d", d->area_code);
for (i = 0; i < d->num_freqs; i++) {
- dvb_log("| frequency[%d] %ld Hz", i, d->frequency[i] * 1000000l / 7);
+ dvb_loginfo("| frequency[%d] %u Hz", i, d->frequency[i]);
}
}
diff --git a/lib/libdvbv5/descriptors/desc_language.c b/lib/libdvbv5/descriptors/desc_language.c
index 3d234e14..617fcc70 100644
--- a/lib/libdvbv5/descriptors/desc_language.c
+++ b/lib/libdvbv5/descriptors/desc_language.c
@@ -20,10 +20,9 @@
*/
#include <libdvbv5/desc_language.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_language_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_language_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_language *lang = (struct dvb_desc_language *) desc;
@@ -32,11 +31,12 @@ void dvb_desc_language_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, s
lang->language[2] = buf[2];
lang->language[3] = '\0';
lang->audio_type = buf[3];
+ return 0;
}
void dvb_desc_language_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_language *lang = (const struct dvb_desc_language *) desc;
- dvb_log("| lang: %s (type: %d)", lang->language, lang->audio_type);
+ dvb_loginfo("| lang: %s (type: %d)", lang->language, lang->audio_type);
}
diff --git a/lib/libdvbv5/descriptors/desc_logical_channel.c b/lib/libdvbv5/descriptors/desc_logical_channel.c
index d3edbd93..99a4507f 100644
--- a/lib/libdvbv5/descriptors/desc_logical_channel.c
+++ b/lib/libdvbv5/descriptors/desc_logical_channel.c
@@ -22,12 +22,11 @@
* http://tdt.telecom.pt/recursos/apresentacoes/Signalling Specifications for DTT deployment in Portugal.pdf
*/
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/desc_logical_channel.h>
#include <libdvbv5/dvb-fe.h>
#include <parse_string.h>
-void dvb_desc_logical_channel_init(struct dvb_v5_fe_parms *parms,
+int dvb_desc_logical_channel_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_logical_channel *d = (void *)desc;
@@ -37,8 +36,8 @@ void dvb_desc_logical_channel_init(struct dvb_v5_fe_parms *parms,
d->lcn = malloc(d->length);
if (!d->lcn) {
- dvb_perror("Out of memory!");
- return;
+ dvb_logerr("%s: out of memory", __func__);
+ return -1;
}
memcpy(d->lcn, p, d->length);
@@ -49,6 +48,7 @@ void dvb_desc_logical_channel_init(struct dvb_v5_fe_parms *parms,
bswap16(d->lcn[i].service_id);
bswap16(d->lcn[i].bitfield);
}
+ return 0;
}
void dvb_desc_logical_channel_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
@@ -60,9 +60,9 @@ void dvb_desc_logical_channel_print(struct dvb_v5_fe_parms *parms, const struct
len = d->length / sizeof(d->lcn);
for (i = 0; i < len; i++) {
- dvb_log("| service ID[%d] %d", i, d->lcn[i].service_id);
- dvb_log("| LCN %d", d->lcn[i].logical_channel_number);
- dvb_log("| visible service %d", d->lcn[i].visible_service_flag);
+ dvb_loginfo("| service ID[%d] %d", i, d->lcn[i].service_id);
+ dvb_loginfo("| LCN %d", d->lcn[i].logical_channel_number);
+ dvb_loginfo("| visible service %d", d->lcn[i].visible_service_flag);
}
}
diff --git a/lib/libdvbv5/descriptors/desc_network_name.c b/lib/libdvbv5/descriptors/desc_network_name.c
index b48cec1c..a34a27fa 100644
--- a/lib/libdvbv5/descriptors/desc_network_name.c
+++ b/lib/libdvbv5/descriptors/desc_network_name.c
@@ -20,11 +20,10 @@
*/
#include <libdvbv5/desc_network_name.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
#include "parse_string.h"
-void dvb_desc_network_name_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_network_name_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_network_name *net = (struct dvb_desc_network_name *) desc;
uint8_t len; /* the length of the string in the input data */
@@ -36,13 +35,14 @@ void dvb_desc_network_name_init(struct dvb_v5_fe_parms *parms, const uint8_t *bu
net->network_name_emph = NULL;
parse_string(parms, &net->network_name, &net->network_name_emph, buf, len1, default_charset, output_charset);
buf += len;
+ return 0;
}
void dvb_desc_network_name_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_network_name *net = (const struct dvb_desc_network_name *) desc;
- dvb_log("| network name: '%s'", net->network_name);
+ dvb_loginfo("| network name: '%s'", net->network_name);
}
void dvb_desc_network_name_free(struct dvb_desc *desc)
diff --git a/lib/libdvbv5/descriptors/desc_partial_reception.c b/lib/libdvbv5/descriptors/desc_partial_reception.c
index 58d3fe6a..390080cd 100644
--- a/lib/libdvbv5/descriptors/desc_partial_reception.c
+++ b/lib/libdvbv5/descriptors/desc_partial_reception.c
@@ -19,12 +19,11 @@
* Described on ARIB STD-B10 as Partial reception descriptor
*/
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/desc_partial_reception.h>
#include <libdvbv5/dvb-fe.h>
#include <parse_string.h>
-void isdb_desc_partial_reception_init(struct dvb_v5_fe_parms *parms,
+int isdb_desc_partial_reception_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf, struct dvb_desc *desc)
{
struct isdb_desc_partial_reception *d = (void *)desc;
@@ -34,8 +33,8 @@ void isdb_desc_partial_reception_init(struct dvb_v5_fe_parms *parms,
d->partial_reception = malloc(d->length);
if (!d->partial_reception) {
- dvb_perror("Out of memory!");
- return;
+ dvb_logerr("%s: out of memory", __func__);
+ return -1;
}
memcpy(d->partial_reception, p, d->length);
@@ -44,6 +43,7 @@ void isdb_desc_partial_reception_init(struct dvb_v5_fe_parms *parms,
for (i = 0; i < len; i++)
bswap16(d->partial_reception[i].service_id);
+ return 0;
}
void isdb_desc_partial_reception_free(struct dvb_desc *desc)
@@ -62,6 +62,6 @@ void isdb_desc_partial_reception_print(struct dvb_v5_fe_parms *parms, const stru
len = d->length / sizeof(d->partial_reception);
for (i = 0; i < len; i++) {
- dvb_log("| service ID[%d] %d", i, d->partial_reception[i].service_id);
+ dvb_loginfo("| service ID[%d] %d", i, d->partial_reception[i].service_id);
}
}
diff --git a/lib/libdvbv5/descriptors/desc_sat.c b/lib/libdvbv5/descriptors/desc_sat.c
index 510de256..f7fb8f14 100644
--- a/lib/libdvbv5/descriptors/desc_sat.c
+++ b/lib/libdvbv5/descriptors/desc_sat.c
@@ -20,10 +20,9 @@
*/
#include <libdvbv5/desc_sat.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_sat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_sat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_sat *sat = (struct dvb_desc_sat *) desc;
/* copy from .length */
@@ -36,6 +35,8 @@ void dvb_desc_sat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct
sat->orbit = bcd(sat->orbit);
sat->frequency = bcd(sat->frequency) * 10;
sat->symbol_rate = bcd(sat->symbol_rate) * 100;
+
+ return 0;
}
void dvb_desc_sat_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
@@ -56,13 +57,13 @@ void dvb_desc_sat_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *de
pol = 'R';
break;
}
- dvb_log("| modulation_system %s", sat->modulation_system ? "DVB-S2" : "DVB-S");
- dvb_log("| frequency %d %c", sat->frequency, pol);
- dvb_log("| symbol_rate %d", sat->symbol_rate);
- dvb_log("| fec %d", sat->fec);
- dvb_log("| modulation_type %d", sat->modulation_type);
- dvb_log("| roll_off %d", sat->roll_off);
- dvb_log("| orbit %.1f %c", (float) sat->orbit / 10.0, sat->west_east ? 'E' : 'W');
+ dvb_loginfo("| modulation_system %s", sat->modulation_system ? "DVB-S2" : "DVB-S");
+ dvb_loginfo("| frequency %d %c", sat->frequency, pol);
+ dvb_loginfo("| symbol_rate %d", sat->symbol_rate);
+ dvb_loginfo("| fec %d", sat->fec);
+ dvb_loginfo("| modulation_type %d", sat->modulation_type);
+ dvb_loginfo("| roll_off %d", sat->roll_off);
+ dvb_loginfo("| orbit %.1f %c", (float) sat->orbit / 10.0, sat->west_east ? 'E' : 'W');
}
const unsigned dvbs_dvbc_dvbs_freq_inner[] = {
diff --git a/lib/libdvbv5/descriptors/desc_service.c b/lib/libdvbv5/descriptors/desc_service.c
index e73bf789..069317a5 100644
--- a/lib/libdvbv5/descriptors/desc_service.c
+++ b/lib/libdvbv5/descriptors/desc_service.c
@@ -20,17 +20,15 @@
*/
#include <libdvbv5/desc_service.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
#include <parse_string.h>
-void dvb_desc_service_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_service_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_service *service = (struct dvb_desc_service *) desc;
uint8_t len; /* the length of the string in the input data */
uint8_t len1, len2; /* the lenght of the output strings */
- /*hexdump(parms, "service desc: ", buf - 2, desc->length + 2);*/
service->service_type = buf[0];
buf++;
@@ -49,6 +47,7 @@ void dvb_desc_service_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, st
buf++;
parse_string(parms, &service->name, &service->name_emph, buf, len2, default_charset, output_charset);
buf += len;
+ return 0;
}
void dvb_desc_service_free(struct dvb_desc *desc)
@@ -63,8 +62,8 @@ void dvb_desc_service_free(struct dvb_desc *desc)
void dvb_desc_service_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_service *service = (const struct dvb_desc_service *) desc;
- dvb_log("| service type %d", service->service_type);
- dvb_log("| name '%s'", service->name);
- dvb_log("| provider '%s'", service->provider);
+ dvb_loginfo("| service type %d", service->service_type);
+ dvb_loginfo("| provider '%s'", service->provider);
+ dvb_loginfo("| name '%s'", service->name);
}
diff --git a/lib/libdvbv5/descriptors/desc_service_list.c b/lib/libdvbv5/descriptors/desc_service_list.c
index f3c5c799..4cd4018a 100644
--- a/lib/libdvbv5/descriptors/desc_service_list.c
+++ b/lib/libdvbv5/descriptors/desc_service_list.c
@@ -20,10 +20,11 @@
*/
#include <libdvbv5/desc_service_list.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_service_list_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+/* FIXME: implement */
+
+int dvb_desc_service_list_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
/*struct dvb_desc_service_list *slist = (struct dvb_desc_service_list *) desc;*/
@@ -38,7 +39,8 @@ void dvb_desc_service_list_init(struct dvb_v5_fe_parms *parms, const uint8_t *bu
/*}*/
/*return sizeof(struct dvb_desc_service_list) + slist->length + sizeof(struct dvb_desc_service_list_table);*/
- //FIXME: make linked list
+ /* FIXME: make linked list */
+ return 0;
}
void dvb_desc_service_list_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
@@ -46,8 +48,8 @@ void dvb_desc_service_list_print(struct dvb_v5_fe_parms *parms, const struct dvb
/*const struct dvb_desc_service_list *slist = (const struct dvb_desc_service_list *) desc;*/
/*int i = 0;*/
/*while(slist->services[i].service_id != 0) {*/
- /*dvb_log("| service id : '%d'", slist->services[i].service_id);*/
- /*dvb_log("| service type : '%d'", slist->services[i].service_type);*/
+ /*dvb_loginfo("| service id : '%d'", slist->services[i].service_id);*/
+ /*dvb_loginfo("| service type : '%d'", slist->services[i].service_type);*/
/*++i;*/
/*}*/
}
diff --git a/lib/libdvbv5/descriptors/desc_service_location.c b/lib/libdvbv5/descriptors/desc_service_location.c
index f386f57e..95cb3427 100644
--- a/lib/libdvbv5/descriptors/desc_service_location.c
+++ b/lib/libdvbv5/descriptors/desc_service_location.c
@@ -22,7 +22,7 @@
#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_service_location_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_service_location_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_service_location *service_location = (struct dvb_desc_service_location *) desc;
const uint8_t *endbuf = buf + desc->length;
@@ -32,7 +32,7 @@ void dvb_desc_service_location_init(struct dvb_v5_fe_parms *parms, const uint8_t
if (buf + size > endbuf) {
dvb_logerr("%s: short read %zd/%zd bytes", __FUNCTION__, endbuf - buf, size);
- return;
+ return -1;
}
memcpy(desc->data, buf, size);
@@ -40,12 +40,12 @@ void dvb_desc_service_location_init(struct dvb_v5_fe_parms *parms, const uint8_t
buf += size;
if (service_location->elements == 0)
- return;
+ return 0;
size = service_location->elements * sizeof(struct dvb_desc_service_location_element);
if (buf + size > endbuf) {
dvb_logerr("%s: short read %zd/%zd bytes", __FUNCTION__, endbuf - buf, size);
- return;
+ return -2;
}
service_location->element = malloc(size);
element = service_location->element;
@@ -56,6 +56,7 @@ void dvb_desc_service_location_init(struct dvb_v5_fe_parms *parms, const uint8_t
bswap16(element->bitfield);
element++;
}
+ return 0;
}
void dvb_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
@@ -64,11 +65,11 @@ void dvb_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct
struct dvb_desc_service_location_element *element = service_location->element;
int i;
- dvb_log("| pcr pid %d", service_location->pcr_pid);
- dvb_log("| streams:");
+ dvb_loginfo("| pcr pid %d", service_location->pcr_pid);
+ dvb_loginfo("| streams:");
for (i = 0; i < service_location->elements; i++)
- dvb_log("| pid %d, type %d: %s", element[i].elementary_pid, element[i].stream_type, element[i].language);
- dvb_log("| %d elements", service_location->elements);
+ dvb_loginfo("| pid %d, type %d: %s", element[i].elementary_pid, element[i].stream_type, element[i].language);
+ dvb_loginfo("| %d elements", service_location->elements);
}
void dvb_desc_service_location_free(struct dvb_desc *desc)
diff --git a/lib/libdvbv5/descriptors/desc_t2_delivery.c b/lib/libdvbv5/descriptors/desc_t2_delivery.c
index a5631643..498c7078 100644
--- a/lib/libdvbv5/descriptors/desc_t2_delivery.c
+++ b/lib/libdvbv5/descriptors/desc_t2_delivery.c
@@ -19,12 +19,11 @@
* Based on ETSI EN 300 468 V1.11.1 (2010-04)
*/
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/desc_extension.h>
#include <libdvbv5/desc_t2_delivery.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
+int dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf,
struct dvb_extension_descriptor *ext,
void *desc)
@@ -39,7 +38,7 @@ void dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
if (desc_len < len) {
dvb_logwarn("T2 delivery descriptor is too small");
- return;
+ return -1;
}
if (desc_len < len2) {
memcpy(p, buf, len);
@@ -48,7 +47,7 @@ void dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
if (desc_len != len)
dvb_logwarn("T2 delivery descriptor is truncated");
- return;
+ return -2;
}
memcpy(p, buf, len2);
p += len2;
@@ -67,8 +66,8 @@ void dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
d->centre_frequency = calloc(d->frequency_loop_length,
sizeof(*d->centre_frequency));
if (!d->centre_frequency) {
- dvb_perror("Out of memory");
- return;
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
}
memcpy(d->centre_frequency, p, sizeof(*d->centre_frequency) * d->frequency_loop_length);
@@ -82,13 +81,14 @@ void dvb_desc_t2_delivery_init(struct dvb_v5_fe_parms *parms,
d->subcell = calloc(d->subcel_info_loop_length, sizeof(*d->subcell));
if (!d->subcell) {
- dvb_perror("Out of memory");
- return;
+ dvb_logerr("%s: out of memory", __func__);
+ return -4;
}
memcpy(d->subcell, p, sizeof(*d->subcell) * d->subcel_info_loop_length);
for (i = 0; i < d->subcel_info_loop_length; i++)
bswap16(d->subcell[i].transposer_frequency);
+ return 0;
}
void dvb_desc_t2_delivery_print(struct dvb_v5_fe_parms *parms,
@@ -98,27 +98,26 @@ void dvb_desc_t2_delivery_print(struct dvb_v5_fe_parms *parms,
const struct dvb_desc_t2_delivery *d = desc;
int i;
- dvb_log("| DVB-T2 delivery");
- dvb_log("| plp_id %d", d->plp_id);
- dvb_log("| system_id %d", d->system_id);
+ dvb_loginfo("| plp_id %d", d->plp_id);
+ dvb_loginfo("| system_id %d", d->system_id);
if (ext->length - 1 <= 4)
return;
- dvb_log("| tfs_flag %d", d->tfs_flag);
- dvb_log("| other_frequency_flag %d", d->other_frequency_flag);
- dvb_log("| transmission_mode %d", d->transmission_mode);
- dvb_log("| guard_interval %d", d->guard_interval);
- dvb_log("| reserved %d", d->reserved);
- dvb_log("| bandwidth %d", d->bandwidth);
- dvb_log("| SISO MISO %d", d->SISO_MISO);
+ dvb_loginfo("| tfs_flag %d", d->tfs_flag);
+ dvb_loginfo("| other_frequency_flag %d", d->other_frequency_flag);
+ dvb_loginfo("| transmission_mode %d", d->transmission_mode);
+ dvb_loginfo("| guard_interval %d", d->guard_interval);
+ dvb_loginfo("| reserved %d", d->reserved);
+ dvb_loginfo("| bandwidth %d", d->bandwidth);
+ dvb_loginfo("| SISO MISO %d", d->SISO_MISO);
for (i = 0; i < d->frequency_loop_length; i++)
- dvb_log("| centre frequency[%d] %d", i, d->centre_frequency[i]);
+ dvb_loginfo("| centre frequency[%d] %d", i, d->centre_frequency[i]);
for (i = 0; i < d->subcel_info_loop_length; i++) {
- dvb_log("| cell_id_extension[%d] %d", i, d->subcell[i].cell_id_extension);
- dvb_log("| transposer frequency %d", d->subcell[i].transposer_frequency);
+ dvb_loginfo("| cell_id_extension[%d] %d", i, d->subcell[i].cell_id_extension);
+ dvb_loginfo("| transposer frequency %d", d->subcell[i].transposer_frequency);
}
}
diff --git a/lib/libdvbv5/descriptors/desc_terrestrial_delivery.c b/lib/libdvbv5/descriptors/desc_terrestrial_delivery.c
index d7ebe1dc..8df1a531 100644
--- a/lib/libdvbv5/descriptors/desc_terrestrial_delivery.c
+++ b/lib/libdvbv5/descriptors/desc_terrestrial_delivery.c
@@ -22,10 +22,9 @@
*/
#include <libdvbv5/desc_terrestrial_delivery.h>
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_desc_terrestrial_delivery_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
+int dvb_desc_terrestrial_delivery_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_terrestrial_delivery *tdel = (struct dvb_desc_terrestrial_delivery *) desc;
/* copy from .length */
@@ -34,25 +33,25 @@ void dvb_desc_terrestrial_delivery_init(struct dvb_v5_fe_parms *parms, const uin
tdel->length);
bswap32(tdel->centre_frequency);
bswap32(tdel->reserved_future_use2);
+ return 0;
}
void dvb_desc_terrestrial_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
{
const struct dvb_desc_terrestrial_delivery *tdel = (const struct dvb_desc_terrestrial_delivery *) desc;
- dvb_log("| terrestrial delivery");
- dvb_log("| length %d", tdel->length);
- dvb_log("| centre frequency %d", tdel->centre_frequency * 10);
- dvb_log("| mpe_fec_indicator %d", tdel->mpe_fec_indicator);
- dvb_log("| time_slice_indicator %d", tdel->time_slice_indicator);
- dvb_log("| priority %d", tdel->priority);
- dvb_log("| bandwidth %d", tdel->bandwidth);
- dvb_log("| code_rate_hp_stream %d", tdel->code_rate_hp_stream);
- dvb_log("| hierarchy_information %d", tdel->hierarchy_information);
- dvb_log("| constellation %d", tdel->constellation);
- dvb_log("| other_frequency_flag %d", tdel->other_frequency_flag);
- dvb_log("| transmission_mode %d", tdel->transmission_mode);
- dvb_log("| guard_interval %d", tdel->guard_interval);
- dvb_log("| code_rate_lp_stream %d", tdel->code_rate_lp_stream);
+ dvb_loginfo("| length %d", tdel->length);
+ dvb_loginfo("| centre frequency %d", tdel->centre_frequency * 10);
+ dvb_loginfo("| mpe_fec_indicator %d", tdel->mpe_fec_indicator);
+ dvb_loginfo("| time_slice_indicator %d", tdel->time_slice_indicator);
+ dvb_loginfo("| priority %d", tdel->priority);
+ dvb_loginfo("| bandwidth %d", tdel->bandwidth);
+ dvb_loginfo("| code_rate_hp_stream %d", tdel->code_rate_hp_stream);
+ dvb_loginfo("| hierarchy_information %d", tdel->hierarchy_information);
+ dvb_loginfo("| constellation %d", tdel->constellation);
+ dvb_loginfo("| other_frequency_flag %d", tdel->other_frequency_flag);
+ dvb_loginfo("| transmission_mode %d", tdel->transmission_mode);
+ dvb_loginfo("| guard_interval %d", tdel->guard_interval);
+ dvb_loginfo("| code_rate_lp_stream %d", tdel->code_rate_lp_stream);
}
const unsigned dvbt_bw[] = {
diff --git a/lib/libdvbv5/descriptors/desc_ts_info.c b/lib/libdvbv5/descriptors/desc_ts_info.c
index 02fcb821..75501af8 100644
--- a/lib/libdvbv5/descriptors/desc_ts_info.c
+++ b/lib/libdvbv5/descriptors/desc_ts_info.c
@@ -19,12 +19,11 @@
* Described on ARIB STD-B10 as TS information descriptor
*/
-#include <libdvbv5/descriptors.h>
#include <libdvbv5/desc_ts_info.h>
#include <libdvbv5/dvb-fe.h>
#include <parse_string.h>
-void dvb_desc_ts_info_init(struct dvb_v5_fe_parms *parms,
+int dvb_desc_ts_info_init(struct dvb_v5_fe_parms *parms,
const uint8_t *buf, struct dvb_desc *desc)
{
struct dvb_desc_ts_info *d = (void *)desc;
@@ -50,8 +49,10 @@ void dvb_desc_ts_info_init(struct dvb_v5_fe_parms *parms,
t = &d->transmission_type;
d->service_id = malloc(sizeof(*d->service_id) * t->num_of_service);
- if (!d->service_id)
- dvb_perror("Out of memory!");
+ if (!d->service_id) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -1;
+ }
memcpy(d->service_id, p, sizeof(*d->service_id) * t->num_of_service);
@@ -59,6 +60,7 @@ void dvb_desc_ts_info_init(struct dvb_v5_fe_parms *parms,
bswap16(d->service_id[i]);
p += sizeof(*d->service_id) * t->num_of_service;
+ return 0;
}
void dvb_desc_ts_info_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc)
@@ -69,14 +71,13 @@ void dvb_desc_ts_info_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc
t = &d->transmission_type;
- dvb_log("| TS Information");
- dvb_log("| remote key ID %d", d->remote_control_key_id);
- dvb_log("| name %s", d->ts_name);
- dvb_log("| emphasis name %s", d->ts_name_emph);
- dvb_log("| transmission type %s", d->ts_name_emph);
+ dvb_loginfo("| remote key ID %d", d->remote_control_key_id);
+ dvb_loginfo("| name %s", d->ts_name);
+ dvb_loginfo("| emphasis name %s", d->ts_name_emph);
+ dvb_loginfo("| transmission type %s", d->ts_name_emph);
for (i = 0; i < t->num_of_service; i++)
- dvb_log("| service ID[%d] %d", i, d->service_id[i]);
+ dvb_loginfo("| service ID[%d] %d", i, d->service_id[i]);
}
void dvb_desc_ts_info_free(struct dvb_desc *desc)
diff --git a/lib/libdvbv5/descriptors/eit.c b/lib/libdvbv5/descriptors/eit.c
deleted file mode 100644
index 1b64e291..00000000
--- a/lib/libdvbv5/descriptors/eit.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
- * Copyright (c) 2012 - Andre Roth <neolynx@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- *
- */
-
-#include <libdvbv5/eit.h>
-#include <libdvbv5/dvb-fe.h>
-
-void dvb_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length)
-{
- const uint8_t *p = buf;
- struct dvb_table_eit *eit = (struct dvb_table_eit *) table;
- struct dvb_table_eit_event **head;
-
- if (*table_length > 0) {
- memcpy(eit, p, sizeof(struct dvb_table_eit) - sizeof(eit->event));
-
- bswap16(eit->transport_id);
- bswap16(eit->network_id);
-
- /* find end of curent list */
- head = &eit->event;
- while (*head != NULL)
- head = &(*head)->next;
- } else {
- memcpy(eit, p, sizeof(struct dvb_table_eit) - sizeof(eit->event));
- *table_length = sizeof(struct dvb_table_eit);
-
- bswap16(eit->transport_id);
- bswap16(eit->network_id);
-
- eit->event = NULL;
- head = &eit->event;
- }
- p += sizeof(struct dvb_table_eit) - sizeof(eit->event);
-
- struct dvb_table_eit_event *last = NULL;
- while ((uint8_t *) p < buf + buflen - 4) {
- struct dvb_table_eit_event *event = (struct dvb_table_eit_event *) malloc(sizeof(struct dvb_table_eit_event));
- memcpy(event, p, sizeof(struct dvb_table_eit_event) -
- sizeof(event->descriptor) -
- sizeof(event->next) -
- sizeof(event->start) -
- sizeof(event->duration) -
- sizeof(event->service_id));
- p += sizeof(struct dvb_table_eit_event) -
- sizeof(event->descriptor) -
- sizeof(event->next) -
- sizeof(event->start) -
- sizeof(event->duration) -
- sizeof(event->service_id);
-
- bswap16(event->event_id);
- bswap16(event->bitfield1);
- bswap16(event->bitfield2);
- event->descriptor = NULL;
- event->next = NULL;
- dvb_time(event->dvbstart, &event->start);
- event->duration = bcd((uint32_t) event->dvbduration[0]) * 3600 +
- bcd((uint32_t) event->dvbduration[1]) * 60 +
- bcd((uint32_t) event->dvbduration[2]);
-
- event->service_id = eit->header.id;
-
- if(!*head)
- *head = event;
- if(last)
- last->next = event;
-
- /* get the descriptors for each program */
- struct dvb_desc **head_desc = &event->descriptor;
- dvb_parse_descriptors(parms, p, event->section_length, head_desc);
-
- p += event->section_length;
- last = event;
- }
-}
-
-void dvb_table_eit_free(struct dvb_table_eit *eit)
-{
- struct dvb_table_eit_event *event = eit->event;
- while (event) {
- dvb_free_descriptors((struct dvb_desc **) &event->descriptor);
- struct dvb_table_eit_event *tmp = event;
- event = event->next;
- free(tmp);
- }
- free(eit);
-}
-
-void dvb_table_eit_print(struct dvb_v5_fe_parms *parms, struct dvb_table_eit *eit)
-{
- dvb_log("EIT");
- dvb_table_header_print(parms, &eit->header);
- dvb_log("|- transport_id %d", eit->transport_id);
- dvb_log("|- network_id %d", eit->network_id);
- dvb_log("|- last segment %d", eit->last_segment);
- dvb_log("|- last table %d", eit->last_table_id);
- dvb_log("|\\ event_id");
- const struct dvb_table_eit_event *event = eit->event;
- uint16_t events = 0;
- while (event) {
- char start[255];
- strftime(start, sizeof(start), "%F %T", &event->start);
- dvb_log("|- %7d", event->event_id);
- dvb_log("| Service %d", event->service_id);
- dvb_log("| Start %s UTC", start);
- dvb_log("| Duration %dh %dm %ds", event->duration / 3600, (event->duration % 3600) / 60, event->duration % 60);
- dvb_log("| free CA mode %d", event->free_CA_mode);
- dvb_log("| running status %d: %s", event->running_status, dvb_eit_running_status_name[event->running_status] );
- dvb_print_descriptors(parms, event->descriptor);
- event = event->next;
- events++;
- }
- dvb_log("|_ %d events", events);
-}
-
-void dvb_time(const uint8_t data[5], struct tm *tm)
-{
- /* ETSI EN 300 468 V1.4.1 */
- int year, month, day, hour, min, sec;
- int k = 0;
- uint16_t mjd;
-
- mjd = *(uint16_t *) data;
- hour = bcd(data[2]);
- min = bcd(data[3]);
- sec = bcd(data[4]);
- year = ((mjd - 15078.2) / 365.25);
- month = ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001);
- day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001);
- if (month == 14 || month == 15) k = 1;
- year += k;
- month = month - 1 - k * 12;
-
- tm->tm_sec = sec;
- tm->tm_min = min;
- tm->tm_hour = hour;
- tm->tm_mday = day;
- tm->tm_mon = month - 1;
- tm->tm_year = year;
- tm->tm_isdst = 1; /* dst in effect, do not adjust */
- mktime( tm );
-}
-
-
-const char *dvb_eit_running_status_name[8] = {
- [0] = "Undefined",
- [1] = "Not running",
- [2] = "Starts in a few seconds",
- [3] = "Pausing",
- [4] = "Running",
- [5 ... 7] = "Reserved"
-};
diff --git a/lib/libdvbv5/descriptors/mgt.c b/lib/libdvbv5/descriptors/mgt.c
deleted file mode 100644
index ba57c842..00000000
--- a/lib/libdvbv5/descriptors/mgt.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2013 - Andre Roth <neolynx@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- *
- */
-
-#include <libdvbv5/mgt.h>
-#include <libdvbv5/dvb-fe.h>
-
-void atsc_table_mgt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length)
-{
- const uint8_t *p = buf, *endbuf = buf + buflen - 4; /* minus CRC */
- struct atsc_table_mgt *mgt = (struct atsc_table_mgt *) table;
- struct dvb_desc **head_desc;
- struct atsc_table_mgt_table **head;
- int i = 0;
- struct atsc_table_mgt_table *last = NULL;
- size_t size = offsetof(struct atsc_table_mgt, table);
-
- if (p + size > endbuf) {
- dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
- }
-
- if (*table_length > 0) {
- /* find end of curent lists */
- head_desc = &mgt->descriptor;
- while (*head_desc != NULL)
- head_desc = &(*head_desc)->next;
- head = &mgt->table;
- while (*head != NULL)
- head = &(*head)->next;
-
- /* FIXME: read current mgt->tables for loop below */
- } else {
- memcpy(table, p, size);
- *table_length = sizeof(struct atsc_table_mgt);
-
- bswap16(mgt->tables);
-
- mgt->descriptor = NULL;
- mgt->table = NULL;
- head_desc = &mgt->descriptor;
- head = &mgt->table;
- }
- p += size;
-
- while (i++ < mgt->tables && p < endbuf) {
- struct atsc_table_mgt_table *table;
-
- size = offsetof(struct atsc_table_mgt_table, descriptor);
- if (p + size > endbuf) {
- dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
- }
- table = (struct atsc_table_mgt_table *) malloc(sizeof(struct atsc_table_mgt_table));
- memcpy(table, p, size);
- p += size;
-
- bswap16(table->type);
- bswap16(table->bitfield);
- bswap16(table->bitfield2);
- bswap32(table->size);
- table->descriptor = NULL;
- table->next = NULL;
-
- if(!*head)
- *head = table;
- if(last)
- last->next = table;
-
- /* get the descriptors for each table */
- size = table->desc_length;
- if (p + size > endbuf) {
- dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
- }
- dvb_parse_descriptors(parms, p, size, &table->descriptor);
-
- p += size;
- last = table;
- }
- /* TODO: parse MGT descriptors here into head_desc */
-}
-
-void atsc_table_mgt_free(struct atsc_table_mgt *mgt)
-{
- struct atsc_table_mgt_table *table = mgt->table;
-
- dvb_free_descriptors((struct dvb_desc **) &mgt->descriptor);
- while(table) {
- struct atsc_table_mgt_table *tmp = table;
-
- dvb_free_descriptors((struct dvb_desc **) &table->descriptor);
- table = table->next;
- free(tmp);
- }
- free(mgt);
-}
-
-void atsc_table_mgt_print(struct dvb_v5_fe_parms *parms, struct atsc_table_mgt *mgt)
-{
- const struct atsc_table_mgt_table *table = mgt->table;
- uint16_t tables = 0;
-
- dvb_log("MGT");
- atsc_table_header_print(parms, &mgt->header);
- dvb_log("| tables %d", mgt->tables);
- while(table) {
- dvb_log("|- type %04x %d", table->type, table->pid);
- dvb_log("| one %d", table->one);
- dvb_log("| one2 %d", table->one2);
- dvb_log("| type version %d", table->type_version);
- dvb_log("| size %d", table->size);
- dvb_log("| one3 %d", table->one3);
- dvb_log("| desc_length %d", table->desc_length);
- dvb_print_descriptors(parms, table->descriptor);
- table = table->next;
- tables++;
- }
- dvb_log("|_ %d tables", tables);
-}
-
diff --git a/lib/libdvbv5/descriptors/pat.c b/lib/libdvbv5/descriptors/pat.c
deleted file mode 100644
index 20007291..00000000
--- a/lib/libdvbv5/descriptors/pat.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
- * Copyright (c) 2012 - Andre Roth <neolynx@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- *
- */
-
-#include <libdvbv5/pat.h>
-#include <libdvbv5/descriptors.h>
-#include <libdvbv5/dvb-fe.h>
-
-void dvb_table_pat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
- ssize_t buflen, uint8_t *table, ssize_t *table_length)
-{
- struct dvb_table_pat *pat = (void *)table;
- struct dvb_table_pat_program **head = &pat->program;
- const uint8_t *p = buf, *endbuf = buf + buflen - 4;
- size_t size;
-
- if (*table_length > 0) {
- /* find end of current list */
- while (*head != NULL)
- head = &(*head)->next;
- } else {
- size = offsetof(struct dvb_table_pat, programs);
- if (p + size > endbuf) {
- dvb_logerr("PAT table was truncated. Need %zu bytes, but has only %zu.",
- size, buflen);
- return;
- }
- memcpy(table, buf, size);
- p += size;
- pat->programs = 0;
- pat->program = NULL;
- }
- *table_length = sizeof(struct dvb_table_pat_program);
-
- size = offsetof(struct dvb_table_pat_program, next);
- while (p + size <= endbuf) {
- struct dvb_table_pat_program *pgm;
-
- pgm = malloc(sizeof(struct dvb_table_pat_program));
- if (!pgm) {
- dvb_perror("Out of memory");
- return;
- }
-
- memcpy(pgm, p, size);
- p += size;
-
- bswap16(pgm->service_id);
- bswap16(pgm->bitfield);
- pat->programs++;
-
- pgm->next = NULL;
-
- *head = pgm;
- head = &(*head)->next;
- }
- if (endbuf - p)
- dvb_logerr("PAT table has %zu spurious bytes at the end.",
- endbuf - p);
-}
-
-void dvb_table_pat_free(struct dvb_table_pat *pat)
-{
- struct dvb_table_pat_program *pgm = pat->program;
-
- while (pgm) {
- struct dvb_table_pat_program *tmp = pgm;
- pgm = pgm->next;
- free(tmp);
- }
- free(pat);
-}
-
-void dvb_table_pat_print(struct dvb_v5_fe_parms *parms, struct dvb_table_pat *pat)
-{
- struct dvb_table_pat_program *pgm = pat->program;
-
- dvb_log("PAT");
- dvb_table_header_print(parms, &pat->header);
- dvb_log("|\\ program service (%d programs)", pat->programs);
-
- while (pgm) {
- dvb_log("|- %7d %7d", pgm->pid, pgm->service_id);
- pgm = pgm->next;
- }
-}
-
diff --git a/lib/libdvbv5/descriptors/sdt.c b/lib/libdvbv5/descriptors/sdt.c
deleted file mode 100644
index 5e0c924d..00000000
--- a/lib/libdvbv5/descriptors/sdt.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
- * Copyright (c) 2012 - Andre Roth <neolynx@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- *
- */
-
-#include <libdvbv5/sdt.h>
-#include <libdvbv5/dvb-fe.h>
-
-void dvb_table_sdt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
- ssize_t buflen, uint8_t *table, ssize_t *table_length)
-{
- const uint8_t *p = buf, *endbuf = buf + buflen - 4;
- struct dvb_table_sdt *sdt = (void *)table;
- struct dvb_table_sdt_service **head = &sdt->service;
- size_t size = offsetof(struct dvb_table_sdt, service);
-
- if (*table_length > 0) {
- /* find end of curent list */
- while (*head != NULL)
- head = &(*head)->next;
- } else {
- if (p + size > endbuf) {
- dvb_logerr("SDT table was truncated. Need %zu bytes, but has only %zu.",
- size, buflen);
- return;
- }
- memcpy(sdt, p, size);
- *table_length = sizeof(struct dvb_table_sdt);
-
- bswap16(sdt->network_id);
-
- sdt->service = NULL;
- }
- p += size;
-
- size = offsetof(struct dvb_table_sdt_service, descriptor);
- while (p + size <= endbuf) {
- struct dvb_table_sdt_service *service;
-
- service = malloc(sizeof(struct dvb_table_sdt_service));
-
- memcpy(service, p, size);
- p += size;
-
- bswap16(service->service_id);
- bswap16(service->bitfield);
- service->descriptor = NULL;
- service->next = NULL;
-
- *head = service;
- head = &(*head)->next;
-
- /* get the descriptors for each program */
- dvb_parse_descriptors(parms, p, service->section_length,
- &service->descriptor);
-
- p += service->section_length;
- }
- if (endbuf - p)
- dvb_logerr("PAT table has %zu spurious bytes at the end.",
- endbuf - p);
-}
-
-void dvb_table_sdt_free(struct dvb_table_sdt *sdt)
-{
- struct dvb_table_sdt_service *service = sdt->service;
- while(service) {
- dvb_free_descriptors((struct dvb_desc **) &service->descriptor);
- struct dvb_table_sdt_service *tmp = service;
- service = service->next;
- free(tmp);
- }
- free(sdt);
-}
-
-void dvb_table_sdt_print(struct dvb_v5_fe_parms *parms, struct dvb_table_sdt *sdt)
-{
- dvb_log("SDT");
- dvb_table_header_print(parms, &sdt->header);
- dvb_log("|- network_id %d", sdt->network_id);
- dvb_log("|\\ service_id");
- const struct dvb_table_sdt_service *service = sdt->service;
- uint16_t services = 0;
- while(service) {
- dvb_log("|- %7d", service->service_id);
- dvb_log("| EIT schedule %d", service->EIT_schedule);
- dvb_log("| EIT present following %d", service->EIT_present_following);
- dvb_log("| free CA mode %d", service->free_CA_mode);
- dvb_log("| running status %d", service->running_status);
- dvb_print_descriptors(parms, service->descriptor);
- service = service->next;
- services++;
- }
- dvb_log("|_ %d services", services);
-}
-
diff --git a/lib/libdvbv5/dvb-fe.c b/lib/libdvbv5/dvb-fe.c
index 0841546f..013edd64 100644
--- a/lib/libdvbv5/dvb-fe.c
+++ b/lib/libdvbv5/dvb-fe.c
@@ -629,15 +629,11 @@ int dvb_fe_set_parms(struct dvb_v5_fe_parms *parms)
struct dvb_frontend_parameters v3_parms;
uint32_t bw;
- if (dvb_fe_is_satellite(tmp_parms.current_sys))
- dvb_sat_set_parms(&tmp_parms);
-
- /* Filter out any user DTV_foo property such as DTV_POLARIZATION */
- tmp_parms.n_props = dvb_copy_fe_props(tmp_parms.dvb_prop, tmp_parms.n_props, tmp_parms.dvb_prop);
-
if (parms->lna != LNA_AUTO && !parms->legacy_fe) {
+ struct dvb_v5_fe_parms tmp_lna_parms;
+
memset(&prop, 0, sizeof(prop));
- prop.props = tmp_parms.dvb_prop;
+ prop.props = tmp_lna_parms.dvb_prop;
prop.props[0].cmd = DTV_LNA;
prop.props[0].u.data = parms->lna;
@@ -649,6 +645,12 @@ int dvb_fe_set_parms(struct dvb_v5_fe_parms *parms)
dvb_logdbg("LNA is %s", parms->lna ? "ON" : "OFF");
}
+ if (dvb_fe_is_satellite(tmp_parms.current_sys))
+ dvb_sat_set_parms(&tmp_parms);
+
+ /* Filter out any user DTV_foo property such as DTV_POLARIZATION */
+ tmp_parms.n_props = dvb_copy_fe_props(tmp_parms.dvb_prop, tmp_parms.n_props, tmp_parms.dvb_prop);
+
memset(&prop, 0, sizeof(prop));
prop.props = tmp_parms.dvb_prop;
prop.num = tmp_parms.n_props;
diff --git a/lib/libdvbv5/dvb-file.c b/lib/libdvbv5/dvb-file.c
index 84ff725d..8df348eb 100644
--- a/lib/libdvbv5/dvb-file.c
+++ b/lib/libdvbv5/dvb-file.c
@@ -380,12 +380,15 @@ int write_format_oneline(const char *fname,
data = entry->props[j].u.data;
if (table->prop == DTV_BANDWIDTH_HZ) {
- if (data < ARRAY_SIZE(fe_bandwidth_name))
- data = fe_bandwidth_name[data];
- else
+ for (j = 0; j < ARRAY_SIZE(fe_bandwidth_name); j++) {
+ if (fe_bandwidth_name[j] == data) {
+ data = j;
+ break;
+ }
+ }
+ if (j == ARRAY_SIZE(fe_bandwidth_name))
data = BANDWIDTH_AUTO;
}
-
if (data >= table->size) {
sprintf(err_msg,
"value not supported");
@@ -953,7 +956,8 @@ static int get_program_and_store(struct dvb_v5_fe_parms *parms,
int get_detected, int get_nit)
{
struct dvb_entry *entry;
- int i, j, found = 0;
+ int i, j, r, found = 0;
+ uint32_t freq = 0;
/* Go to the last entry */
@@ -992,7 +996,6 @@ static int get_program_and_store(struct dvb_v5_fe_parms *parms,
}
/* Initialize data */
- entry->channel = channel;
entry->service_id = service_id;
entry->vchannel = vchannel;
entry->sat_number = parms->sat_number;
@@ -1018,9 +1021,21 @@ static int get_program_and_store(struct dvb_v5_fe_parms *parms,
for (j = 0; j < parms->n_props; j++) {
entry->props[j].cmd = parms->dvb_prop[j].cmd;
entry->props[j].u.data = parms->dvb_prop[j].u.data;
+
+ if (!channel && entry->props[j].cmd == DTV_FREQUENCY)
+ freq = parms->dvb_prop[j].u.data;
}
entry->n_props = parms->n_props;
+ if (!channel) {
+ r = asprintf(&channel, "%.2fMHz#%d", freq/1000000., service_id);
+ if (r < 0)
+ dvb_perror("asprintf");
+ if (parms->verbose)
+ dvb_log("Storing as: '%s'", channel);
+ }
+ entry->channel = channel;
+
if (get_nit)
dvb_update_transponders(parms, dvb_scan_handler,
dvb_file->first_entry,
@@ -1096,8 +1111,25 @@ int store_dvb_channel(struct dvb_file **dvb_file,
if (!dvb_scan_handler->sdt) {
- dvb_logerr("no SDT table - can't store channels");
- return -1;
+ int i;
+
+ dvb_logerr("no SDT table - storing channels without their names");
+ for (i = 0; i < dvb_scan_handler->num_program; i++) {
+ unsigned service_id;
+
+ if (!dvb_scan_handler->program[i].pmt)
+ continue;
+
+ service_id = dvb_scan_handler->program[i].pat_pgm->service_id;
+
+ rc = get_program_and_store(parms, *dvb_file, dvb_scan_handler,
+ service_id, NULL, NULL,
+ get_detected, get_nit);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
}
dvb_sdt_service_foreach(service, dvb_scan_handler->sdt) {
char *channel = NULL;
diff --git a/lib/libdvbv5/dvb-scan.c b/lib/libdvbv5/dvb-scan.c
index d4490fbf..94cf98ec 100644
--- a/lib/libdvbv5/dvb-scan.c
+++ b/lib/libdvbv5/dvb-scan.c
@@ -42,7 +42,7 @@
#include <libdvbv5/dvb-frontend.h>
#include <libdvbv5/descriptors.h>
#include "parse_string.h"
-#include "crc32.h"
+#include <libdvbv5/crc32.h>
#include <libdvbv5/dvb-fe.h>
#include <libdvbv5/dvb-file.h>
#include <libdvbv5/dvb-scan.h>
@@ -85,7 +85,7 @@ static int poll(struct dvb_v5_fe_parms *parms, int fd, unsigned int seconds)
}
int dvb_read_section(struct dvb_v5_fe_parms *parms, int dmx_fd,
- unsigned char tid, uint16_t pid, uint8_t **table,
+ unsigned char tid, uint16_t pid, void **table,
unsigned timeout)
{
return dvb_read_section_with_id(parms, dmx_fd, tid, pid, -1, table, timeout);
@@ -124,118 +124,111 @@ static int is_all_bits_set(int nr, unsigned long *addr)
}
-struct tid_pid_table_priv {
+struct dvb_table_filter_priv {
int last_section;
unsigned long is_read_bits[BITS_TO_LONGS(256)];
- int done;
-};
-struct tid_pid_table {
- /* Input data */
- unsigned char tid;
- uint16_t pid;
- int ts_id;
- uint8_t **table;
-
- /*
- * Private temp data used by dvb_read_sections().
- * Should not be filled outside dvb-scan.c, as they'll be
- * overrided
- */
- void *priv;
+ /* section gaps and multiple ts_id handling */
+ int first_ts_id;
+ int first_section;
+ int done;
};
static int dvb_parse_section_alloc(struct dvb_v5_fe_parms *parms,
- struct tid_pid_table *sect)
+ struct dvb_table_filter *sect)
{
- struct tid_pid_table_priv *priv;
+ struct dvb_table_filter_priv *priv;
if (!sect->table) {
- dvb_logerr("table memory pointer not filled");
+ dvb_logerr("%s: table memory pointer not filled",
+ __func__);
return -4;
}
*sect->table = NULL;
- priv = calloc(sizeof(struct tid_pid_table_priv), 1);
+ priv = calloc(sizeof(struct dvb_table_filter_priv), 1);
if (!priv) {
- dvb_perror("Out of memory");
+ dvb_logerr("%s: out of memory", __func__);
return -1;
}
priv->last_section = -1;
+ priv->first_section = -1;
+ priv->first_ts_id = -1;
sect->priv = priv;
return 0;
}
-static void dvb_parse_section_free(struct tid_pid_table *sect)
+void dvb_table_filter_free(struct dvb_table_filter *sect)
{
- if (sect->priv)
+ if (sect->priv) {
free(sect->priv);
+ sect->priv = NULL;
+ }
}
static int dvb_parse_section(struct dvb_v5_fe_parms *parms,
- struct tid_pid_table *sect,
- uint8_t *buf, ssize_t buf_length)
+ struct dvb_table_filter *sect,
+ const uint8_t *buf, ssize_t buf_length)
{
- struct dvb_table_header *h;
- struct tid_pid_table_priv *priv;
-
- uint8_t *tbl = NULL;
+ struct dvb_table_header h;
+ struct dvb_table_filter_priv *priv;
unsigned char tid;
- ssize_t table_length = 0;
- h = (struct dvb_table_header *)buf;
- dvb_table_header_init(h);
+ memcpy(&h, buf, sizeof(struct dvb_table_header));
+ dvb_table_header_init(&h);
if (parms->verbose)
- dvb_log("Received table 0x%02x, TS ID 0x%04x, section number 0x%02x, last section 0x%02x",
- h->table_id, h->id, h->section_id, h->last_section);
+ dvb_log("%s: received table 0x%02x, TS ID 0x%04x, section %d/%d",
+ __func__, h.table_id, h.id, h.section_id, h.last_section);
- if (sect->tid != h->table_id) {
- dvb_logdbg("Something's wrong: couldn't match ID %d at the active section filters",
- h->table_id);
+ if (sect->tid != h.table_id) {
+ dvb_logdbg("%s: couldn't match ID %d at the active section filters",
+ __func__, h.table_id);
return -1;
}
priv = sect->priv;
- tid = h->table_id;
-
- /* Check if the table was already parsed */
+ tid = h.table_id;
+ if (priv->first_ts_id < 0)
+ priv->first_ts_id = h.id;
+ if (priv->first_section < 0)
+ priv->first_section = h.section_id;
if (priv->last_section < 0)
- priv->last_section = h->last_section;
- else if (test_bit(h->section_id, priv->is_read_bits))
- return 0;
+ priv->last_section = h.last_section;
+ else { /* Check if the table was already parsed, but not on first pass */
+ if (!sect->allow_section_gaps && sect->ts_id == -1) {
+ if (test_bit(h.section_id, priv->is_read_bits))
+ return 0;
+ } else if (priv->first_ts_id == h.id && priv->first_section == h.section_id) {
+ /* tables like EIT can increment sections by gaps > 1.
+ * in this case, reading is done when a already read
+ * table is reached. */
+ dvb_log("%s: section repeated, reading done", __func__);
+ priv->done = 1;
+ return 1;
+ }
+ }
+
/* search for an specific TS ID */
if (sect->ts_id != -1) {
- if (h->id != sect->ts_id)
+ if (h.id != sect->ts_id)
return 0;
}
/* handle the sections */
- set_bit(h->section_id, priv->is_read_bits);
-
- tbl = *sect->table;
- if (!tbl) {
- if (!dvb_table_initializers[tid].size) {
- dvb_logerr("dvb_read_section: no table size for table %d",
- tid);
- return -1;
- }
+ if (!sect->allow_section_gaps && sect->ts_id == -1)
+ set_bit(h.section_id, priv->is_read_bits);
- tbl = calloc(dvb_table_initializers[tid].size, 1);
- }
-
- if (dvb_table_initializers[tid].init)
- dvb_table_initializers[tid].init(parms, buf, buf_length,
- tbl, &table_length);
+ if (dvb_table_initializers[tid])
+ dvb_table_initializers[tid](parms, buf, buf_length - DVB_CRC_SIZE,
+ sect->table);
else
- dvb_logerr("dvb_read_section: no initializer for table %d",
- tid);
-
- /* Store the table */
- *sect->table = tbl;
+ dvb_logerr("%s: no initializer for table %d",
+ __func__, tid);
- if (is_all_bits_set(priv->last_section, priv->is_read_bits))
+ if (!sect->allow_section_gaps && sect->ts_id == -1 &&
+ is_all_bits_set(priv->last_section, priv->is_read_bits))
priv->done = 1;
if (!priv->done)
@@ -245,16 +238,14 @@ static int dvb_parse_section(struct dvb_v5_fe_parms *parms,
return 1;
}
-static int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
- struct tid_pid_table *sect,
+int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
+ struct dvb_table_filter *sect,
unsigned timeout)
{
int ret;
uint8_t *buf = NULL;
uint8_t mask = 0xff;
- /* FIXME: verify if all requested tables are known */
-
ret = dvb_parse_section_alloc(parms, sect);
if (ret < 0)
return ret;
@@ -266,14 +257,14 @@ static int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
return -1;
}
if (parms->verbose)
- dvb_log("Waiting for table ID %d, program ID %d",
- sect->tid, sect->pid);
+ dvb_log("%s: waiting for table ID 0x%02x, program ID 0x%02x",
+ __func__, sect->tid, sect->pid);
buf = calloc(DVB_MAX_PAYLOAD_PACKET_SIZE, 1);
if (!buf) {
- dvb_perror("Out of memory");
+ dvb_logerr("%s: out of memory", __func__);
dvb_dmx_stop(dmx_fd);
- dvb_parse_section_free(sect);
+ dvb_table_filter_free(sect);
return -1;
}
@@ -292,14 +283,14 @@ static int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
break;
}
if (available <= 0) {
- dvb_logerr("dvb_read_section: no data read on section filter");
+ dvb_logerr("%s: no data read on section filter", __func__);
ret = -1;
break;
}
buf_length = read(dmx_fd, buf, DVB_MAX_PAYLOAD_PACKET_SIZE);
if (!buf_length) {
- dvb_logerr("dvb_read_section: buf returned an empty buffer");
+ dvb_logerr("%s: buf returned an empty buffer", __func__);
ret = -1;
break;
}
@@ -311,7 +302,7 @@ static int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
crc = crc32(buf, buf_length, 0xFFFFFFFF);
if (crc != 0) {
- dvb_logerr("dvb_read_section: crc error");
+ dvb_logerr("%s: crc error", __func__);
ret = -3;
break;
}
@@ -320,7 +311,7 @@ static int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
} while (!ret);
free(buf);
dvb_dmx_stop(dmx_fd);
- dvb_parse_section_free(sect);
+ dvb_table_filter_free(sect);
if (ret > 0)
ret = 0;
@@ -331,14 +322,15 @@ static int dvb_read_sections(struct dvb_v5_fe_parms *parms, int dmx_fd,
int dvb_read_section_with_id(struct dvb_v5_fe_parms *parms, int dmx_fd,
unsigned char tid, uint16_t pid,
int ts_id,
- uint8_t **table, unsigned timeout)
+ void **table, unsigned timeout)
{
- struct tid_pid_table tab;
+ struct dvb_table_filter tab;
tab.tid = tid;
tab.pid = pid;
tab.ts_id = ts_id;
tab.table = table;
+ tab.allow_section_gaps = 0;
return dvb_read_sections(parms, dmx_fd, &tab, timeout);
}
@@ -446,7 +438,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
/* PAT table */
rc = dvb_read_section(parms, dmx_fd,
DVB_TABLE_PAT, DVB_TABLE_PAT_PID,
- (uint8_t **) &dvb_scan_handler->pat,
+ (void **)&dvb_scan_handler->pat,
pat_pmt_time * timeout_multiply);
if (parms->abort)
return dvb_scan_handler;
@@ -462,7 +454,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
if (atsc_filter) {
rc = dvb_read_section(parms, dmx_fd,
atsc_filter, ATSC_TABLE_VCT_PID,
- (uint8_t **)&dvb_scan_handler->vct,
+ (void **)&dvb_scan_handler->vct,
vct_time * timeout_multiply);
if (parms->abort)
return dvb_scan_handler;
@@ -481,15 +473,17 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
if (!program->service_id) {
if (parms->verbose)
- dvb_log("Network PID: 0x%02x", program->pid);
+ dvb_log("Program #%d is network PID: 0x%04x",
+ num_pmt, program->pid);
num_pmt++;
continue;
}
if (parms->verbose)
- dvb_log("Program ID %d", program->pid);
+ dvb_log("Program #%d ID 0x%04x, service ID 0x%04x",
+ num_pmt, program->pid, program->service_id);
rc = dvb_read_section(parms, dmx_fd,
DVB_TABLE_PMT, program->pid,
- (uint8_t **)&dvb_scan_handler->program[num_pmt].pmt,
+ (void **)&dvb_scan_handler->program[num_pmt].pmt,
pat_pmt_time * timeout_multiply);
if (parms->abort) {
dvb_scan_handler->num_program = num_pmt + 1;
@@ -510,7 +504,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
/* NIT table */
rc = dvb_read_section(parms, dmx_fd,
DVB_TABLE_NIT, DVB_TABLE_NIT_PID,
- (uint8_t **)&dvb_scan_handler->nit,
+ (void **)&dvb_scan_handler->nit,
nit_time * timeout_multiply);
if (parms->abort)
return dvb_scan_handler;
@@ -523,7 +517,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
if (!dvb_scan_handler->vct || other_nit) {
rc = dvb_read_section(parms, dmx_fd,
DVB_TABLE_SDT, DVB_TABLE_SDT_PID,
- (uint8_t **)&dvb_scan_handler->sdt,
+ (void **)&dvb_scan_handler->sdt,
sdt_time * timeout_multiply);
if (parms->abort)
return dvb_scan_handler;
@@ -539,7 +533,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
dvb_log("Parsing other NIT/SDT");
rc = dvb_read_section(parms, dmx_fd,
DVB_TABLE_NIT2, DVB_TABLE_NIT_PID,
- (uint8_t **)&dvb_scan_handler->nit,
+ (void **)&dvb_scan_handler->nit,
nit_time * timeout_multiply);
if (parms->abort)
return dvb_scan_handler;
@@ -550,7 +544,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *parms,
rc = dvb_read_section(parms, dmx_fd,
DVB_TABLE_SDT2, DVB_TABLE_SDT_PID,
- (uint8_t **)&dvb_scan_handler->sdt,
+ (void **)&dvb_scan_handler->sdt,
sdt_time * timeout_multiply);
if (parms->abort)
return dvb_scan_handler;
@@ -749,7 +743,7 @@ struct dvb_entry *dvb_scan_add_entry(struct dvb_v5_fe_parms *parms,
n, freq);
entry->next = new_entry;
new_entry->next = NULL;
- return entry;
+ return new_entry;
}
}
@@ -821,10 +815,8 @@ static void add_update_nit_isdbt(struct dvb_table_nit *nit,
}
for (i = 0; i < d->num_freqs; i++) {
- uint32_t frq = d->frequency[i] * 1000000l / 7;
-
new = dvb_scan_add_entry(tr->parms, tr->first_entry, tr->entry,
- frq, tr->shift, tr->pol);
+ d->frequency[i], tr->shift, tr->pol);
if (!new)
return;
}
diff --git a/lib/libdvbv5/gen_dvb_structs.pl b/lib/libdvbv5/gen_dvb_structs.pl
index df697005..1fab0578 100755
--- a/lib/libdvbv5/gen_dvb_structs.pl
+++ b/lib/libdvbv5/gen_dvb_structs.pl
@@ -468,7 +468,7 @@ sub output_arrays($$$$$)
}
}
-my $fe_file = "$dir/uapi/linux/dvb/frontend.h";
+my $fe_file = "$dir/linux/dvb/frontend.h";
copy $fe_file, "../include/dvb-frontend.h";
@@ -510,7 +510,7 @@ print OUT <<EOF;
*/
#include <stddef.h>
-#include <libdvbv5/dvb-v5.h>
+#include "dvb-v5.h"
EOF
output_arrays ("fe_caps_name", \%fe_caps, "unsigned", 1, 0);
diff --git a/lib/libdvbv5/descriptors/atsc_eit.c b/lib/libdvbv5/tables/atsc_eit.c
index 86a7b119..6a7c4d25 100644
--- a/lib/libdvbv5/descriptors/atsc_eit.c
+++ b/lib/libdvbv5/tables/atsc_eit.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 - Andre Roth <neolynx@gmail.com>
+ * Copyright (c) 2013-2014 - Andre Roth <neolynx@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,38 +19,47 @@
*/
#include <libdvbv5/atsc_eit.h>
+#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-void atsc_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length)
+ssize_t atsc_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct atsc_table_eit **table)
{
- const uint8_t *p = buf, *endbuf = buf + buflen - 4; /* minus CRC */;
- struct atsc_table_eit *eit = (struct atsc_table_eit *) table;
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct atsc_table_eit *eit;
struct atsc_table_eit_event **head;
+ size_t size;
int i = 0;
- struct atsc_table_eit_event *last = NULL;
- size_t size = offsetof(struct atsc_table_eit, event);
+ size = offsetof(struct atsc_table_eit, event);
if (p + size > endbuf) {
dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
+ endbuf - p, size);
+ return -1;
}
- if (*table_length > 0) {
- memcpy(eit, p, size);
-
- /* find end of curent list */
- head = &eit->event;
- while (*head != NULL)
- head = &(*head)->next;
- } else {
- memcpy(eit, p, size);
- *table_length = sizeof(struct atsc_table_eit);
+ if (buf[0] != ATSC_TABLE_EIT) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x",
+ __func__, buf[0], ATSC_TABLE_EIT);
+ return -2;
+ }
- eit->event = NULL;
- head = &eit->event;
+ if (!*table) {
+ *table = calloc(sizeof(struct atsc_table_eit), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
+ }
}
+ eit = *table;
+ memcpy(eit, p, size);
p += size;
+ dvb_table_header_init(&eit->header);
+
+ /* find end of curent list */
+ head = &eit->event;
+ while (*head != NULL)
+ head = &(*head)->next;
while (i++ < eit->events && p < endbuf) {
struct atsc_table_eit_event *event;
@@ -59,10 +68,14 @@ void atsc_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssiz
size = offsetof(struct atsc_table_eit_event, descriptor);
if (p + size > endbuf) {
dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
+ endbuf - p, size);
+ return -4;
}
event = (struct atsc_table_eit_event *) malloc(sizeof(struct atsc_table_eit_event));
+ if (!event) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -5;
+ }
memcpy(event, p, size);
p += size;
@@ -74,26 +87,24 @@ void atsc_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssiz
atsc_time(event->start_time, &event->start);
event->source_id = eit->header.id;
+ *head = event;
+ head = &(*head)->next;
+
size = event->title_length - 1;
if (p + size > endbuf) {
dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
+ endbuf - p, size);
+ return -6;
}
/* TODO: parse title */
p += size;
- if(!*head)
- *head = event;
- if(last)
- last->next = event;
-
/* get the descriptors for each program */
size = sizeof(union atsc_table_eit_desc_length);
if (p + size > endbuf) {
dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
+ endbuf - p, size);
+ return -7;
}
memcpy(&dl, p, size);
p += size;
@@ -102,14 +113,18 @@ void atsc_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssiz
size = dl.desc_length;
if (p + size > endbuf) {
dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
+ endbuf - p, size);
+ return -8;
+ }
+ if (dvb_desc_parse(parms, p, size,
+ &event->descriptor) != 0 ) {
+ return -9;
}
- dvb_parse_descriptors(parms, p, size, &event->descriptor);
p += size;
- last = event;
}
+
+ return p - buf;
}
void atsc_table_eit_free(struct atsc_table_eit *eit)
@@ -119,7 +134,7 @@ void atsc_table_eit_free(struct atsc_table_eit *eit)
while (event) {
struct atsc_table_eit_event *tmp = event;
- dvb_free_descriptors((struct dvb_desc **) &event->descriptor);
+ dvb_desc_free((struct dvb_desc **) &event->descriptor);
event = event->next;
free(tmp);
}
@@ -128,8 +143,8 @@ void atsc_table_eit_free(struct atsc_table_eit *eit)
void atsc_table_eit_print(struct dvb_v5_fe_parms *parms, struct atsc_table_eit *eit)
{
- dvb_log("EIT");
- atsc_table_header_print(parms, &eit->header);
+ dvb_loginfo("EIT");
+ ATSC_TABLE_HEADER_PRINT(parms, eit);
const struct atsc_table_eit_event *event = eit->event;
uint16_t events = 0;
@@ -137,18 +152,18 @@ void atsc_table_eit_print(struct dvb_v5_fe_parms *parms, struct atsc_table_eit *
char start[255];
strftime(start, sizeof(start), "%F %T", &event->start);
- dvb_log("|- event %7d", event->event_id);
- dvb_log("| Source %d", event->source_id);
- dvb_log("| Starttime %d", event->start_time);
- dvb_log("| Start %s UTC", start);
- dvb_log("| Duration %dh %dm %ds", event->duration / 3600, (event->duration % 3600) / 60, event->duration % 60);
- dvb_log("| ETM %d", event->etm);
- dvb_log("| title length %d", event->title_length);
- dvb_print_descriptors(parms, event->descriptor);
+ dvb_loginfo("|- event %7d", event->event_id);
+ dvb_loginfo("| Source %d", event->source_id);
+ dvb_loginfo("| Starttime %d", event->start_time);
+ dvb_loginfo("| Start %s UTC", start);
+ dvb_loginfo("| Duration %dh %dm %ds", event->duration / 3600, (event->duration % 3600) / 60, event->duration % 60);
+ dvb_loginfo("| ETM %d", event->etm);
+ dvb_loginfo("| title length %d", event->title_length);
+ dvb_desc_print(parms, event->descriptor);
event = event->next;
events++;
}
- dvb_log("|_ %d events", events);
+ dvb_loginfo("|_ %d events", events);
}
void atsc_time(const uint32_t start_time, struct tm *tm)
diff --git a/lib/libdvbv5/tables/cat.c b/lib/libdvbv5/tables/cat.c
new file mode 100644
index 00000000..49983070
--- /dev/null
+++ b/lib/libdvbv5/tables/cat.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013-2014 - Andre Roth <neolynx@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ */
+
+#include <libdvbv5/cat.h>
+#include <libdvbv5/descriptors.h>
+#include <libdvbv5/dvb-fe.h>
+
+ssize_t dvb_table_cat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct dvb_table_cat **table)
+{
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct dvb_table_cat *cat;
+ struct dvb_desc **head_desc;
+ size_t size;
+
+ size = offsetof(struct dvb_table_cat, descriptor);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
+ }
+
+ if (buf[0] != DVB_TABLE_CAT) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x",
+ __func__, buf[0], DVB_TABLE_CAT);
+ return -2;
+ }
+
+ if (!*table) {
+ *table = calloc(sizeof(struct dvb_table_cat), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
+ }
+ }
+ cat = *table;
+ memcpy(cat, p, size);
+ p += size;
+ dvb_table_header_init(&cat->header);
+
+ /* find end of current lists */
+ head_desc = &cat->descriptor;
+ while (*head_desc != NULL)
+ head_desc = &(*head_desc)->next;
+
+ size = cat->header.section_length + 3 - DVB_CRC_SIZE; /* plus header, minus CRC */
+ if (buf + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - buf, size);
+ return -4;
+ }
+ endbuf = buf + size;
+
+ /* parse the descriptors */
+ if (endbuf > p) {
+ uint16_t desc_length = endbuf - p;
+ if (dvb_desc_parse(parms, p, desc_length,
+ head_desc) != 0) {
+ return -5;
+ }
+ p += desc_length;
+ }
+
+ if (endbuf - p)
+ dvb_logwarn("%s: %zu spurious bytes at the end",
+ __func__, endbuf - p);
+
+ return p - buf;
+}
+
+void dvb_table_cat_free(struct dvb_table_cat *cat)
+{
+ dvb_desc_free((struct dvb_desc **) &cat->descriptor);
+ free(cat);
+}
+
+void dvb_table_cat_print(struct dvb_v5_fe_parms *parms, struct dvb_table_cat *cat)
+{
+ dvb_loginfo("CAT");
+ dvb_table_header_print(parms, &cat->header);
+ dvb_desc_print(parms, cat->descriptor);
+}
+
diff --git a/lib/libdvbv5/tables/eit.c b/lib/libdvbv5/tables/eit.c
new file mode 100644
index 00000000..b17ff329
--- /dev/null
+++ b/lib/libdvbv5/tables/eit.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2012-2014 - Andre Roth <neolynx@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ */
+
+#include <libdvbv5/eit.h>
+#include <libdvbv5/descriptors.h>
+#include <libdvbv5/dvb-fe.h>
+
+ssize_t dvb_table_eit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct dvb_table_eit **table)
+{
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct dvb_table_eit *eit;
+ struct dvb_table_eit_event **head;
+ size_t size;
+
+ size = offsetof(struct dvb_table_eit, event);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
+ }
+
+ if ((buf[0] != DVB_TABLE_EIT && buf[0] != DVB_TABLE_EIT_OTHER) &&
+ !(buf[0] >= DVB_TABLE_EIT_SCHEDULE && buf[0] <= DVB_TABLE_EIT_SCHEDULE + 0xF) &&
+ !(buf[0] >= DVB_TABLE_EIT_SCHEDULE_OTHER && buf[0] <= DVB_TABLE_EIT_SCHEDULE_OTHER + 0xF)) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x, 0x%02x or between 0x%02x and 0x%02x or 0x%02x and 0x%02x",
+ __func__, buf[0], DVB_TABLE_EIT, DVB_TABLE_EIT_OTHER,
+ DVB_TABLE_EIT_SCHEDULE, DVB_TABLE_EIT_SCHEDULE + 0xF,
+ DVB_TABLE_EIT_SCHEDULE_OTHER, DVB_TABLE_EIT_SCHEDULE_OTHER + 0xF);
+ return -2;
+ }
+
+ if (!*table) {
+ *table = calloc(sizeof(struct dvb_table_eit), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
+ }
+ }
+ eit = *table;
+ memcpy(eit, p, size);
+ p += size;
+ dvb_table_header_init(&eit->header);
+
+ bswap16(eit->transport_id);
+ bswap16(eit->network_id);
+
+ /* find end of curent list */
+ head = &eit->event;
+ while (*head != NULL)
+ head = &(*head)->next;
+
+ /* get the event entries */
+ size = offsetof(struct dvb_table_eit_event, descriptor);
+ while (p + size <= endbuf) {
+ struct dvb_table_eit_event *event;
+
+ event = malloc(sizeof(struct dvb_table_eit_event));
+ if (!event) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -4;
+ }
+ memcpy(event, p, size);
+ p += size;
+
+ bswap16(event->event_id);
+ bswap16(event->bitfield1);
+ bswap16(event->bitfield2);
+ event->descriptor = NULL;
+ event->next = NULL;
+ dvb_time(event->dvbstart, &event->start);
+ event->duration = bcd((uint32_t) event->dvbduration[0]) * 3600 +
+ bcd((uint32_t) event->dvbduration[1]) * 60 +
+ bcd((uint32_t) event->dvbduration[2]);
+
+ event->service_id = eit->header.id;
+
+ *head = event;
+ head = &(*head)->next;
+
+ /* parse the descriptors */
+ if (event->desc_length > 0) {
+ uint16_t desc_length = event->desc_length;
+ if (p + desc_length > endbuf) {
+ dvb_logwarn("%s: decsriptors short read %zd/%d bytes", __func__,
+ endbuf - p, desc_length);
+ desc_length = endbuf - p;
+ }
+ if (dvb_desc_parse(parms, p, desc_length,
+ &event->descriptor) != 0) {
+ return -5;
+ }
+ p += desc_length;
+ }
+ }
+ if (p < endbuf)
+ dvb_logwarn("%s: %zu spurious bytes at the end",
+ __func__, endbuf - p);
+ return p - buf;
+}
+
+void dvb_table_eit_free(struct dvb_table_eit *eit)
+{
+ struct dvb_table_eit_event *event = eit->event;
+ while (event) {
+ dvb_desc_free((struct dvb_desc **) &event->descriptor);
+ struct dvb_table_eit_event *tmp = event;
+ event = event->next;
+ free(tmp);
+ }
+ free(eit);
+}
+
+void dvb_table_eit_print(struct dvb_v5_fe_parms *parms, struct dvb_table_eit *eit)
+{
+ dvb_loginfo("EIT");
+ dvb_table_header_print(parms, &eit->header);
+ dvb_loginfo("|- transport_id %d", eit->transport_id);
+ dvb_loginfo("|- network_id %d", eit->network_id);
+ dvb_loginfo("|- last segment %d", eit->last_segment);
+ dvb_loginfo("|- last table %d", eit->last_table_id);
+ dvb_loginfo("|\\ event_id");
+ const struct dvb_table_eit_event *event = eit->event;
+ uint16_t events = 0;
+ while (event) {
+ char start[255];
+ strftime(start, sizeof(start), "%F %T", &event->start);
+ dvb_loginfo("|- %7d", event->event_id);
+ dvb_loginfo("| Service %d", event->service_id);
+ dvb_loginfo("| Start %s UTC", start);
+ dvb_loginfo("| Duration %dh %dm %ds", event->duration / 3600, (event->duration % 3600) / 60, event->duration % 60);
+ dvb_loginfo("| free CA mode %d", event->free_CA_mode);
+ dvb_loginfo("| running status %d: %s", event->running_status, dvb_eit_running_status_name[event->running_status] );
+ dvb_desc_print(parms, event->descriptor);
+ event = event->next;
+ events++;
+ }
+ dvb_loginfo("|_ %d events", events);
+}
+
+void dvb_time(const uint8_t data[5], struct tm *tm)
+{
+ /* ETSI EN 300 468 V1.4.1 */
+ int year, month, day, hour, min, sec;
+ int k = 0;
+ uint16_t mjd;
+
+ mjd = *(uint16_t *) data;
+ hour = bcd(data[2]);
+ min = bcd(data[3]);
+ sec = bcd(data[4]);
+ year = ((mjd - 15078.2) / 365.25);
+ month = ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001);
+ day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001);
+ if (month == 14 || month == 15) k = 1;
+ year += k;
+ month = month - 1 - k * 12;
+
+ tm->tm_sec = sec;
+ tm->tm_min = min;
+ tm->tm_hour = hour;
+ tm->tm_mday = day;
+ tm->tm_mon = month - 1;
+ tm->tm_year = year;
+ tm->tm_isdst = 1; /* dst in effect, do not adjust */
+ mktime( tm );
+}
+
+
+const char *dvb_eit_running_status_name[8] = {
+ [0] = "Undefined",
+ [1] = "Not running",
+ [2] = "Starts in a few seconds",
+ [3] = "Pausing",
+ [4] = "Running",
+ [5 ... 7] = "Reserved"
+};
diff --git a/lib/libdvbv5/descriptors/header.c b/lib/libdvbv5/tables/header.c
index da3f9702..14b2372f 100644
--- a/lib/libdvbv5/descriptors/header.c
+++ b/lib/libdvbv5/tables/header.c
@@ -23,26 +23,24 @@
#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
-int dvb_table_header_init(struct dvb_table_header *t)
+void dvb_table_header_init(struct dvb_table_header *t)
{
bswap16(t->bitfield);
bswap16(t->id);
- return 0;
}
void dvb_table_header_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_header *t)
{
- dvb_log("| table_id %d", t->table_id);
- dvb_log("| section_length %d", t->section_length);
- dvb_log("| zero %d", t->zero);
- dvb_log("| one %d", t->one);
- dvb_log("| zero2 %d", t->zero2);
- dvb_log("| syntax %d", t->syntax);
- dvb_log("| transport_stream_id %d", t->id);
- dvb_log("| current_next %d", t->current_next);
- dvb_log("| version %d", t->version);
- dvb_log("| one2 %d", t->one2);
- dvb_log("| section_number %d", t->section_id);
- dvb_log("| last_section_number %d", t->last_section);
+ dvb_loginfo("| table_id 0x%02x", t->table_id);
+ dvb_loginfo("| section_length %d", t->section_length);
+ dvb_loginfo("| one %d", t->one);
+ dvb_loginfo("| zero %d", t->zero);
+ dvb_loginfo("| syntax %d", t->syntax);
+ dvb_loginfo("| transport_stream_id %d", t->id);
+ dvb_loginfo("| current_next %d", t->current_next);
+ dvb_loginfo("| version %d", t->version);
+ dvb_loginfo("| one2 %d", t->one2);
+ dvb_loginfo("| section_number %d", t->section_id);
+ dvb_loginfo("| last_section_number %d", t->last_section);
}
diff --git a/lib/libdvbv5/tables/mgt.c b/lib/libdvbv5/tables/mgt.c
new file mode 100644
index 00000000..b2d59d6c
--- /dev/null
+++ b/lib/libdvbv5/tables/mgt.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013-2014 - Andre Roth <neolynx@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ */
+
+#include <libdvbv5/mgt.h>
+#include <libdvbv5/descriptors.h>
+#include <libdvbv5/dvb-fe.h>
+
+ssize_t atsc_table_mgt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct atsc_table_mgt **table)
+{
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct atsc_table_mgt *mgt;
+ struct atsc_table_mgt_table **head;
+ struct dvb_desc **head_desc;
+ size_t size;
+ int i = 0;
+
+ size = offsetof(struct atsc_table_mgt, table);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
+ }
+
+ if (buf[0] != ATSC_TABLE_MGT) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x",
+ __func__, buf[0], ATSC_TABLE_MGT);
+ return -2;
+ }
+
+ if (!*table) {
+ *table = calloc(sizeof(struct atsc_table_mgt), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
+ }
+ }
+ mgt = *table;
+ memcpy(mgt, p, size);
+ p += size;
+ dvb_table_header_init(&mgt->header);
+
+ bswap16(mgt->tables);
+
+ /* find end of curent lists */
+ head_desc = &mgt->descriptor;
+ while (*head_desc != NULL)
+ head_desc = &(*head_desc)->next;
+ head = &mgt->table;
+ while (*head != NULL)
+ head = &(*head)->next;
+
+ while (i++ < mgt->tables && p < endbuf) {
+ struct atsc_table_mgt_table *table;
+
+ size = offsetof(struct atsc_table_mgt_table, descriptor);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -4;
+ }
+ table = (struct atsc_table_mgt_table *) malloc(sizeof(struct atsc_table_mgt_table));
+ if (!table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -5;
+ }
+ memcpy(table, p, size);
+ p += size;
+
+ bswap16(table->type);
+ bswap16(table->bitfield);
+ bswap16(table->bitfield2);
+ bswap32(table->size);
+ table->descriptor = NULL;
+ table->next = NULL;
+
+ *head = table;
+ head = &(*head)->next;
+
+ /* parse the descriptors */
+ size = table->desc_length;
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -6;
+ }
+ if (dvb_desc_parse(parms, p, size,
+ &table->descriptor) != 0) {
+ return -7;
+ }
+
+ p += size;
+ }
+
+ /* TODO: parse MGT descriptors here into head_desc */
+
+ return p - buf;
+}
+
+void atsc_table_mgt_free(struct atsc_table_mgt *mgt)
+{
+ struct atsc_table_mgt_table *table = mgt->table;
+
+ dvb_desc_free((struct dvb_desc **) &mgt->descriptor);
+ while (table) {
+ struct atsc_table_mgt_table *tmp = table;
+
+ dvb_desc_free((struct dvb_desc **) &table->descriptor);
+ table = table->next;
+ free(tmp);
+ }
+ free(mgt);
+}
+
+void atsc_table_mgt_print(struct dvb_v5_fe_parms *parms, struct atsc_table_mgt *mgt)
+{
+ const struct atsc_table_mgt_table *table = mgt->table;
+ uint16_t tables = 0;
+
+ dvb_loginfo("MGT");
+ ATSC_TABLE_HEADER_PRINT(parms, mgt);
+ dvb_loginfo("| tables %d", mgt->tables);
+ while (table) {
+ dvb_loginfo("|- type %04x %d", table->type, table->pid);
+ dvb_loginfo("| one %d", table->one);
+ dvb_loginfo("| one2 %d", table->one2);
+ dvb_loginfo("| type version %d", table->type_version);
+ dvb_loginfo("| size %d", table->size);
+ dvb_loginfo("| one3 %d", table->one3);
+ dvb_loginfo("| desc_length %d", table->desc_length);
+ dvb_desc_print(parms, table->descriptor);
+ table = table->next;
+ tables++;
+ }
+ dvb_loginfo("|_ %d tables", tables);
+}
+
diff --git a/lib/libdvbv5/descriptors/mpeg_es.c b/lib/libdvbv5/tables/mpeg_es.c
index f9cfbd74..e7d750f0 100644
--- a/lib/libdvbv5/descriptors/mpeg_es.c
+++ b/lib/libdvbv5/tables/mpeg_es.c
@@ -35,17 +35,17 @@ int dvb_mpeg_es_seq_start_init(const uint8_t *buf, ssize_t buflen, struct dvb_mp
void dvb_mpeg_es_seq_start_print(struct dvb_v5_fe_parms *parms, struct dvb_mpeg_es_seq_start *seq_start)
{
- dvb_log("MPEG ES SEQ START");
- dvb_log(" - width %d", seq_start->width);
- dvb_log(" - height %d", seq_start->height);
- dvb_log(" - aspect %d", seq_start->aspect);
- dvb_log(" - framerate %d", seq_start->framerate);
- dvb_log(" - bitrate %d", seq_start->bitrate);
- dvb_log(" - one %d", seq_start->one);
- dvb_log(" - vbv %d", seq_start->vbv);
- dvb_log(" - constrained %d", seq_start->constrained);
- dvb_log(" - qm_intra %d", seq_start->qm_intra);
- dvb_log(" - qm_nonintra %d", seq_start->qm_nonintra);
+ dvb_loginfo("MPEG ES SEQ START");
+ dvb_loginfo(" - width %d", seq_start->width);
+ dvb_loginfo(" - height %d", seq_start->height);
+ dvb_loginfo(" - aspect %d", seq_start->aspect);
+ dvb_loginfo(" - framerate %d", seq_start->framerate);
+ dvb_loginfo(" - bitrate %d", seq_start->bitrate);
+ dvb_loginfo(" - one %d", seq_start->one);
+ dvb_loginfo(" - vbv %d", seq_start->vbv);
+ dvb_loginfo(" - constrained %d", seq_start->constrained);
+ dvb_loginfo(" - qm_intra %d", seq_start->qm_intra);
+ dvb_loginfo(" - qm_nonintra %d", seq_start->qm_nonintra);
}
const char *dvb_mpeg_es_frame_names[5] = {
@@ -68,8 +68,8 @@ int dvb_mpeg_es_pic_start_init(const uint8_t *buf, ssize_t buflen, struct dvb_mp
void dvb_mpeg_es_pic_start_print(struct dvb_v5_fe_parms *parms, struct dvb_mpeg_es_pic_start *pic_start)
{
- dvb_log("MPEG ES PIC START");
- dvb_log(" - temporal_ref %d", pic_start->temporal_ref);
- dvb_log(" - coding_type %d (%s-frame)", pic_start->coding_type, dvb_mpeg_es_frame_names[pic_start->coding_type]);
- dvb_log(" - vbv_delay %d", pic_start->vbv_delay);
+ dvb_loginfo("MPEG ES PIC START");
+ dvb_loginfo(" - temporal_ref %d", pic_start->temporal_ref);
+ dvb_loginfo(" - coding_type %d (%s-frame)", pic_start->coding_type, dvb_mpeg_es_frame_names[pic_start->coding_type]);
+ dvb_loginfo(" - vbv_delay %d", pic_start->vbv_delay);
}
diff --git a/lib/libdvbv5/descriptors/mpeg_pes.c b/lib/libdvbv5/tables/mpeg_pes.c
index 6ce9f663..8ccbbabd 100644
--- a/lib/libdvbv5/descriptors/mpeg_pes.c
+++ b/lib/libdvbv5/tables/mpeg_pes.c
@@ -21,6 +21,7 @@
#include <libdvbv5/mpeg_pes.h>
#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
+#include <inttypes.h>
ssize_t dvb_mpeg_pes_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table)
{
@@ -109,7 +110,7 @@ void dvb_mpeg_pes_print(struct dvb_v5_fe_parms *parms, struct dvb_mpeg_pes *pes)
pes->stream_id == DVB_MPEG_STREAM_DIRECTORY ||
pes->stream_id == DVB_MPEG_STREAM_DSMCC ||
pes->stream_id == DVB_MPEG_STREAM_H222E ) {
- dvb_log(" mpeg pes unsupported stream type %#04x", pes->stream_id);
+ dvb_logwarn(" mpeg pes unsupported stream type 0x%04x", pes->stream_id);
} else {
dvb_loginfo(" mpeg pes optional");
dvb_loginfo(" - two %d", pes->optional->two);
@@ -127,8 +128,10 @@ void dvb_mpeg_pes_print(struct dvb_v5_fe_parms *parms, struct dvb_mpeg_pes *pes)
dvb_loginfo(" - PES_extension %d", pes->optional->PES_extension);
dvb_loginfo(" - length %d", pes->optional->length);
if (pes->optional->PTS_DTS & 2)
- dvb_loginfo(" - pts %lx (%fs)", pes->optional->pts, (float) pes->optional->pts / 90000.0);
+ dvb_loginfo(" - pts %" PRIu64 " (%fs)",
+ pes->optional->pts, (float) pes->optional->pts / 90000.0);
if (pes->optional->PTS_DTS & 1)
- dvb_loginfo(" - dts %lx (%fs)", pes->optional->dts, (float) pes->optional->dts/ 90000.0);
+ dvb_loginfo(" - dts %" PRIu64 " (%fs)",
+ pes->optional->dts, (float) pes->optional->dts/ 90000.0);
}
}
diff --git a/lib/libdvbv5/descriptors/mpeg_ts.c b/lib/libdvbv5/tables/mpeg_ts.c
index e1e115ff..98864fd4 100644
--- a/lib/libdvbv5/descriptors/mpeg_ts.c
+++ b/lib/libdvbv5/tables/mpeg_ts.c
@@ -28,7 +28,7 @@ ssize_t dvb_mpeg_ts_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssiz
const uint8_t *p = buf;
if (buf[0] != DVB_MPEG_TS) {
- dvb_logerr("mpeg ts invalid marker %#02x, sould be %#02x", buf[0], DVB_MPEG_TS);
+ dvb_logerr("mpeg ts invalid marker 0x%02x, sould be 0x%02x", buf[0], DVB_MPEG_TS);
*table_length = 0;
return -1;
}
@@ -56,17 +56,16 @@ void dvb_mpeg_ts_free(struct dvb_mpeg_ts *ts)
void dvb_mpeg_ts_print(struct dvb_v5_fe_parms *parms, struct dvb_mpeg_ts *ts)
{
dvb_loginfo("MPEG TS");
- dvb_loginfo(" - sync byte 0x%02x", ts->sync_byte);
+ dvb_loginfo(" - sync 0x%02x", ts->sync_byte);
dvb_loginfo(" - tei %d", ts->tei);
dvb_loginfo(" - payload_start %d", ts->payload_start);
dvb_loginfo(" - priority %d", ts->priority);
dvb_loginfo(" - pid 0x%04x", ts->pid);
dvb_loginfo(" - scrambling %d", ts->scrambling);
dvb_loginfo(" - adaptation_field %d", ts->adaptation_field);
- dvb_loginfo(" - payload present %d", ts->payload);
dvb_loginfo(" - continuity_counter %d", ts->continuity_counter);
if (ts->adaptation_field) {
- dvb_loginfo(" Adaption Field");
+ dvb_loginfo(" Adaptation Field");
dvb_loginfo(" - length %d", ts->adaption->length);
dvb_loginfo(" - discontinued %d", ts->adaption->discontinued);
dvb_loginfo(" - random_access %d", ts->adaption->random_access);
diff --git a/lib/libdvbv5/descriptors/nit.c b/lib/libdvbv5/tables/nit.c
index 054a9241..08b156c6 100644
--- a/lib/libdvbv5/descriptors/nit.c
+++ b/lib/libdvbv5/tables/nit.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2011-2012 - Mauro Carvalho Chehab
- * Copyright (c) 2012 - Andre Roth <neolynx@gmail.com>
+ * Copyright (c) 2012-2014 - Andre Roth <neolynx@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,65 +22,66 @@
#include <libdvbv5/nit.h>
#include <libdvbv5/dvb-fe.h>
-void dvb_table_nit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
- ssize_t buflen, uint8_t *table, ssize_t *table_length)
+ssize_t dvb_table_nit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct dvb_table_nit **table)
{
- const uint8_t *p = buf, *endbuf = buf + buflen - 4;
- struct dvb_table_nit *nit = (void *)table;
- struct dvb_desc **head_desc = &nit->descriptor;
- struct dvb_table_nit_transport **head = &nit->transport;
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct dvb_table_nit *nit;
+ struct dvb_table_nit_transport **head;
+ struct dvb_desc **head_desc;
size_t size;
- if (*table_length > 0) {
- struct dvb_table_nit *t;
+ size = offsetof(struct dvb_table_nit, descriptor);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
+ }
- /* find end of current lists */
- while (*head_desc != NULL)
- head_desc = &(*head_desc)->next;
- while (*head != NULL)
- head = &(*head)->next;
+ if (buf[0] != DVB_TABLE_NIT) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x",
+ __func__, buf[0], DVB_TABLE_NIT);
+ return -2;
+ }
- size = offsetof(struct dvb_table_nit, descriptor);
- if (p + size > endbuf) {
- dvb_logerr("NIT table (cont) was truncated");
- return;
- }
- p += size;
- t = (struct dvb_table_nit *)buf;
-
- bswap16(t->bitfield);
- size = t->desc_length;
- } else {
- size = offsetof(struct dvb_table_nit, descriptor);
- if (p + size > endbuf) {
- dvb_logerr("NIT table was truncated while filling dvb_table_nit. Need %zu bytes, but has only %zu.",
- size, buflen);
- return;
+ if (!*table) {
+ *table = calloc(sizeof(struct dvb_table_nit), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
}
- memcpy(table, p, size);
- p += size;
+ }
+ nit = *table;
+ memcpy(nit, p, size);
+ p += size;
+ dvb_table_header_init(&nit->header);
- *table_length = sizeof(struct dvb_table_nit);
+ bswap16(nit->bitfield);
- nit->descriptor = NULL;
- nit->transport = NULL;
+ /* find end of current lists */
+ head_desc = &nit->descriptor;
+ while (*head_desc != NULL)
+ head_desc = &(*head_desc)->next;
+ head = &nit->transport;
+ while (*head != NULL)
+ head = &(*head)->next;
- bswap16(nit->bitfield);
- size = nit->desc_length;
- }
+ size = nit->desc_length;
if (p + size > endbuf) {
- dvb_logerr("NIT table was truncated while getting NIT descriptors. Need %zu bytes, but has only %zu.",
- size, endbuf - p);
- return;
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -4;
+ }
+ if (dvb_desc_parse(parms, p, size, head_desc) != 0) {
+ return -5;
}
- dvb_parse_descriptors(parms, p, size, head_desc);
p += size;
size = sizeof(union dvb_table_nit_transport_header);
if (p + size > endbuf) {
- dvb_logerr("NIT table was truncated while getting NIT transports. Need %zu bytes, but has only %zu.",
- size, endbuf - p);
- return;
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -6;
}
p += size;
@@ -90,8 +91,8 @@ void dvb_table_nit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
transport = malloc(sizeof(struct dvb_table_nit_transport));
if (!transport) {
- dvb_perror("Out of memory");
- return;
+ dvb_logerr("%s: out of memory", __func__);
+ return -7;
}
memcpy(transport, p, size);
p += size;
@@ -105,28 +106,33 @@ void dvb_table_nit_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
*head = transport;
head = &(*head)->next;
- /* get the descriptors for each transport */
- head_desc = &transport->descriptor;
-
- if (p + transport->section_length > endbuf) {
- dvb_logerr("NIT table was truncated while getting NIT transport descriptors. Need %u bytes, but has only %zu.",
- transport->section_length, endbuf - p);
- return;
+ /* parse the descriptors */
+ if (transport->desc_length > 0) {
+ uint16_t desc_length = transport->desc_length;
+ if (p + desc_length > endbuf) {
+ dvb_logwarn("%s: decsriptors short read %zd/%d bytes", __func__,
+ endbuf - p, desc_length);
+ desc_length = endbuf - p;
+ }
+ if (dvb_desc_parse(parms, p, desc_length,
+ &transport->descriptor) != 0) {
+ return -8;
+ }
+ p += desc_length;
}
- dvb_parse_descriptors(parms, p, transport->section_length, head_desc);
- p += transport->section_length;
}
if (endbuf - p)
- dvb_logerr("NIT table has %zu spurious bytes at the end.",
- endbuf - p);
+ dvb_logwarn("%s: %zu spurious bytes at the end",
+ __func__, endbuf - p);
+ return p - buf;
}
void dvb_table_nit_free(struct dvb_table_nit *nit)
{
struct dvb_table_nit_transport *transport = nit->transport;
- dvb_free_descriptors((struct dvb_desc **) &nit->descriptor);
- while(transport) {
- dvb_free_descriptors((struct dvb_desc **) &transport->descriptor);
+ dvb_desc_free((struct dvb_desc **) &nit->descriptor);
+ while (transport) {
+ dvb_desc_free((struct dvb_desc **) &transport->descriptor);
struct dvb_table_nit_transport *tmp = transport;
transport = transport->next;
free(tmp);
@@ -136,19 +142,20 @@ void dvb_table_nit_free(struct dvb_table_nit *nit)
void dvb_table_nit_print(struct dvb_v5_fe_parms *parms, struct dvb_table_nit *nit)
{
- dvb_log("NIT");
- dvb_table_header_print(parms, &nit->header);
- dvb_log("| desc_length %d", nit->desc_length);
- dvb_print_descriptors(parms, nit->descriptor);
const struct dvb_table_nit_transport *transport = nit->transport;
uint16_t transports = 0;
- while(transport) {
- dvb_log("|- Transport: %-7d Network: %-7d", transport->transport_id, transport->network_id);
- dvb_print_descriptors(parms, transport->descriptor);
+
+ dvb_loginfo("NIT");
+ dvb_table_header_print(parms, &nit->header);
+ dvb_loginfo("| desc_length %d", nit->desc_length);
+ dvb_desc_print(parms, nit->descriptor);
+ while (transport) {
+ dvb_loginfo("|- transport %04x network %04x", transport->transport_id, transport->network_id);
+ dvb_desc_print(parms, transport->descriptor);
transport = transport->next;
transports++;
}
- dvb_log("|_ %d transports", transports);
+ dvb_loginfo("|_ %d transports", transports);
}
void nit_descriptor_handler(struct dvb_v5_fe_parms *parms,
diff --git a/lib/libdvbv5/tables/pat.c b/lib/libdvbv5/tables/pat.c
new file mode 100644
index 00000000..03b75b0a
--- /dev/null
+++ b/lib/libdvbv5/tables/pat.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
+ * Copyright (c) 2012-2014 - Andre Roth <neolynx@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ */
+
+#include <libdvbv5/pat.h>
+#include <libdvbv5/descriptors.h>
+#include <libdvbv5/dvb-fe.h>
+
+ssize_t dvb_table_pat_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct dvb_table_pat **table)
+{
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct dvb_table_pat *pat;
+ struct dvb_table_pat_program **head;
+ size_t size;
+
+ size = offsetof(struct dvb_table_pat, programs);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
+ }
+
+ if (buf[0] != DVB_TABLE_PAT) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x",
+ __func__, buf[0], DVB_TABLE_PAT);
+ return -2;
+ }
+
+ if (!*table) {
+ *table = calloc(sizeof(struct dvb_table_pat), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
+ }
+ }
+ pat = *table;
+ memcpy(pat, buf, size);
+ p += size;
+ dvb_table_header_init(&pat->header);
+
+ /* find end of current list */
+ head = &pat->program;
+ while (*head != NULL)
+ head = &(*head)->next;
+
+ size = pat->header.section_length + 3 - DVB_CRC_SIZE; /* plus header, minus CRC */
+ if (buf + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - buf, size);
+ return -4;
+ }
+ endbuf = buf + size;
+
+ size = offsetof(struct dvb_table_pat_program, next);
+ while (p + size <= endbuf) {
+ struct dvb_table_pat_program *prog;
+
+ prog = malloc(sizeof(struct dvb_table_pat_program));
+ if (!prog) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -5;
+ }
+
+ memcpy(prog, p, size);
+ p += size;
+
+ bswap16(prog->service_id);
+
+ if (prog->pid == 0x1fff) { /* ignore null packets */
+ free(prog);
+ break;
+ }
+ bswap16(prog->bitfield);
+ pat->programs++;
+
+ prog->next = NULL;
+
+ *head = prog;
+ head = &(*head)->next;
+ }
+ if (endbuf - p)
+ dvb_logwarn("%s: %zu spurious bytes at the end",
+ __func__, endbuf - p);
+ return p - buf;
+}
+
+void dvb_table_pat_free(struct dvb_table_pat *pat)
+{
+ struct dvb_table_pat_program *prog = pat->program;
+
+ while (prog) {
+ struct dvb_table_pat_program *tmp = prog;
+ prog = prog->next;
+ free(tmp);
+ }
+ free(pat);
+}
+
+void dvb_table_pat_print(struct dvb_v5_fe_parms *parms, struct dvb_table_pat *pat)
+{
+ struct dvb_table_pat_program *prog = pat->program;
+
+ dvb_loginfo("PAT");
+ dvb_table_header_print(parms, &pat->header);
+ dvb_loginfo("|\\ %d program pid%s", pat->programs, pat->programs != 1 ? "s" : "");
+
+ while (prog) {
+ dvb_loginfo("| pid 0x%04x: service 0x%04x", prog->pid, prog->service_id);
+ prog = prog->next;
+ }
+}
+
diff --git a/lib/libdvbv5/descriptors/pmt.c b/lib/libdvbv5/tables/pmt.c
index c0af2d41..d2e26932 100644
--- a/lib/libdvbv5/descriptors/pmt.c
+++ b/lib/libdvbv5/tables/pmt.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2011-2012 - Mauro Carvalho Chehab
- * Copyright (c) 2012-2013 - Andre Roth <neolynx@gmail.com>
+ * Copyright (c) 2012-2014 - Andre Roth <neolynx@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,51 +25,71 @@
#include <string.h> /* memcpy */
-void dvb_table_pmt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
- ssize_t buflen, uint8_t *table, ssize_t *table_length)
+ssize_t dvb_table_pmt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct dvb_table_pmt **table)
{
- const uint8_t *p = buf, *endbuf = buf + buflen - 4;
- struct dvb_table_pmt *pmt = (void *)table;
- struct dvb_table_pmt_stream **head = &pmt->stream;
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct dvb_table_pmt *pmt;
+ struct dvb_table_pmt_stream **head;
+ struct dvb_desc **head_desc;
size_t size;
+ size = offsetof(struct dvb_table_pmt, dvb_pmt_field_last);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
+ }
+
if (buf[0] != DVB_TABLE_PMT) {
- dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x", __func__, buf[0], DVB_TABLE_PMT);
- *table_length = 0;
- return;
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x",
+ __func__, buf[0], DVB_TABLE_PMT);
+ return -2;
}
- if (*table_length > 0) {
- /* find end of current list */
- while (*head != NULL)
- head = &(*head)->next;
- } else {
- size = offsetof(struct dvb_table_pmt, dvb_pmt_field_last);
- if (p + size > endbuf) {
- dvb_logerr("%s: short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- return;
+ if (!*table) {
+ *table = calloc(sizeof(struct dvb_table_pmt), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
}
- memcpy(pmt, p, size);
- p += size;
-
- bswap16(pmt->bitfield);
- bswap16(pmt->bitfield2);
- pmt->descriptor = NULL;
- pmt->stream = NULL;
-
- /* parse the descriptors */
- if (pmt->desc_length > 0 ) {
- size = pmt->desc_length;
- if (p + size > endbuf) {
- dvb_logwarn("%s: decsriptors short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- size = endbuf - p;
- }
- dvb_parse_descriptors(parms, p, size,
- &pmt->descriptor);
- p += size;
+ }
+ pmt = *table;
+ memcpy(pmt, p, size);
+ p += size;
+ dvb_table_header_init(&pmt->header);
+ bswap16(pmt->bitfield);
+ bswap16(pmt->bitfield2);
+
+ /* find end of current list */
+ head = &pmt->stream;
+ while (*head != NULL)
+ head = &(*head)->next;
+ head_desc = &pmt->descriptor;
+ while (*head_desc != NULL)
+ head_desc = &(*head_desc)->next;
+
+ size = pmt->header.section_length + 3 - DVB_CRC_SIZE; /* plus header, minus CRC */
+ if (buf + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - buf, size);
+ return -4;
+ }
+ endbuf = buf + size;
+
+ /* parse the descriptors */
+ if (pmt->desc_length > 0 ) {
+ uint16_t desc_length = pmt->desc_length;
+ if (p + desc_length > endbuf) {
+ dvb_logwarn("%s: decsriptors short read %d/%zd bytes", __func__,
+ desc_length, endbuf - p);
+ desc_length = endbuf - p;
}
+ if (dvb_desc_parse(parms, p, desc_length,
+ head_desc) != 0) {
+ return -4;
+ }
+ p += desc_length;
}
/* get the stream entries */
@@ -78,7 +98,10 @@ void dvb_table_pmt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
struct dvb_table_pmt_stream *stream;
stream = malloc(sizeof(struct dvb_table_pmt_stream));
-
+ if (!stream) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -5;
+ }
memcpy(stream, p, size);
p += size;
@@ -92,35 +115,36 @@ void dvb_table_pmt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
/* parse the descriptors */
if (stream->desc_length > 0) {
- size = stream->desc_length;
- if (p + size > endbuf) {
- dvb_logwarn("%s: decsriptors short read %zd/%zd bytes", __func__,
- size, endbuf - p);
- size = endbuf - p;
+ uint16_t desc_length = stream->desc_length;
+ if (p + desc_length > endbuf) {
+ dvb_logwarn("%s: decsriptors short read %zd/%d bytes", __func__,
+ endbuf - p, desc_length);
+ desc_length = endbuf - p;
}
- dvb_parse_descriptors(parms, p, size,
- &stream->descriptor);
-
- p += size;
+ if (dvb_desc_parse(parms, p, desc_length,
+ &stream->descriptor) != 0) {
+ return -6;
+ }
+ p += desc_length;
}
}
if (p < endbuf)
dvb_logwarn("%s: %zu spurious bytes at the end",
__func__, endbuf - p);
- *table_length = p - buf;
+ return p - buf;
}
void dvb_table_pmt_free(struct dvb_table_pmt *pmt)
{
struct dvb_table_pmt_stream *stream = pmt->stream;
while(stream) {
- dvb_free_descriptors((struct dvb_desc **) &stream->descriptor);
+ dvb_desc_free((struct dvb_desc **) &stream->descriptor);
struct dvb_table_pmt_stream *tmp = stream;
stream = stream->next;
free(tmp);
}
- dvb_free_descriptors((struct dvb_desc **) &pmt->descriptor);
+ dvb_desc_free((struct dvb_desc **) &pmt->descriptor);
free(pmt);
}
@@ -133,7 +157,7 @@ void dvb_table_pmt_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_p
dvb_loginfo("| descriptor length %d", pmt->desc_length);
dvb_loginfo("| zero3 %d", pmt->zero3);
dvb_loginfo("| reserved3 %d", pmt->reserved3);
- dvb_print_descriptors(parms, pmt->descriptor);
+ dvb_desc_print(parms, pmt->descriptor);
dvb_loginfo("|\\");
const struct dvb_table_pmt_stream *stream = pmt->stream;
uint16_t streams = 0;
@@ -141,7 +165,7 @@ void dvb_table_pmt_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_p
dvb_loginfo("|- stream 0x%04x: %s (%x)", stream->elementary_pid,
pmt_stream_name[stream->type], stream->type);
dvb_loginfo("| descriptor length %d", stream->desc_length);
- dvb_print_descriptors(parms, stream->descriptor);
+ dvb_desc_print(parms, stream->descriptor);
stream = stream->next;
streams++;
}
diff --git a/lib/libdvbv5/tables/sdt.c b/lib/libdvbv5/tables/sdt.c
new file mode 100644
index 00000000..d27cec87
--- /dev/null
+++ b/lib/libdvbv5/tables/sdt.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
+ * Copyright (c) 2012-2014 - Andre Roth <neolynx@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ */
+
+#include <libdvbv5/sdt.h>
+#include <libdvbv5/descriptors.h>
+#include <libdvbv5/dvb-fe.h>
+
+ssize_t dvb_table_sdt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct dvb_table_sdt **table)
+{
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct dvb_table_sdt *sdt;
+ struct dvb_table_sdt_service **head;
+ size_t size;
+
+ size = offsetof(struct dvb_table_sdt, service);
+ if (p + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
+ }
+
+ if (buf[0] != DVB_TABLE_SDT && buf[0] != DVB_TABLE_SDT2) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x or 0x%02x",
+ __func__, buf[0], DVB_TABLE_SDT, DVB_TABLE_SDT2);
+ return -2;
+ }
+
+ if (!*table) {
+ *table = calloc(sizeof(struct dvb_table_sdt), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
+ }
+ }
+ sdt = *table;
+ memcpy(sdt, p, size);
+ p += size;
+ dvb_table_header_init(&sdt->header);
+ bswap16(sdt->network_id);
+
+ /* find end of curent list */
+ head = &sdt->service;
+ while (*head != NULL)
+ head = &(*head)->next;
+
+ size = sdt->header.section_length + 3 - DVB_CRC_SIZE; /* plus header, minus CRC */
+ if (buf + size > endbuf) {
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - buf, size);
+ return -4;
+ }
+ endbuf = buf + size;
+
+ /* get the event entries */
+ size = offsetof(struct dvb_table_sdt_service, descriptor);
+ while (p + size <= endbuf) {
+ struct dvb_table_sdt_service *service;
+
+ service = malloc(sizeof(struct dvb_table_sdt_service));
+ if (!service) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -5;
+ }
+ memcpy(service, p, size);
+ p += size;
+
+ bswap16(service->service_id);
+ bswap16(service->bitfield);
+ service->descriptor = NULL;
+ service->next = NULL;
+
+ *head = service;
+ head = &(*head)->next;
+
+ /* parse the descriptors */
+ if (service->desc_length > 0) {
+ uint16_t desc_length = service->desc_length;
+ if (p + desc_length > endbuf) {
+ dvb_logwarn("%s: decsriptors short read %zd/%d bytes", __func__,
+ endbuf - p, desc_length);
+ desc_length = endbuf - p;
+ }
+ if (dvb_desc_parse(parms, p, desc_length,
+ &service->descriptor) != 0) {
+ return -6;
+ }
+ p += desc_length;
+ }
+
+ }
+ if (endbuf - p)
+ dvb_logwarn("%s: %zu spurious bytes at the end",
+ __func__, endbuf - p);
+
+ return p - buf;
+}
+
+void dvb_table_sdt_free(struct dvb_table_sdt *sdt)
+{
+ struct dvb_table_sdt_service *service = sdt->service;
+ while(service) {
+ dvb_desc_free((struct dvb_desc **) &service->descriptor);
+ struct dvb_table_sdt_service *tmp = service;
+ service = service->next;
+ free(tmp);
+ }
+ free(sdt);
+}
+
+void dvb_table_sdt_print(struct dvb_v5_fe_parms *parms, struct dvb_table_sdt *sdt)
+{
+ dvb_loginfo("SDT");
+ dvb_table_header_print(parms, &sdt->header);
+ dvb_loginfo("| network_id %d", sdt->network_id);
+ dvb_loginfo("| reserved %d", sdt->reserved);
+ dvb_loginfo("|\\");
+ const struct dvb_table_sdt_service *service = sdt->service;
+ uint16_t services = 0;
+ while (service) {
+ dvb_loginfo("|- service 0x%04x", service->service_id);
+ dvb_loginfo("| EIT schedule %d", service->EIT_schedule);
+ dvb_loginfo("| EIT present following %d", service->EIT_present_following);
+ dvb_loginfo("| free CA mode %d", service->free_CA_mode);
+ dvb_loginfo("| running status %d", service->running_status);
+ dvb_loginfo("| descriptor length %d", service->desc_length);
+ dvb_desc_print(parms, service->descriptor);
+ service = service->next;
+ services++;
+ }
+ dvb_loginfo("|_ %d services", services);
+}
+
diff --git a/lib/libdvbv5/descriptors/vct.c b/lib/libdvbv5/tables/vct.c
index 0f051ac2..e761a7dc 100644
--- a/lib/libdvbv5/descriptors/vct.c
+++ b/lib/libdvbv5/tables/vct.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013 - Mauro Carvalho Chehab <m.chehab@samsung.com>
- * Copyright (c) 2013 - Andre Roth <neolynx@gmail.com>
+ * Copyright (c) 2013-2014 - Andre Roth <neolynx@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,50 +20,65 @@
*/
#include <libdvbv5/vct.h>
+#include <libdvbv5/descriptors.h>
#include <libdvbv5/dvb-fe.h>
#include <parse_string.h>
-void atsc_table_vct_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
- ssize_t buflen, uint8_t *table, ssize_t *table_length)
+ssize_t atsc_table_vct_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
+ ssize_t buflen, struct atsc_table_vct **table)
{
- const uint8_t *p = buf, *endbuf = buf + buflen - 4;
- struct atsc_table_vct *vct = (void *)table;
- struct atsc_table_vct_channel **head = &vct->channel;
+ const uint8_t *p = buf, *endbuf = buf + buflen;
+ struct atsc_table_vct *vct;
+ struct atsc_table_vct_channel **head;
+ size_t size;
int i, n;
- size_t size = offsetof(struct atsc_table_vct, channel);
+ size = offsetof(struct atsc_table_vct, channel);
if (p + size > endbuf) {
- dvb_logerr("VCT table was truncated. Need %zu bytes, but has only %zu.",
- size, buflen);
- return;
+ dvb_logerr("%s: short read %zd/%zd bytes", __func__,
+ endbuf - p, size);
+ return -1;
}
- if (*table_length > 0) {
- /* find end of curent list */
- while (*head != NULL)
- head = &(*head)->next;
- } else {
- memcpy(vct, p, size);
-
- *table_length = sizeof(struct atsc_table_vct);
+ if (buf[0] != ATSC_TABLE_TVCT && buf[0] != ATSC_TABLE_CVCT) {
+ dvb_logerr("%s: invalid marker 0x%02x, sould be 0x%02x or 0x%02x",
+ __func__, buf[0], ATSC_TABLE_TVCT, ATSC_TABLE_CVCT);
+ return -2;
+ }
- vct->channel = NULL;
- vct->descriptor = NULL;
+ if (!*table) {
+ *table = calloc(sizeof(struct atsc_table_vct), 1);
+ if (!*table) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -3;
+ }
}
+ vct = *table;
+ memcpy(vct, p, size);
p += size;
+ dvb_table_header_init(&vct->header);
+
+ /* find end of curent list */
+ head = &vct->channel;
+ while (*head != NULL)
+ head = &(*head)->next;
size = offsetof(struct atsc_table_vct_channel, descriptor);
for (n = 0; n < vct->num_channels_in_section; n++) {
struct atsc_table_vct_channel *channel;
if (p + size > endbuf) {
- dvb_logerr("VCT channel table is missing %d elements",
- vct->num_channels_in_section - n + 1);
+ dvb_logerr("%s: channel table is missing %d elements",
+ __func__, vct->num_channels_in_section - n + 1);
vct->num_channels_in_section = n;
break;
}
channel = malloc(sizeof(struct atsc_table_vct_channel));
+ if (!channel) {
+ dvb_logerr("%s: out of memory", __func__);
+ return -4;
+ }
memcpy(channel, p, size);
p += size;
@@ -99,12 +114,14 @@ void atsc_table_vct_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
if (endbuf - p < channel->descriptors_length) {
dvb_logerr("%s: short read %d/%zd bytes", __func__,
channel->descriptors_length, endbuf - p);
- return;
+ return -5;
}
/* get the descriptors for each program */
- dvb_parse_descriptors(parms, p, channel->descriptors_length,
- &channel->descriptor);
+ if (dvb_desc_parse(parms, p, channel->descriptors_length,
+ &channel->descriptor) != 0) {
+ return -6;
+ }
p += channel->descriptors_length;
}
@@ -118,68 +135,72 @@ void atsc_table_vct_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
if (endbuf - p < d->descriptor_length) {
dvb_logerr("%s: short read %d/%zd bytes", __func__,
d->descriptor_length, endbuf - p);
- return;
+ return -7;
+ }
+ if (dvb_desc_parse(parms, p, d->descriptor_length,
+ &vct->descriptor) != 0) {
+ return -8;
}
- dvb_parse_descriptors(parms, p, d->descriptor_length,
- &vct->descriptor);
}
if (endbuf - p)
- dvb_logerr("VCT table has %zu spurious bytes at the end.",
- endbuf - p);
+ dvb_logwarn("%s: %zu spurious bytes at the end",
+ __func__, endbuf - p);
+ return p - buf;
}
void atsc_table_vct_free(struct atsc_table_vct *vct)
{
struct atsc_table_vct_channel *channel = vct->channel;
- while(channel) {
- dvb_free_descriptors((struct dvb_desc **) &channel->descriptor);
+ while (channel) {
+ dvb_desc_free((struct dvb_desc **) &channel->descriptor);
struct atsc_table_vct_channel *tmp = channel;
channel = channel->next;
free(tmp);
}
- dvb_free_descriptors((struct dvb_desc **) &vct->descriptor);
+ dvb_desc_free((struct dvb_desc **) &vct->descriptor);
free(vct);
}
void atsc_table_vct_print(struct dvb_v5_fe_parms *parms, struct atsc_table_vct *vct)
{
+ const struct atsc_table_vct_channel *channel = vct->channel;
+ uint16_t channels = 0;
+
if (vct->header.table_id == ATSC_TABLE_CVCT)
- dvb_log("CVCT");
+ dvb_loginfo("CVCT");
else
- dvb_log("TVCT");
+ dvb_loginfo("TVCT");
- atsc_table_header_print(parms, &vct->header);
+ ATSC_TABLE_HEADER_PRINT(parms, vct);
- dvb_log("|- #channels %d", vct->num_channels_in_section);
- dvb_log("|\\ channel_id");
- const struct atsc_table_vct_channel *channel = vct->channel;
- uint16_t channels = 0;
- while(channel) {
- dvb_log("|- Channel %d.%d: %s",
+ dvb_loginfo("|- #channels %d", vct->num_channels_in_section);
+ dvb_loginfo("|\\ channel_id");
+ while (channel) {
+ dvb_loginfo("|- Channel %d.%d: %s",
channel->major_channel_number,
channel->minor_channel_number,
channel->short_name);
- dvb_log("| modulation mode %d", channel->modulation_mode);
- dvb_log("| carrier frequency %d", channel->carrier_frequency);
- dvb_log("| TS ID %d", channel->channel_tsid);
- dvb_log("| program number %d", channel->program_number);
+ dvb_loginfo("| modulation mode %d", channel->modulation_mode);
+ dvb_loginfo("| carrier frequency %d", channel->carrier_frequency);
+ dvb_loginfo("| TS ID %d", channel->channel_tsid);
+ dvb_loginfo("| program number %d", channel->program_number);
- dvb_log("| ETM location %d", channel->ETM_location);
- dvb_log("| access controlled %d", channel->access_controlled);
- dvb_log("| hidden %d", channel->hidden);
+ dvb_loginfo("| ETM location %d", channel->ETM_location);
+ dvb_loginfo("| access controlled %d", channel->access_controlled);
+ dvb_loginfo("| hidden %d", channel->hidden);
if (vct->header.table_id == ATSC_TABLE_CVCT) {
- dvb_log("| path select %d", channel->path_select);
- dvb_log("| out of band %d", channel->out_of_band);
+ dvb_loginfo("| path select %d", channel->path_select);
+ dvb_loginfo("| out of band %d", channel->out_of_band);
}
- dvb_log("| hide guide %d", channel->hide_guide);
- dvb_log("| service type %d", channel->service_type);
- dvb_log("| source id %d", channel->source_id);
+ dvb_loginfo("| hide guide %d", channel->hide_guide);
+ dvb_loginfo("| service type %d", channel->service_type);
+ dvb_loginfo("| source id %d", channel->source_id);
- dvb_print_descriptors(parms, channel->descriptor);
+ dvb_desc_print(parms, channel->descriptor);
channel = channel->next;
channels++;
}
- dvb_log("|_ %d channels", channels);
+ dvb_loginfo("|_ %d channels", channels);
}
diff --git a/lib/libv4l-mplane/libv4l-mplane.c b/lib/libv4l-mplane/libv4l-mplane.c
index 1223a003..5659dd57 100644
--- a/lib/libv4l-mplane/libv4l-mplane.c
+++ b/lib/libv4l-mplane/libv4l-mplane.c
@@ -31,6 +31,10 @@
#define SYS_IOCTL(fd, cmd, arg) \
syscall(SYS_ioctl, (int)(fd), (unsigned long)(cmd), (void *)(arg))
+#define SYS_READ(fd, buf, len) \
+ syscall(SYS_read, (int)(fd), (void *)(buf), (size_t)(len));
+#define SYS_WRITE(fd, buf, len) \
+ syscall(SYS_write, (int)(fd), (const void *)(buf), (size_t)(len));
#if HAVE_VISIBILITY
@@ -53,9 +57,15 @@ struct mplane_plugin {
int __ret; \
struct __struc *req = arg; \
uint32_t type = req->type; \
- req->type = convert_type(type); \
- __ret = SYS_IOCTL(fd, cmd, arg); \
- req->type = type; \
+ if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || \
+ type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { \
+ errno = EINVAL; \
+ __ret = -1; \
+ } else { \
+ req->type = convert_type(type); \
+ __ret = SYS_IOCTL(fd, cmd, arg); \
+ req->type = type; \
+ } \
__ret; \
})
@@ -126,12 +136,20 @@ static int querycap_ioctl(int fd, unsigned long int cmd,
if (cap->capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
cap->capabilities |= V4L2_CAP_VIDEO_OUTPUT;
+ if (cap->device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
+ cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+
+ if (cap->device_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
+ cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
+
/*
* Don't report mplane caps, as this will be handled via
* this plugin
*/
cap->capabilities &= ~(V4L2_CAP_VIDEO_OUTPUT_MPLANE |
V4L2_CAP_VIDEO_CAPTURE_MPLANE);
+ cap->device_caps &= ~(V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+ V4L2_CAP_VIDEO_CAPTURE_MPLANE);
return 0;
}
@@ -162,8 +180,12 @@ static int try_set_fmt_ioctl(int fd, unsigned long int cmd,
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ errno = EINVAL;
+ return -1;
default:
- return SYS_IOCTL(fd, cmd, &fmt);
+ return SYS_IOCTL(fd, cmd, arg);
}
fmt.fmt.pix_mp.width = org->fmt.pix.width;
@@ -186,6 +208,7 @@ static int try_set_fmt_ioctl(int fd, unsigned long int cmd,
org->fmt.pix.colorspace = fmt.fmt.pix_mp.colorspace;
org->fmt.pix.bytesperline = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
org->fmt.pix.sizeimage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
+ org->fmt.pix.priv = 0;
return 0;
}
@@ -193,43 +216,51 @@ static int try_set_fmt_ioctl(int fd, unsigned long int cmd,
static int create_bufs_ioctl(int fd, unsigned long int cmd,
struct v4l2_create_buffers *arg)
{
- struct v4l2_format fmt = { 0 };
+ struct v4l2_create_buffers cbufs = { 0 };
+ struct v4l2_format *fmt = &cbufs.format;
struct v4l2_format *org = &arg->format;
int ret;
switch (arg->format.type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ errno = EINVAL;
+ return -1;
default:
- return SYS_IOCTL(fd, cmd, &fmt);
+ return SYS_IOCTL(fd, cmd, arg);
}
- fmt.fmt.pix_mp.width = org->fmt.pix.width;
- fmt.fmt.pix_mp.height = org->fmt.pix.height;
- fmt.fmt.pix_mp.pixelformat = org->fmt.pix.pixelformat;
- fmt.fmt.pix_mp.field = org->fmt.pix.field;
- fmt.fmt.pix_mp.colorspace = org->fmt.pix.colorspace;
- fmt.fmt.pix_mp.num_planes = 1;
- fmt.fmt.pix_mp.plane_fmt[0].bytesperline = org->fmt.pix.bytesperline;
- fmt.fmt.pix_mp.plane_fmt[0].sizeimage = org->fmt.pix.sizeimage;
-
- ret = SYS_IOCTL(fd, cmd, &arg);
- if (ret)
- return ret;
+ cbufs.index = arg->index;
+ cbufs.count = arg->count;
+ cbufs.memory = arg->memory;
+ fmt->fmt.pix_mp.width = org->fmt.pix.width;
+ fmt->fmt.pix_mp.height = org->fmt.pix.height;
+ fmt->fmt.pix_mp.pixelformat = org->fmt.pix.pixelformat;
+ fmt->fmt.pix_mp.field = org->fmt.pix.field;
+ fmt->fmt.pix_mp.colorspace = org->fmt.pix.colorspace;
+ fmt->fmt.pix_mp.num_planes = 1;
+ fmt->fmt.pix_mp.plane_fmt[0].bytesperline = org->fmt.pix.bytesperline;
+ fmt->fmt.pix_mp.plane_fmt[0].sizeimage = org->fmt.pix.sizeimage;
+
+ ret = SYS_IOCTL(fd, cmd, &cbufs);
+
+ arg->index = cbufs.index;
+ arg->count = cbufs.count;
+ org->fmt.pix.width = fmt->fmt.pix_mp.width;
+ org->fmt.pix.height = fmt->fmt.pix_mp.height;
+ org->fmt.pix.pixelformat = fmt->fmt.pix_mp.pixelformat;
+ org->fmt.pix.field = fmt->fmt.pix_mp.field;
+ org->fmt.pix.colorspace = fmt->fmt.pix_mp.colorspace;
+ org->fmt.pix.bytesperline = fmt->fmt.pix_mp.plane_fmt[0].bytesperline;
+ org->fmt.pix.sizeimage = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
- org->fmt.pix.width = fmt.fmt.pix_mp.width;
- org->fmt.pix.height = fmt.fmt.pix_mp.height;
- org->fmt.pix.pixelformat = fmt.fmt.pix_mp.pixelformat;
- org->fmt.pix.field = fmt.fmt.pix_mp.field;
- org->fmt.pix.colorspace = fmt.fmt.pix_mp.colorspace;
- org->fmt.pix.bytesperline = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
- org->fmt.pix.sizeimage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
-
- return 0;
+ return ret;
}
static int get_fmt_ioctl(int fd, unsigned long int cmd, struct v4l2_format *arg)
@@ -245,8 +276,12 @@ static int get_fmt_ioctl(int fd, unsigned long int cmd, struct v4l2_format *arg)
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ errno = EINVAL;
+ return -1;
default:
- return SYS_IOCTL(fd, cmd, &fmt);
+ return SYS_IOCTL(fd, cmd, arg);
}
ret = SYS_IOCTL(fd, cmd, &fmt);
@@ -260,13 +295,14 @@ static int get_fmt_ioctl(int fd, unsigned long int cmd, struct v4l2_format *arg)
org->fmt.pix.colorspace = fmt.fmt.pix_mp.colorspace;
org->fmt.pix.bytesperline = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
org->fmt.pix.sizeimage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
+ org->fmt.pix.priv = 0;
/*
* If the device doesn't support just one plane, there's
* nothing we can do, except return an error condition.
*/
if (fmt.fmt.pix_mp.num_planes > 1) {
- errno = -EINVAL;
+ errno = EINVAL;
return -1;
}
@@ -279,6 +315,12 @@ static int buf_ioctl(int fd, unsigned long int cmd, struct v4l2_buffer *arg)
struct v4l2_plane plane = { 0 };
int ret;
+ if (arg->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
+ arg->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ errno = EINVAL;
+ return -1;
+ }
+
buf.type = convert_type(arg->type);
if (buf.type == arg->type)
@@ -294,6 +336,7 @@ static int buf_ioctl(int fd, unsigned long int cmd, struct v4l2_buffer *arg)
ret = SYS_IOCTL(fd, cmd, &buf);
arg->index = buf.index;
+ arg->memory = buf.memory;
arg->flags = buf.flags;
arg->field = buf.field;
arg->timestamp = buf.timestamp;
@@ -302,6 +345,7 @@ static int buf_ioctl(int fd, unsigned long int cmd, struct v4l2_buffer *arg)
arg->length = plane.length;
arg->bytesused = plane.bytesused;
+ memcpy(&arg->m, &plane.m, sizeof(arg->m));
return ret;
}
@@ -309,7 +353,6 @@ static int buf_ioctl(int fd, unsigned long int cmd, struct v4l2_buffer *arg)
static int plugin_ioctl(void *dev_ops_priv, int fd,
unsigned long int cmd, void *arg)
{
- struct mplane_plugin *plugin = dev_ops_priv;
switch (cmd) {
case VIDIOC_QUERYCAP:
return querycap_ioctl(fd, cmd, arg);
@@ -323,11 +366,6 @@ static int plugin_ioctl(void *dev_ops_priv, int fd,
case VIDIOC_S_PARM:
case VIDIOC_G_PARM:
return SIMPLE_CONVERT_IOCTL(fd, cmd, arg, v4l2_streamparm);
- case VIDIOC_CROPCAP:
- return SIMPLE_CONVERT_IOCTL(fd, cmd, arg, v4l2_cropcap);
- case VIDIOC_S_CROP:
- case VIDIOC_G_CROP:
- return SIMPLE_CONVERT_IOCTL(fd, cmd, arg, v4l2_crop);
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
case VIDIOC_QUERYBUF:
@@ -340,26 +378,16 @@ static int plugin_ioctl(void *dev_ops_priv, int fd,
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
{
- int type, ret;
-
- /*
- * If the device has both capture and output, weird things
- * could happen. For now, let's not consider this case. If this
- * is ever happens in practice, the logic should be changed to
- * track reqbufs, in order to identify what's required.
- */
- if (plugin->mplane_capture) {
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- ret = SYS_IOCTL(fd, cmd, &type);
- } else if (plugin->mplane_output) {
- type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- ret = SYS_IOCTL(fd, cmd, &type);
- } else {
- ret = -1;
+ int type = *(int *)arg;
+
+ if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
+ type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
errno = EINVAL;
+ return -1;
}
+ type = convert_type(type);
- return ret;
+ return SYS_IOCTL(fd, cmd, &type);
}
/* CASE VIDIOC_EXPBUF: */
default:
@@ -367,8 +395,21 @@ static int plugin_ioctl(void *dev_ops_priv, int fd,
}
}
+static ssize_t plugin_read(void *dev_ops_priv, int fd, void *buf, size_t len)
+{
+ return SYS_READ(fd, buf, len);
+}
+
+static ssize_t plugin_write(void *dev_ops_priv, int fd, const void *buf,
+ size_t len)
+{
+ return SYS_WRITE(fd, buf, len);
+}
+
PLUGIN_PUBLIC const struct libv4l_dev_ops libv4l2_plugin = {
.init = &plugin_init,
.close = &plugin_close,
.ioctl = &plugin_ioctl,
+ .read = &plugin_read,
+ .write = &plugin_write,
};
diff --git a/lib/libv4l2/libv4l2-priv.h b/lib/libv4l2/libv4l2-priv.h
index 585273cf..ff4c8d2b 100644
--- a/lib/libv4l2/libv4l2-priv.h
+++ b/lib/libv4l2/libv4l2-priv.h
@@ -92,6 +92,7 @@ struct v4l2_dev_info {
unsigned char *frame_pointers[V4L2_MAX_NO_FRAMES];
int frame_sizes[V4L2_MAX_NO_FRAMES];
int frame_queued; /* 1 status bit per frame */
+ int frame_info_generation;
/* mapping tracking of our fake (converting mmap) frame buffers */
unsigned char frame_map_count[V4L2_MAX_NO_FRAMES];
/* buffer when doing conversion and using read() for read() */
diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c
index c4d69f71..8291ebe7 100644
--- a/lib/libv4l2/libv4l2.c
+++ b/lib/libv4l2/libv4l2.c
@@ -282,7 +282,7 @@ static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf,
unsigned char *dest, int dest_size)
{
const int max_tries = V4L2_IGNORE_FIRST_FRAME_ERRORS + 1;
- int result, tries = max_tries;
+ int result, tries = max_tries, frame_info_gen;
/* Make sure we have the real v4l2 buffers mapped */
result = v4l2_map_buffers(index);
@@ -290,9 +290,12 @@ static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf,
return result;
do {
+ frame_info_gen = devices[index].frame_info_generation;
+ pthread_mutex_unlock(&devices[index].stream_lock);
result = devices[index].dev_ops->ioctl(
devices[index].dev_ops_priv,
devices[index].fd, VIDIOC_DQBUF, buf);
+ pthread_mutex_lock(&devices[index].stream_lock);
if (result) {
if (errno != EAGAIN) {
int saved_err = errno;
@@ -305,6 +308,11 @@ static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf,
devices[index].frame_queued &= ~(1 << buf->index);
+ if (frame_info_gen != devices[index].frame_info_generation) {
+ errno = -EINVAL;
+ return -1;
+ }
+
result = v4lconvert_convert(devices[index].convert,
&devices[index].src_fmt, &devices[index].dest_fmt,
devices[index].frame_pointers[buf->index],
@@ -839,6 +847,7 @@ int v4l2_dup(int fd)
static int v4l2_check_buffer_change_ok(int index)
{
+ devices[index].frame_info_generation++;
v4l2_unmap_buffers(index);
/* Check if the app itself still is using the stream */
@@ -1013,6 +1022,9 @@ int v4l2_ioctl(int fd, unsigned long int request, ...)
case VIDIOC_QUERYCTRL:
case VIDIOC_G_CTRL:
case VIDIOC_S_CTRL:
+ case VIDIOC_G_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+ case VIDIOC_S_EXT_CTRLS:
case VIDIOC_ENUM_FRAMESIZES:
case VIDIOC_ENUM_FRAMEINTERVALS:
is_capture_request = 1;
@@ -1120,6 +1132,18 @@ no_capture_request:
result = v4lconvert_vidioc_s_ctrl(devices[index].convert, arg);
break;
+ case VIDIOC_G_EXT_CTRLS:
+ result = v4lconvert_vidioc_g_ext_ctrls(devices[index].convert, arg);
+ break;
+
+ case VIDIOC_TRY_EXT_CTRLS:
+ result = v4lconvert_vidioc_try_ext_ctrls(devices[index].convert, arg);
+ break;
+
+ case VIDIOC_S_EXT_CTRLS:
+ result = v4lconvert_vidioc_s_ext_ctrls(devices[index].convert, arg);
+ break;
+
case VIDIOC_QUERYCAP: {
struct v4l2_capability *cap = arg;
@@ -1294,9 +1318,11 @@ no_capture_request:
}
if (!v4l2_needs_conversion(index)) {
+ pthread_mutex_unlock(&devices[index].stream_lock);
result = devices[index].dev_ops->ioctl(
devices[index].dev_ops_priv,
fd, VIDIOC_DQBUF, buf);
+ pthread_mutex_lock(&devices[index].stream_lock);
if (result) {
saved_err = errno;
V4L2_PERROR("dequeuing buf");
diff --git a/lib/libv4l2rds/libv4l2rds.c b/lib/libv4l2rds/libv4l2rds.c
index 913bdce2..efc8a7d9 100644
--- a/lib/libv4l2rds/libv4l2rds.c
+++ b/lib/libv4l2rds/libv4l2rds.c
@@ -1022,10 +1022,10 @@ static time_t rds_decode_mjd(const struct rds_private_state *priv_state)
/* add / subtract the local offset to get the local time.
* The offset is expressed in multiples of half hours */
if (priv_state->utc_offset & 0x20) { /* bit 5 indicates -/+ */
- local_hour -= (offset * 2);
+ local_hour -= offset / 2;
local_minute -= (offset % 2) * 30;
} else {
- local_hour += (offset * 2);
+ local_hour += offset / 2;
local_minute += (offset % 2) * 30;
}
@@ -1044,14 +1044,14 @@ static time_t rds_decode_mjd(const struct rds_private_state *priv_state)
new_time.tm_min = local_minute;
new_time.tm_hour = local_hour;
new_time.tm_mday = d;
- new_time.tm_mon = m;
+ new_time.tm_mon = m - 1;
new_time.tm_year = y;
/* offset (submitted by RDS) that was used to compute the local time,
* expressed in multiples of half hours, bit 5 indicates -/+ */
if (priv_state->utc_offset & 0x20)
- new_time.tm_gmtoff = -2 * offset * 3600;
+ new_time.tm_gmtoff = -offset * 1800;
else
- new_time.tm_gmtoff = 2 * offset * 3600;
+ new_time.tm_gmtoff = offset * 1800;
/* convert tm struct to time_t value and return it */
return mktime(&new_time);
@@ -1388,7 +1388,8 @@ uint32_t v4l2_rds_add(struct v4l2_rds *handle, struct v4l2_rds_data *rds_data)
rds_stats->block_cnt++;
/* check for corrected / uncorrectable errors in the data */
- if (rds_data->block & V4L2_RDS_BLOCK_ERROR) {
+ if ((rds_data->block & V4L2_RDS_BLOCK_ERROR) ||
+ block_id == V4L2_RDS_BLOCK_INVALID) {
block_id = -1;
rds_stats->block_error_cnt++;
} else if (rds_data->block & V4L2_RDS_BLOCK_CORRECTED) {
@@ -1583,7 +1584,8 @@ const char *v4l2_rds_get_language_str(const struct v4l2_rds *handle)
const char *v4l2_rds_get_coverage_str(const struct v4l2_rds *handle)
{
/* bits 8-11 contain the area coverage code */
- uint8_t coverage = (handle->pi >> 8) & 0X0f;
+ uint8_t coverage = (handle->pi >> 8) & 0x0f;
+ uint8_t nibble = (handle->pi >> 12) & 0x0f;
static const char *coverage_lut[16] = {
"Local", "International", "National", "Supra-Regional",
"Regional 1", "Regional 2", "Regional 3", "Regional 4",
@@ -1591,7 +1593,14 @@ const char *v4l2_rds_get_coverage_str(const struct v4l2_rds *handle)
"Regional 9", "Regional 10", "Regional 11", "Regional 12"
};
- return coverage_lut[coverage];
+ /*
+ * Coverage area codes are restricted to the B, D and E PI code
+ * blocks for RBDS.
+ */
+ if (!handle->is_rbds ||
+ (nibble == 0xb || nibble == 0xd || nibble == 0xe))
+ return coverage_lut[coverage];
+ return "Not Available";
}
const struct v4l2_rds_group *v4l2_rds_get_group(const struct v4l2_rds *handle)
diff --git a/lib/libv4lconvert/control/libv4lcontrol.c b/lib/libv4lconvert/control/libv4lcontrol.c
index 088e936b..33bf9ce9 100644
--- a/lib/libv4lconvert/control/libv4lcontrol.c
+++ b/lib/libv4lconvert/control/libv4lcontrol.c
@@ -89,6 +89,10 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = {
V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },
{ 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_F0945",
V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },
+ /* This Asus has its camera the right way up, so we've an entry here
+ to override the wildcard match from the upside_down table. */
+ { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F3Sc ",
+ 0 },
{ 0x04f2, 0xb071, 0, "AXIOO", "PICO DJH Model",
V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },
{ 0x04f2, 0xb071, 0, "PEGATRON CORPORATION", "H54",
@@ -528,15 +532,6 @@ static void v4lcontrol_get_flags_from_db(struct v4lcontrol_data *data,
v4lcontrol_get_dmi_string(sysfs_prefix, "board_version", dmi_board_version,
sizeof(dmi_board_version));
- for (i = 0; i < ARRAY_SIZE(upside_down); i++)
- if (find_dmi_string(upside_down[i].board_vendor, dmi_board_vendor) &&
- find_dmi_string(upside_down[i].board_name, dmi_board_name) &&
- find_usb_id(upside_down[i].camera_id, vendor_id, product_id)) {
- /* found entry */
- data->flags |= V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED;
- break;
- }
-
for (i = 0; i < ARRAY_SIZE(v4lcontrol_flags); i++)
if (v4lcontrol_flags[i].vendor_id == vendor_id &&
v4lcontrol_flags[i].product_id ==
@@ -557,6 +552,17 @@ static void v4lcontrol_get_flags_from_db(struct v4lcontrol_data *data,
!strcmp(v4lcontrol_flags[i].dmi_board_version, dmi_board_version))) {
data->flags |= v4lcontrol_flags[i].flags;
data->flags_info = &v4lcontrol_flags[i];
+ /* Entries in the v4lcontrol_flags table override
+ wildcard matches in the upside_down table. */
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(upside_down); i++)
+ if (find_dmi_string(upside_down[i].board_vendor, dmi_board_vendor) &&
+ find_dmi_string(upside_down[i].board_name, dmi_board_name) &&
+ find_usb_id(upside_down[i].camera_id, vendor_id, product_id)) {
+ /* found entry */
+ data->flags |= V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED;
break;
}
}
@@ -782,7 +788,7 @@ static const struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = {
{
.id = V4L2_CID_AUTO_WHITE_BALANCE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Whitebalance (software)",
+ .name = "White Balance, Automatic",
.minimum = 0,
.maximum = 1,
.step = 1,
@@ -791,7 +797,7 @@ static const struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = {
}, {
.id = V4L2_CID_HFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Horizontal flip (sw)",
+ .name = "Horizontal Flip",
.minimum = 0,
.maximum = 1,
.step = 1,
@@ -800,7 +806,7 @@ static const struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = {
}, {
.id = V4L2_CID_VFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Vertical flip (sw)",
+ .name = "Vertical Flip",
.minimum = 0,
.maximum = 1,
.step = 1,
@@ -809,17 +815,17 @@ static const struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = {
}, {
.id = V4L2_CID_GAMMA,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Gamma (software)",
+ .name = "Gamma",
.minimum = 500, /* == 0.5 */
.maximum = 3000, /* == 3.0 */
.step = 1,
.default_value = 1000, /* == 1.0 */
- .flags = 0
+ .flags = V4L2_CTRL_FLAG_SLIDER
}, { /* Dummy place holder for V4LCONTROL_AUTO_ENABLE_COUNT */
}, {
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Auto Gain (software)",
+ .name = "Gain, Automatic",
.minimum = 0,
.maximum = 1,
.step = 1,
@@ -828,12 +834,12 @@ static const struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = {
}, {
.id = V4L2_CTRL_CLASS_USER + 0x2000, /* FIXME */
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Auto Gain target",
+ .name = "Auto Gain Target",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 100,
- .flags = 0
+ .flags = V4L2_CTRL_FLAG_SLIDER
},
};
@@ -910,6 +916,81 @@ int v4lcontrol_vidioc_g_ctrl(struct v4lcontrol_data *data, void *arg)
VIDIOC_G_CTRL, arg);
}
+static void v4lcontrol_alloc_valid_controls(struct v4lcontrol_data *data,
+ const struct v4l2_ext_controls *src,
+ struct v4l2_ext_controls *dst)
+{
+ struct v4l2_ext_control *ctrl;
+ unsigned i, j;
+
+ *dst = *src;
+ if (data->controls == 0)
+ return;
+ ctrl = malloc(src->count * sizeof(*ctrl));
+ if (ctrl == NULL)
+ return;
+ dst->controls = ctrl;
+ dst->count = 0;
+ for (i = 0; i < src->count; i++) {
+ for (j = 0; j < V4LCONTROL_COUNT; j++)
+ if ((data->controls & (1 << j)) &&
+ src->controls[i].id == fake_controls[j].id)
+ break;
+ if (j == V4LCONTROL_COUNT)
+ ctrl[dst->count++] = src->controls[i];
+ }
+}
+
+static void v4lcontrol_free_valid_controls(struct v4lcontrol_data *data,
+ struct v4l2_ext_controls *src,
+ struct v4l2_ext_controls *dst)
+{
+ unsigned i, j, k = 0;
+ int inc_idx;
+
+ src->error_idx = dst->error_idx;
+ if (dst->controls == src->controls)
+ return;
+
+ inc_idx = dst->error_idx < dst->count;
+ for (i = 0; i < src->count; i++) {
+ for (j = 0; j < V4LCONTROL_COUNT; j++)
+ if ((data->controls & (1 << j)) &&
+ src->controls[i].id == fake_controls[j].id)
+ break;
+ if (j == V4LCONTROL_COUNT)
+ src->controls[i] = dst->controls[k++];
+ else if (inc_idx)
+ src->error_idx++;
+ }
+ free(dst->controls);
+}
+
+int v4lcontrol_vidioc_g_ext_ctrls(struct v4lcontrol_data *data, void *arg)
+{
+ struct v4l2_ext_controls *ctrls = arg;
+ struct v4l2_ext_controls dst;
+ int i, j;
+ int res;
+
+ v4lcontrol_alloc_valid_controls(data, ctrls, &dst);
+ res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
+ VIDIOC_G_EXT_CTRLS, &dst);
+ v4lcontrol_free_valid_controls(data, ctrls, &dst);
+ if (res)
+ return res;
+
+ for (i = 0; i < ctrls->count; i++) {
+ for (j = 0; j < V4LCONTROL_COUNT; j++)
+ if ((data->controls & (1 << j)) &&
+ ctrls->controls[i].id == fake_controls[j].id) {
+ ctrls->controls[i].value = data->shm_values[j];
+ break;
+ }
+ }
+ return 0;
+}
+
int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data *data, void *arg)
{
int i;
@@ -932,6 +1013,72 @@ int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data *data, void *arg)
VIDIOC_S_CTRL, arg);
}
+static int v4lcontrol_validate_ext_ctrls(struct v4lcontrol_data *data,
+ struct v4l2_ext_controls *ctrls)
+{
+ int i, j;
+
+ if (data->controls == 0)
+ return 0;
+ for (i = 0; i < ctrls->count; i++) {
+ for (j = 0; j < V4LCONTROL_COUNT; j++)
+ if ((data->controls & (1 << j)) &&
+ ctrls->controls[i].id == fake_controls[j].id) {
+ if (ctrls->controls[i].value > fake_controls[j].maximum ||
+ ctrls->controls[i].value < fake_controls[j].minimum) {
+ ctrls->error_idx = i;
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+int v4lcontrol_vidioc_try_ext_ctrls(struct v4lcontrol_data *data, void *arg)
+{
+ struct v4l2_ext_controls *ctrls = arg;
+ struct v4l2_ext_controls dst;
+ int res = v4lcontrol_validate_ext_ctrls(data, ctrls);
+
+ if (res)
+ return res;
+
+ v4lcontrol_alloc_valid_controls(data, ctrls, &dst);
+ res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
+ VIDIOC_TRY_EXT_CTRLS, &dst);
+ v4lcontrol_free_valid_controls(data, ctrls, &dst);
+ return res;
+}
+
+int v4lcontrol_vidioc_s_ext_ctrls(struct v4lcontrol_data *data, void *arg)
+{
+ struct v4l2_ext_controls *ctrls = arg;
+ struct v4l2_ext_controls dst;
+ int i, j;
+ int res = v4lcontrol_validate_ext_ctrls(data, ctrls);
+
+ if (res)
+ return res;
+
+ v4lcontrol_alloc_valid_controls(data, ctrls, &dst);
+ res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
+ VIDIOC_S_EXT_CTRLS, &dst);
+ v4lcontrol_free_valid_controls(data, ctrls, &dst);
+ if (res)
+ return res;
+
+ for (i = 0; i < ctrls->count; i++) {
+ for (j = 0; j < V4LCONTROL_COUNT; j++)
+ if ((data->controls & (1 << j)) &&
+ ctrls->controls[i].id == fake_controls[j].id) {
+ data->shm_values[j] = ctrls->controls[i].value;
+ break;
+ }
+ }
+ return 0;
+}
+
int v4lcontrol_get_bandwidth(struct v4lcontrol_data *data)
{
return data->bandwidth;
diff --git a/lib/libv4lconvert/control/libv4lcontrol.h b/lib/libv4lconvert/control/libv4lcontrol.h
index 804f1c5d..fa9cf42a 100644
--- a/lib/libv4lconvert/control/libv4lcontrol.h
+++ b/lib/libv4lconvert/control/libv4lcontrol.h
@@ -72,5 +72,8 @@ int v4lcontrol_needs_conversion(struct v4lcontrol_data *data);
int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data *data, void *arg);
int v4lcontrol_vidioc_g_ctrl(struct v4lcontrol_data *data, void *arg);
int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data *data, void *arg);
+int v4lcontrol_vidioc_g_ext_ctrls(struct v4lcontrol_data *data, void *arg);
+int v4lcontrol_vidioc_try_ext_ctrls(struct v4lcontrol_data *data, void *arg);
+int v4lcontrol_vidioc_s_ext_ctrls(struct v4lcontrol_data *data, void *arg);
#endif
diff --git a/lib/libv4lconvert/helper.c b/lib/libv4lconvert/helper.c
index 00e9e42a..b15beb0a 100644
--- a/lib/libv4lconvert/helper.c
+++ b/lib/libv4lconvert/helper.c
@@ -212,12 +212,9 @@ void v4lconvert_helper_cleanup(struct v4lconvert_data *data)
int status;
if (data->decompress_pid != -1) {
- kill(data->decompress_pid, SIGTERM);
- waitpid(data->decompress_pid, &status, 0);
-
close(data->decompress_out_pipe[WRITE_END]);
close(data->decompress_in_pipe[READ_END]);
-
+ waitpid(data->decompress_pid, &status, 0);
data->decompress_pid = -1;
}
}
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
index df06b755..7ee7c195 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -974,6 +974,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
v4lconvert_fixup_fmt(fmt);
break;
+ default:
+ V4LCONVERT_ERR("Unknown destination format in conversion\n");
+ errno = EINVAL;
+ return -1;
}
result = v4lconvert_se401_to_rgb24(data, src, src_size, d,
@@ -1048,11 +1052,6 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
width, height);
break;
}
- if (result == 0) {
- V4LCONVERT_ERR("y10b conversion failed\n");
- errno = EPIPE;
- result = -1;
- }
break;
case V4L2_PIX_FMT_RGB565:
@@ -1542,6 +1541,7 @@ int v4lconvert_enum_framesizes(struct v4lconvert_data *data,
}
frmsize->type = data->framesizes[frmsize->index].type;
+ memset(frmsize->reserved, 0, sizeof(frmsize->reserved));
switch (frmsize->type) {
case V4L2_FRMSIZE_TYPE_DISCRETE:
frmsize->discrete = data->framesizes[frmsize->index].discrete;
@@ -1659,6 +1659,21 @@ int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data *data, void *arg)
return v4lcontrol_vidioc_s_ctrl(data->control, arg);
}
+int v4lconvert_vidioc_g_ext_ctrls(struct v4lconvert_data *data, void *arg)
+{
+ return v4lcontrol_vidioc_g_ext_ctrls(data->control, arg);
+}
+
+int v4lconvert_vidioc_try_ext_ctrls(struct v4lconvert_data *data, void *arg)
+{
+ return v4lcontrol_vidioc_try_ext_ctrls(data->control, arg);
+}
+
+int v4lconvert_vidioc_s_ext_ctrls(struct v4lconvert_data *data, void *arg)
+{
+ return v4lcontrol_vidioc_s_ext_ctrls(data->control, arg);
+}
+
int v4lconvert_get_fps(struct v4lconvert_data *data)
{
return data->fps;
diff --git a/lib/libv4lconvert/se401.c b/lib/libv4lconvert/se401.c
index b38ef389..ce5432ad 100644
--- a/lib/libv4lconvert/se401.c
+++ b/lib/libv4lconvert/se401.c
@@ -116,6 +116,9 @@ int v4lconvert_se401_to_rgb24(struct v4lconvert_data *data,
int in, plen, bits, pixels, info;
int x = 0, total_pixels = 0;
+ if (!src || !dest)
+ goto error;
+
for (in = 0; in + 4 < src_size; in += plen) {
bits = src[in + 3] + (src[in + 2] << 8);
pixels = src[in + 1] + ((src[in + 0] & 0x3f) << 8);
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 5ee99db6..31b29797 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -4,6 +4,7 @@ SUBDIRS = \
libmedia_dev \
decode_tm6000 \
keytable \
+ media-ctl \
v4l2-compliance \
v4l2-ctl \
v4l2-dbg \
diff --git a/utils/dvb/dvbv5-scan.c b/utils/dvb/dvbv5-scan.c
index 501b3322..7eb3bf56 100644
--- a/utils/dvb/dvbv5-scan.c
+++ b/utils/dvb/dvbv5-scan.c
@@ -407,6 +407,7 @@ int main(int argc, char **argv)
{
struct arguments args;
int err, lnb = -1,idx = -1;
+ int r;
const struct argp argp = {
.options = options,
.parser = parse_opt,
@@ -459,8 +460,12 @@ int main(int argc, char **argv)
return -1;
}
- asprintf(&args.demux_dev,
+ r = asprintf(&args.demux_dev,
"/dev/dvb/adapter%i/demux%i", args.adapter_dmx, args.demux);
+ if (r < 0) {
+ fprintf(stderr, "asprintf error\n" );
+ return -1;
+ }
if (verbose)
fprintf(stderr, "using demux '%s'\n", args.demux_dev);
diff --git a/utils/dvb/dvbv5-zap.c b/utils/dvb/dvbv5-zap.c
index eea201e0..98f0dff0 100644
--- a/utils/dvb/dvbv5-zap.c
+++ b/utils/dvb/dvbv5-zap.c
@@ -55,7 +55,6 @@ struct arguments {
int force_dvbv3, lna, lnb, sat_number;
unsigned diseqc_wait, silent, verbose, frontend_only, freq_bpf;
unsigned timeout, dvr, rec_psi, exit_after_tuning;
- unsigned record;
unsigned n_apid, n_vpid, all_pids;
enum file_formats input_format, output_format;
unsigned traffic_monitor, low_traffic;
@@ -75,7 +74,7 @@ static const struct argp_option options[] = {
{"input-format", 'I', "format", 0, "Input format: ZAP, CHANNEL, DVBV5 (default: DVBV5)", 0},
{"lna", 'w', "LNA (0, 1, -1)", 0, "enable/disable/auto LNA power", 0},
{"lnbf", 'l', "LNBf_type", 0, "type of LNBf to use. 'help' lists the available ones", 0},
- {"search", 'L', NULL, 0, "search/look for a string inside the traffic", 0},
+ {"search", 'L', "string", 0, "search/look for a string inside the traffic", 0},
{"monitor", 'm', NULL, 0, "monitors de DVB traffic", 0},
{"output", 'o', "file", 0, "output filename (use -o - for stdout)", 0},
{"pat", 'p', NULL, 0, "add pat and pmt to TS recording (implies -r)", 0},
@@ -189,7 +188,13 @@ static int parse(struct arguments *args,
return -3;
}
- if (entry->lnb) {
+ /*
+ * Both the DVBv5 format and the command line parameters may
+ * specify the LNBf. If both have the definition, use the one
+ * provided by the command line parameter, overriding the one
+ * stored in the channel file.
+ */
+ if (entry->lnb && !parms->lnb) {
int lnb = dvb_sat_search_lnb(entry->lnb);
if (lnb == -1) {
PERROR("unknown LNB %s\n", entry->lnb);
@@ -300,6 +305,7 @@ static int setup_frontend(struct arguments *args,
static void do_timeout(int x)
{
(void)x;
+
if (timeout_flag == 0) {
timeout_flag = 1;
alarm(2);
@@ -385,7 +391,7 @@ static int check_frontend(struct arguments *args,
struct dvb_v5_fe_parms *parms)
{
int rc;
- fe_status_t status;
+ fe_status_t status = 0;
do {
rc = dvb_fe_get_stats(parms);
if (rc) {
@@ -458,7 +464,6 @@ static error_t parse_opt(int k, char *optarg, struct argp_state *state)
break;
case 'o':
args->filename = strdup(optarg);
- args->record = 1;
/* fall through */
case 'r':
args->dvr = 1;
@@ -559,6 +564,7 @@ int do_traffic_monitor(struct arguments *args,
if ((fd = open(args->demux_dev, O_RDWR)) < 0) {
PERROR("failed opening '%s'", args->demux_dev);
+ close(dvr_fd);
return -1;
}
@@ -704,6 +710,7 @@ int main(int argc, char **argv)
memset(&args, 0, sizeof(args));
args.sat_number = -1;
args.lna = LNA_AUTO;
+ args.input_format = FILE_DVBV5;
argp_parse(&argp, argc, argv, 0, &idx, &args);
@@ -721,6 +728,12 @@ int main(int argc, char **argv)
return -1;
}
+ if (!args.traffic_monitor && args.search) {
+ fprintf(stderr, "ERROR: search string can be used only on monitor mode\n");
+ argp_help(&argp, stderr, ARGP_HELP_STD_HELP, PROGRAM_NAME);
+ return -1;
+ }
+
if (args.lnb_name) {
lnb = dvb_sat_search_lnb(args.lnb_name);
if (lnb < 0) {
@@ -766,7 +779,7 @@ int main(int argc, char **argv)
parms = dvb_fe_open(args.adapter, args.frontend, args.verbose, args.force_dvbv3);
if (!parms)
goto err;
- if (lnb)
+ if (lnb >= 0)
parms->lnb = dvb_sat_get_lnb(lnb);
if (args.sat_number > 0)
parms->sat_number = args.sat_number % 3;
@@ -890,11 +903,12 @@ int main(int argc, char **argv)
goto err;
}
- if (args.record) {
- if (args.filename != NULL) {
+ if (args.dvr) {
+ if (args.filename) {
+ file_fd = STDOUT_FILENO;
+
if (strcmp(args.filename, "-") != 0) {
- file_fd =
- open(args.filename,
+ file_fd = open(args.filename,
#ifdef O_LARGEFILE
O_LARGEFILE |
#endif
@@ -905,23 +919,26 @@ int main(int argc, char **argv)
args.filename);
return -1;
}
- } else {
- file_fd = 1;
}
- } else {
- PERROR("Record mode but no filename!");
- goto err;
}
- if ((dvr_fd = open(args.dvr_dev, O_RDONLY)) < 0) {
- PERROR("failed opening '%s'", args.dvr_dev);
- goto err;
- }
if (args.silent < 2)
print_frontend_stats(stderr, &args, parms);
- copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
-
+ if (file_fd >= 0) {
+ if ((dvr_fd = open(args.dvr_dev, O_RDONLY)) < 0) {
+ PERROR("failed opening '%s'", args.dvr_dev);
+ goto err;
+ }
+ if (!timeout_flag)
+ fprintf(stderr, "Record to file '%s' started\n", args.filename);
+ copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
+ } else {
+ if (!timeout_flag)
+ fprintf(stderr, "DVR interface '%s' can now be opened\n", args.dvr_dev);
+ while (timeout_flag == 0)
+ sleep(1);
+ }
if (args.silent < 2)
print_frontend_stats(stderr, &args, parms);
}
diff --git a/utils/keytable/Makefile.am b/utils/keytable/Makefile.am
index 419d4744..3e66ebab 100644
--- a/utils/keytable/Makefile.am
+++ b/utils/keytable/Makefile.am
@@ -14,7 +14,7 @@ install-data-local:
$(install_sh) -d "$(DESTDIR)$(keytableuserdir)"
sync-with-kernel:
- @if [ ! -f $(KERNEL_DIR)/include/uapi/linux/input.h ]; then \
+ @if [ ! -f $(KERNEL_DIR)/usr/include/linux/input.h ]; then \
echo "Error you must set KERNEL_DIR to point to an extracted kernel source dir"; \
exit 1; \
fi
@@ -22,21 +22,21 @@ sync-with-kernel:
@printf "struct parse_event {\n\tchar *name;\n\tunsigned int value;\n};\n" > $(srcdir)/parse.h
@printf "struct parse_event events_type[] = {\n" >> $(srcdir)/parse.h
- @more $(KERNEL_DIR)/include/uapi/linux/input.h | perl -n \
+ @more $(KERNEL_DIR)/usr/include/linux/input.h | perl -n \
-e 'if (m/^\#define\s+(EV_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \
-e '{ printf "\t{\"%s\", %s},\n",$$1,$$2 if ($$1 ne "EV_VERSION"); }' \
>> $(srcdir)/parse.h
@printf "\t{ NULL, 0}\n};\n" >> $(srcdir)/parse.h
@printf "struct parse_event msc_events[] = {\n" >> $(srcdir)/parse.h
- @more $(KERNEL_DIR)/include/uapi/linux/input.h | perl -n \
+ @more $(KERNEL_DIR)/usr/include/linux/input.h | perl -n \
-e 'if (m/^\#define\s+(MSC_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \
-e '{ printf "\t{\"%s\", %s},\n",$$1,$$2; }' \
>> $(srcdir)/parse.h
@printf "\t{ NULL, 0}\n};\n" >> $(srcdir)/parse.h
@printf "struct parse_event key_events[] = {\n" >> $(srcdir)/parse.h
- @more $(KERNEL_DIR)/include/uapi/linux/input.h | perl -n \
+ @more $(KERNEL_DIR)/usr/include/linux/input.h | perl -n \
-e 'if (m/^\#define\s+(KEY_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \
-e '{ printf "\t{\"%s\", %s},\n",$$1,$$2; }' \
-e 'if (m/^\#define\s+(BTN_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \
@@ -45,14 +45,14 @@ sync-with-kernel:
@printf "\t{ NULL, 0}\n};\n" >> $(srcdir)/parse.h
@printf "struct parse_event rel_events[] = {\n" >> $(srcdir)/parse.h
- @more $(KERNEL_DIR)/include/uapi/linux/input.h | perl -n \
+ @more $(KERNEL_DIR)/usr/include/linux/input.h | perl -n \
-e 'if (m/^\#define\s+(REL_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \
-e '{ printf "\t{\"%s\", %s},\n",$$1,$$2; }' \
>> $(srcdir)/parse.h
@printf "\t{ NULL, 0}\n};\n" >> $(srcdir)/parse.h
@printf "struct parse_event abs_events[] = {\n" >> $(srcdir)/parse.h
- @more $(KERNEL_DIR)/include/uapi/linux/input.h | perl -n \
+ @more $(KERNEL_DIR)/usr/include/linux/input.h | perl -n \
-e 'if (m/^\#define\s+(ABS_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \
-e '{ printf "\t{\"%s\", %s},\n",$$1,$$2; }' \
>> $(srcdir)/parse.h
diff --git a/utils/keytable/rc_keymaps/allwinner_ba10_tv_box b/utils/keytable/rc_keymaps/allwinner_ba10_tv_box
new file mode 100644
index 00000000..cfa7641b
--- /dev/null
+++ b/utils/keytable/rc_keymaps/allwinner_ba10_tv_box
@@ -0,0 +1,15 @@
+# table allwinner_ba10_tv_box, type: NEC
+0x206 KEY_UP
+0x216 KEY_VOLUMEDOWN
+0x217 KEY_NEXTSONG
+0x21a KEY_POWER
+0x21b KEY_BACK
+0x21e KEY_OK
+0x21f KEY_DOWN
+0x244 KEY_VOLUMEUP
+0x254 KEY_PREVIOUSSONG
+0x255 KEY_PLAYPAUSE
+0x258 KEY_MENU
+0x259 KEY_HOME
+0x25c KEY_RIGHT
+0x25d KEY_LEFT
diff --git a/utils/keytable/rc_keymaps/allwinner_i12_a20_tv_box b/utils/keytable/rc_keymaps/allwinner_i12_a20_tv_box
new file mode 100644
index 00000000..edbc7a77
--- /dev/null
+++ b/utils/keytable/rc_keymaps/allwinner_i12_a20_tv_box
@@ -0,0 +1,28 @@
+# table allwinner_i12_a20_tv_box, type: NEC
+0x00 KEY_7
+0x01 KEY_4
+0x02 KEY_1
+0x03 KEY_VOLUMEDOWN
+0x04 KEY_8
+0x05 KEY_5
+0x06 KEY_2
+0x07 KEY_BACK
+0x08 KEY_9
+0x09 KEY_6
+0x0a KEY_3
+0x0b KEY_NEXTSONG
+0x0c KEY_WWW
+0x0d KEY_0
+0x0e KEY_BACKSPACE
+0x40 KEY_VOLUMEUP
+0x41 KEY_LEFT
+0x42 KEY_HOME
+0x43 KEY_POWER
+0x44 KEY_DOWN
+0x45 KEY_OK
+0x46 KEY_UP
+0x47 KEY_CONTEXT_MENU
+0x48 KEY_PREVIOUSSONG
+0x49 KEY_RIGHT
+0x4a KEY_MENU
+0x4b KEY_MUTE
diff --git a/utils/keytable/rc_keymaps/tivo b/utils/keytable/rc_keymaps/tivo
index 1decfeb7..53d4e720 100644
--- a/utils/keytable/rc_keymaps/tivo
+++ b/utils/keytable/rc_keymaps/tivo
@@ -1,46 +1,46 @@
# table tivo, type: NEC
-0x3085f009 KEY_MEDIA
-0x3085e010 KEY_POWER2
-0x3085e011 KEY_TV
-0x3085c034 KEY_VIDEO_NEXT
-0x3085e013 KEY_INFO
-0x3085a05f KEY_CYCLEWINDOWS
+0xa10c900f KEY_MEDIA
+0xa10c0807 KEY_POWER2
+0xa10c8807 KEY_TV
+0xa10c2c03 KEY_VIDEO_NEXT
+0xa10cc807 KEY_INFO
+0xa10cfa05 KEY_CYCLEWINDOWS
0x0085305f KEY_CYCLEWINDOWS
-0x3085c036 KEY_EPG
-0x3085e014 KEY_UP
-0x3085e016 KEY_DOWN
-0x3085e017 KEY_LEFT
-0x3085e015 KEY_RIGHT
-0x3085e018 KEY_SCROLLDOWN
-0x3085e019 KEY_SELECT
-0x3085e01a KEY_SCROLLUP
-0x3085e01c KEY_VOLUMEUP
-0x3085e01d KEY_VOLUMEDOWN
-0x3085e01b KEY_MUTE
-0x3085d020 KEY_RECORD
-0x3085e01e KEY_CHANNELUP
-0x3085e01f KEY_CHANNELDOWN
+0xa10c6c03 KEY_EPG
+0xa10c2807 KEY_UP
+0xa10c6807 KEY_DOWN
+0xa10ce807 KEY_LEFT
+0xa10ca807 KEY_RIGHT
+0xa10c1807 KEY_SCROLLDOWN
+0xa10c9807 KEY_SELECT
+0xa10c5807 KEY_SCROLLUP
+0xa10c3807 KEY_VOLUMEUP
+0xa10cb807 KEY_VOLUMEDOWN
+0xa10cd807 KEY_MUTE
+0xa10c040b KEY_RECORD
+0xa10c7807 KEY_CHANNELUP
+0xa10cf807 KEY_CHANNELDOWN
0x0085301f KEY_CHANNELDOWN
-0x3085d021 KEY_PLAY
-0x3085d023 KEY_PAUSE
-0x3085d025 KEY_SLOW
-0x3085d022 KEY_REWIND
-0x3085d024 KEY_FASTFORWARD
-0x3085d026 KEY_PREVIOUS
-0x3085d027 KEY_NEXT
-0x3085b044 KEY_ZOOM
-0x3085b048 KEY_STOP
-0x3085b04a KEY_DVD
-0x3085d028 KEY_NUMERIC_1
-0x3085d029 KEY_NUMERIC_2
-0x3085d02a KEY_NUMERIC_3
-0x3085d02b KEY_NUMERIC_4
-0x3085d02c KEY_NUMERIC_5
-0x3085d02d KEY_NUMERIC_6
-0x3085d02e KEY_NUMERIC_7
-0x3085d02f KEY_NUMERIC_8
+0xa10c840b KEY_PLAY
+0xa10cc40b KEY_PAUSE
+0xa10ca40b KEY_SLOW
+0xa10c440b KEY_REWIND
+0xa10c240b KEY_FASTFORWARD
+0xa10c640b KEY_PREVIOUS
+0xa10ce40b KEY_NEXT
+0xa10c220d KEY_ZOOM
+0xa10c120d KEY_STOP
+0xa10c520d KEY_DVD
+0xa10c140b KEY_NUMERIC_1
+0xa10c940b KEY_NUMERIC_2
+0xa10c540b KEY_NUMERIC_3
+0xa10cd40b KEY_NUMERIC_4
+0xa10c340b KEY_NUMERIC_5
+0xa10cb40b KEY_NUMERIC_6
+0xa10c740b KEY_NUMERIC_7
+0xa10cf40b KEY_NUMERIC_8
0x0085302f KEY_NUMERIC_8
-0x3085c030 KEY_NUMERIC_9
-0x3085c031 KEY_NUMERIC_0
-0x3085c033 KEY_ENTER
-0x3085c032 KEY_CLEAR
+0xa10c0c03 KEY_NUMERIC_9
+0xa10c8c03 KEY_NUMERIC_0
+0xa10ccc03 KEY_ENTER
+0xa10c4c03 KEY_CLEAR
diff --git a/utils/keytable/rc_keymaps/wobo_i5 b/utils/keytable/rc_keymaps/wobo_i5
new file mode 100644
index 00000000..38362c5d
--- /dev/null
+++ b/utils/keytable/rc_keymaps/wobo_i5
@@ -0,0 +1,9 @@
+# table wobo_i5, type: NEC
+0x01 KEY_POWER
+0x05 KEY_UP
+0x06 KEY_LEFT
+0x08 KEY_RIGHT
+0x09 KEY_PLAYPAUSE
+0x0a KEY_DOWN
+0x0c KEY_MENU
+0x0e KEY_BACK
diff --git a/utils/media-ctl/.gitignore b/utils/media-ctl/.gitignore
new file mode 100644
index 00000000..95b6a577
--- /dev/null
+++ b/utils/media-ctl/.gitignore
@@ -0,0 +1 @@
+media-ctl
diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
new file mode 100644
index 00000000..a3931fb3
--- /dev/null
+++ b/utils/media-ctl/Makefile.am
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la
+
+libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h
+libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
+libmediactl_la_LDFLAGS = -static $(LIBUDEV_LIBS)
+
+libv4l2subdev_la_SOURCES = libv4l2subdev.c
+libv4l2subdev_la_LIBADD = libmediactl.la
+libv4l2subdev_la_CFLAGS = -static
+libv4l2subdev_la_LDFLAGS = -static
+
+mediactl_includedir=$(includedir)/mediactl
+noinst_HEADERS = mediactl.h v4l2subdev.h
+
+bin_PROGRAMS = media-ctl
+media_ctl_SOURCES = media-ctl.c options.c options.h tools.h
+media_ctl_LDADD = libmediactl.la libv4l2subdev.la
diff --git a/utils/media-ctl/libmediactl.c b/utils/media-ctl/libmediactl.c
new file mode 100644
index 00000000..ec360bd6
--- /dev/null
+++ b/utils/media-ctl/libmediactl.c
@@ -0,0 +1,957 @@
+/*
+ * Media controller interface library
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <linux/media.h>
+#include <linux/videodev2.h>
+
+#include "mediactl.h"
+#include "mediactl-priv.h"
+#include "tools.h"
+
+/* -----------------------------------------------------------------------------
+ * Graph access
+ */
+
+struct media_pad *media_entity_remote_source(struct media_pad *pad)
+{
+ unsigned int i;
+
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ return NULL;
+
+ for (i = 0; i < pad->entity->num_links; ++i) {
+ struct media_link *link = &pad->entity->links[i];
+
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+ continue;
+
+ if (link->sink == pad)
+ return link->source;
+ }
+
+ return NULL;
+}
+
+struct media_entity *media_get_entity_by_name(struct media_device *media,
+ const char *name, size_t length)
+{
+ unsigned int i;
+
+ /* A match is impossible if the entity name is longer than the maximum
+ * size we can get from the kernel.
+ */
+ if (length >= FIELD_SIZEOF(struct media_entity_desc, name))
+ return NULL;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ if (strncmp(entity->info.name, name, length) == 0 &&
+ entity->info.name[length] == '\0')
+ return entity;
+ }
+
+ return NULL;
+}
+
+struct media_entity *media_get_entity_by_id(struct media_device *media,
+ __u32 id)
+{
+ bool next = id & MEDIA_ENT_ID_FLAG_NEXT;
+ unsigned int i;
+
+ id &= ~MEDIA_ENT_ID_FLAG_NEXT;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ if ((entity->info.id == id && !next) ||
+ (entity->info.id > id && next))
+ return entity;
+ }
+
+ return NULL;
+}
+
+unsigned int media_get_entities_count(struct media_device *media)
+{
+ return media->entities_count;
+}
+
+struct media_entity *media_get_entity(struct media_device *media, unsigned int index)
+{
+ if (index >= media->entities_count)
+ return NULL;
+
+ return &media->entities[index];
+}
+
+const struct media_pad *media_entity_get_pad(struct media_entity *entity, unsigned int index)
+{
+ if (index >= entity->info.pads)
+ return NULL;
+
+ return &entity->pads[index];
+}
+
+unsigned int media_entity_get_links_count(struct media_entity *entity)
+{
+ return entity->num_links;
+}
+
+const struct media_link *media_entity_get_link(struct media_entity *entity, unsigned int index)
+{
+ if (index >= entity->num_links)
+ return NULL;
+
+ return &entity->links[index];
+}
+
+const char *media_entity_get_devname(struct media_entity *entity)
+{
+ return entity->devname[0] ? entity->devname : NULL;
+}
+
+struct media_entity *media_get_default_entity(struct media_device *media,
+ unsigned int type)
+{
+ switch (type) {
+ case MEDIA_ENT_T_DEVNODE_V4L:
+ return media->def.v4l;
+ case MEDIA_ENT_T_DEVNODE_FB:
+ return media->def.fb;
+ case MEDIA_ENT_T_DEVNODE_ALSA:
+ return media->def.alsa;
+ case MEDIA_ENT_T_DEVNODE_DVB:
+ return media->def.dvb;
+ }
+
+ return NULL;
+}
+
+const struct media_device_info *media_get_info(struct media_device *media)
+{
+ return &media->info;
+}
+
+const char *media_get_devnode(struct media_device *media)
+{
+ return media->devnode;
+}
+
+const struct media_entity_desc *media_entity_get_info(struct media_entity *entity)
+{
+ return &entity->info;
+}
+
+/* -----------------------------------------------------------------------------
+ * Open/close
+ */
+
+static int media_device_open(struct media_device *media)
+{
+ int ret;
+
+ if (media->fd != -1)
+ return 0;
+
+ media_dbg(media, "Opening media device %s\n", media->devnode);
+
+ media->fd = open(media->devnode, O_RDWR);
+ if (media->fd < 0) {
+ ret = -errno;
+ media_dbg(media, "%s: Can't open media device %s\n",
+ __func__, media->devnode);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void media_device_close(struct media_device *media)
+{
+ if (media->fd != -1) {
+ close(media->fd);
+ media->fd = -1;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Link setup
+ */
+
+int media_setup_link(struct media_device *media,
+ struct media_pad *source,
+ struct media_pad *sink,
+ __u32 flags)
+{
+ struct media_link *link;
+ struct media_link_desc ulink;
+ unsigned int i;
+ int ret;
+
+ ret = media_device_open(media);
+ if (ret < 0)
+ goto done;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source->entity == source->entity &&
+ link->source->index == source->index &&
+ link->sink->entity == sink->entity &&
+ link->sink->index == sink->index)
+ break;
+ }
+
+ if (i == source->entity->num_links) {
+ media_dbg(media, "%s: Link not found\n", __func__);
+ ret = -ENOENT;
+ goto done;
+ }
+
+ /* source pad */
+ ulink.source.entity = source->entity->info.id;
+ ulink.source.index = source->index;
+ ulink.source.flags = MEDIA_PAD_FL_SOURCE;
+
+ /* sink pad */
+ ulink.sink.entity = sink->entity->info.id;
+ ulink.sink.index = sink->index;
+ ulink.sink.flags = MEDIA_PAD_FL_SINK;
+
+ ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
+
+ ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
+ if (ret == -1) {
+ ret = -errno;
+ media_dbg(media, "%s: Unable to setup link (%s)\n",
+ __func__, strerror(errno));
+ goto done;
+ }
+
+ link->flags = ulink.flags;
+ link->twin->flags = ulink.flags;
+
+ ret = 0;
+
+done:
+ media_device_close(media);
+ return ret;
+}
+
+int media_reset_links(struct media_device *media)
+{
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ for (j = 0; j < entity->num_links; j++) {
+ struct media_link *link = &entity->links[j];
+
+ if (link->flags & MEDIA_LNK_FL_IMMUTABLE ||
+ link->source->entity != entity)
+ continue;
+
+ ret = media_setup_link(media, link->source, link->sink,
+ link->flags & ~MEDIA_LNK_FL_ENABLED);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Entities, pads and links enumeration
+ */
+
+static struct media_link *media_entity_add_link(struct media_entity *entity)
+{
+ if (entity->num_links >= entity->max_links) {
+ struct media_link *links = entity->links;
+ unsigned int max_links = entity->max_links * 2;
+ unsigned int i;
+
+ links = realloc(links, max_links * sizeof *links);
+ if (links == NULL)
+ return NULL;
+
+ for (i = 0; i < entity->num_links; ++i)
+ links[i].twin->twin = &links[i];
+
+ entity->max_links = max_links;
+ entity->links = links;
+ }
+
+ return &entity->links[entity->num_links++];
+}
+
+static int media_enum_links(struct media_device *media)
+{
+ __u32 id;
+ int ret = 0;
+
+ for (id = 1; id <= media->entities_count; id++) {
+ struct media_entity *entity = &media->entities[id - 1];
+ struct media_links_enum links;
+ unsigned int i;
+
+ links.entity = entity->info.id;
+ links.pads = calloc(entity->info.pads, sizeof(struct media_pad_desc));
+ links.links = calloc(entity->info.links, sizeof(struct media_link_desc));
+
+ if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
+ ret = -errno;
+ media_dbg(media,
+ "%s: Unable to enumerate pads and links (%s).\n",
+ __func__, strerror(errno));
+ free(links.pads);
+ free(links.links);
+ return ret;
+ }
+
+ for (i = 0; i < entity->info.pads; ++i) {
+ entity->pads[i].entity = entity;
+ entity->pads[i].index = links.pads[i].index;
+ entity->pads[i].flags = links.pads[i].flags;
+ }
+
+ for (i = 0; i < entity->info.links; ++i) {
+ struct media_link_desc *link = &links.links[i];
+ struct media_link *fwdlink;
+ struct media_link *backlink;
+ struct media_entity *source;
+ struct media_entity *sink;
+
+ source = media_get_entity_by_id(media, link->source.entity);
+ sink = media_get_entity_by_id(media, link->sink.entity);
+
+ if (source == NULL || sink == NULL) {
+ media_dbg(media,
+ "WARNING entity %u link %u from %u/%u to %u/%u is invalid!\n",
+ id, i, link->source.entity,
+ link->source.index,
+ link->sink.entity,
+ link->sink.index);
+ ret = -EINVAL;
+ } else {
+ fwdlink = media_entity_add_link(source);
+ fwdlink->source = &source->pads[link->source.index];
+ fwdlink->sink = &sink->pads[link->sink.index];
+ fwdlink->flags = link->flags;
+
+ backlink = media_entity_add_link(sink);
+ backlink->source = &source->pads[link->source.index];
+ backlink->sink = &sink->pads[link->sink.index];
+ backlink->flags = link->flags;
+
+ fwdlink->twin = backlink;
+ backlink->twin = fwdlink;
+ }
+ }
+
+ free(links.pads);
+ free(links.links);
+ }
+
+ return ret;
+}
+
+#ifdef HAVE_LIBUDEV
+
+#include <libudev.h>
+
+static inline int media_udev_open(struct udev **udev)
+{
+ *udev = udev_new();
+ if (*udev == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void media_udev_close(struct udev *udev)
+{
+ if (udev != NULL)
+ udev_unref(udev);
+}
+
+static int media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity)
+{
+ struct udev_device *device;
+ dev_t devnum;
+ const char *p;
+ int ret = -ENODEV;
+
+ if (udev == NULL)
+ return -EINVAL;
+
+ devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
+ media_dbg(entity->media, "looking up device: %u:%u\n",
+ major(devnum), minor(devnum));
+ device = udev_device_new_from_devnum(udev, 'c', devnum);
+ if (device) {
+ p = udev_device_get_devnode(device);
+ if (p) {
+ strncpy(entity->devname, p, sizeof(entity->devname));
+ entity->devname[sizeof(entity->devname) - 1] = '\0';
+ }
+ ret = 0;
+ }
+
+ udev_device_unref(device);
+
+ return ret;
+}
+
+#else /* HAVE_LIBUDEV */
+
+struct udev;
+
+static inline int media_udev_open(struct udev **udev) { return 0; }
+
+static inline void media_udev_close(struct udev *udev) { }
+
+static inline int media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity)
+{
+ return -ENOTSUP;
+}
+
+#endif /* HAVE_LIBUDEV */
+
+static int media_get_devname_sysfs(struct media_entity *entity)
+{
+ struct stat devstat;
+ char devname[32];
+ char sysname[32];
+ char target[1024];
+ char *p;
+ int ret;
+
+ sprintf(sysname, "/sys/dev/char/%u:%u", entity->info.v4l.major,
+ entity->info.v4l.minor);
+ ret = readlink(sysname, target, sizeof(target) - 1);
+ if (ret < 0)
+ return -errno;
+
+ target[ret] = '\0';
+ p = strrchr(target, '/');
+ if (p == NULL)
+ return -EINVAL;
+
+ sprintf(devname, "/dev/%s", p + 1);
+ ret = stat(devname, &devstat);
+ if (ret < 0)
+ return -errno;
+
+ /* Sanity check: udev might have reordered the device nodes.
+ * Make sure the major/minor match. We should really use
+ * libudev.
+ */
+ if (major(devstat.st_rdev) == entity->info.v4l.major &&
+ minor(devstat.st_rdev) == entity->info.v4l.minor)
+ strcpy(entity->devname, devname);
+
+ return 0;
+}
+
+static int media_enum_entities(struct media_device *media)
+{
+ struct media_entity *entity;
+ struct udev *udev;
+ unsigned int size;
+ __u32 id;
+ int ret;
+
+ ret = media_udev_open(&udev);
+ if (ret < 0)
+ media_dbg(media, "Can't get udev context\n");
+
+ for (id = 0, ret = 0; ; id = entity->info.id) {
+ size = (media->entities_count + 1) * sizeof(*media->entities);
+ media->entities = realloc(media->entities, size);
+
+ entity = &media->entities[media->entities_count];
+ memset(entity, 0, sizeof(*entity));
+ entity->fd = -1;
+ entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+ entity->media = media;
+
+ ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
+ if (ret < 0) {
+ ret = errno != EINVAL ? -errno : 0;
+ break;
+ }
+
+ /* Number of links (for outbound links) plus number of pads (for
+ * inbound links) is a good safe initial estimate of the total
+ * number of links.
+ */
+ entity->max_links = entity->info.pads + entity->info.links;
+
+ entity->pads = malloc(entity->info.pads * sizeof(*entity->pads));
+ entity->links = malloc(entity->max_links * sizeof(*entity->links));
+ if (entity->pads == NULL || entity->links == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ media->entities_count++;
+
+ if (entity->info.flags & MEDIA_ENT_FL_DEFAULT) {
+ switch (entity->info.type) {
+ case MEDIA_ENT_T_DEVNODE_V4L:
+ media->def.v4l = entity;
+ break;
+ case MEDIA_ENT_T_DEVNODE_FB:
+ media->def.fb = entity;
+ break;
+ case MEDIA_ENT_T_DEVNODE_ALSA:
+ media->def.alsa = entity;
+ break;
+ case MEDIA_ENT_T_DEVNODE_DVB:
+ media->def.dvb = entity;
+ break;
+ }
+ }
+
+ /* Find the corresponding device name. */
+ if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE &&
+ media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ continue;
+
+ /* Try to get the device name via udev */
+ if (!media_get_devname_udev(udev, entity))
+ continue;
+
+ /* Fall back to get the device name via sysfs */
+ media_get_devname_sysfs(entity);
+ }
+
+ media_udev_close(udev);
+ return ret;
+}
+
+int media_device_enumerate(struct media_device *media)
+{
+ int ret;
+
+ if (media->entities)
+ return 0;
+
+ ret = media_device_open(media);
+ if (ret < 0)
+ return ret;
+
+ ret = ioctl(media->fd, MEDIA_IOC_DEVICE_INFO, &media->info);
+ if (ret < 0) {
+ ret = -errno;
+ media_dbg(media, "%s: Unable to retrieve media device "
+ "information for device %s (%s)\n", __func__,
+ media->devnode, strerror(errno));
+ goto done;
+ }
+
+ media_dbg(media, "Enumerating entities\n");
+
+ ret = media_enum_entities(media);
+ if (ret < 0) {
+ media_dbg(media,
+ "%s: Unable to enumerate entities for device %s (%s)\n",
+ __func__, media->devnode, strerror(-ret));
+ goto done;
+ }
+
+ media_dbg(media, "Found %u entities\n", media->entities_count);
+ media_dbg(media, "Enumerating pads and links\n");
+
+ ret = media_enum_links(media);
+ if (ret < 0) {
+ media_dbg(media,
+ "%s: Unable to enumerate pads and linksfor device %s\n",
+ __func__, media->devnode);
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ media_device_close(media);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Create/destroy
+ */
+
+static void media_debug_default(void *ptr, ...)
+{
+}
+
+void media_debug_set_handler(struct media_device *media,
+ void (*debug_handler)(void *, ...),
+ void *debug_priv)
+{
+ if (debug_handler) {
+ media->debug_handler = debug_handler;
+ media->debug_priv = debug_priv;
+ } else {
+ media->debug_handler = media_debug_default;
+ media->debug_priv = NULL;
+ }
+}
+
+static struct media_device *__media_device_new(void)
+{
+ struct media_device *media;
+
+ media = calloc(1, sizeof(*media));
+ if (media == NULL)
+ return NULL;
+
+ media->fd = -1;
+ media->refcount = 1;
+
+ media_debug_set_handler(media, NULL, NULL);
+
+ return media;
+}
+
+struct media_device *media_device_new(const char *devnode)
+{
+ struct media_device *media;
+
+ media = __media_device_new();
+ if (media == NULL)
+ return NULL;
+
+ media->devnode = strdup(devnode);
+ if (media->devnode == NULL) {
+ media_device_unref(media);
+ return NULL;
+ }
+
+ return media;
+}
+
+struct media_device *media_device_new_emulated(struct media_device_info *info)
+{
+ struct media_device *media;
+
+ media = __media_device_new();
+ if (media == NULL)
+ return NULL;
+
+ media->info = *info;
+
+ return media;
+}
+
+struct media_device *media_device_ref(struct media_device *media)
+{
+ media->refcount++;
+ return media;
+}
+
+void media_device_unref(struct media_device *media)
+{
+ unsigned int i;
+
+ media->refcount--;
+ if (media->refcount > 0)
+ return;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ free(entity->pads);
+ free(entity->links);
+ if (entity->fd != -1)
+ close(entity->fd);
+ }
+
+ free(media->entities);
+ free(media->devnode);
+ free(media);
+}
+
+int media_device_add_entity(struct media_device *media,
+ const struct media_entity_desc *desc,
+ const char *devnode)
+{
+ struct media_entity **defent = NULL;
+ struct media_entity *entity;
+ unsigned int size;
+
+ size = (media->entities_count + 1) * sizeof(*media->entities);
+ entity = realloc(media->entities, size);
+ if (entity == NULL)
+ return -ENOMEM;
+
+ media->entities = entity;
+ media->entities_count++;
+
+ entity = &media->entities[media->entities_count - 1];
+ memset(entity, 0, sizeof *entity);
+
+ entity->fd = -1;
+ entity->media = media;
+ strncpy(entity->devname, devnode, sizeof entity->devname);
+ entity->devname[sizeof entity->devname - 1] = '\0';
+
+ entity->info.id = 0;
+ entity->info.type = desc->type;
+ entity->info.flags = 0;
+ memcpy(entity->info.name, desc->name, sizeof entity->info.name);
+
+ switch (entity->info.type) {
+ case MEDIA_ENT_T_DEVNODE_V4L:
+ defent = &media->def.v4l;
+ entity->info.v4l = desc->v4l;
+ break;
+ case MEDIA_ENT_T_DEVNODE_FB:
+ defent = &media->def.fb;
+ entity->info.fb = desc->fb;
+ break;
+ case MEDIA_ENT_T_DEVNODE_ALSA:
+ defent = &media->def.alsa;
+ entity->info.alsa = desc->alsa;
+ break;
+ case MEDIA_ENT_T_DEVNODE_DVB:
+ defent = &media->def.dvb;
+ entity->info.dvb = desc->dvb;
+ break;
+ }
+
+ if (desc->flags & MEDIA_ENT_FL_DEFAULT) {
+ entity->info.flags |= MEDIA_ENT_FL_DEFAULT;
+ if (defent)
+ *defent = entity;
+ }
+
+ return 0;
+}
+
+struct media_pad *media_parse_pad(struct media_device *media,
+ const char *p, char **endp)
+{
+ unsigned int entity_id, pad;
+ struct media_entity *entity;
+ char *end;
+
+ /* endp can be NULL. To avoid spreading NULL checks across the function,
+ * set endp to &end in that case.
+ */
+ if (endp == NULL)
+ endp = &end;
+
+ for (; isspace(*p); ++p);
+
+ if (*p == '"' || *p == '\'') {
+ for (end = (char *)p + 1; *end && *end != '"' && *end != '\''; ++end);
+ if (*end != '"' && *end != '\'') {
+ media_dbg(media, "missing matching '\"'\n");
+ *endp = end;
+ return NULL;
+ }
+
+ entity = media_get_entity_by_name(media, p + 1, end - p - 1);
+ if (entity == NULL) {
+ media_dbg(media, "no such entity \"%.*s\"\n", end - p - 1, p + 1);
+ *endp = (char *)p + 1;
+ return NULL;
+ }
+
+ ++end;
+ } else {
+ entity_id = strtoul(p, &end, 10);
+ entity = media_get_entity_by_id(media, entity_id);
+ if (entity == NULL) {
+ media_dbg(media, "no such entity %d\n", entity_id);
+ *endp = (char *)p;
+ return NULL;
+ }
+ }
+ for (; isspace(*end); ++end);
+
+ if (*end != ':') {
+ media_dbg(media, "Expected ':'\n", *end);
+ *endp = end;
+ return NULL;
+ }
+
+ for (p = end + 1; isspace(*p); ++p);
+
+ pad = strtoul(p, &end, 10);
+
+ if (pad >= entity->info.pads) {
+ media_dbg(media, "No pad '%d' on entity \"%s\". Maximum pad number is %d\n",
+ pad, entity->info.name, entity->info.pads - 1);
+ *endp = (char *)p;
+ return NULL;
+ }
+
+ for (p = end; isspace(*p); ++p);
+ *endp = (char *)p;
+
+ return &entity->pads[pad];
+}
+
+struct media_link *media_parse_link(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct media_link *link;
+ struct media_pad *source;
+ struct media_pad *sink;
+ unsigned int i;
+ char *end;
+
+ source = media_parse_pad(media, p, &end);
+ if (source == NULL) {
+ *endp = end;
+ return NULL;
+ }
+
+ if (end[0] != '-' || end[1] != '>') {
+ *endp = end;
+ media_dbg(media, "Expected '->'\n");
+ return NULL;
+ }
+
+ p = end + 2;
+
+ sink = media_parse_pad(media, p, &end);
+ if (sink == NULL) {
+ *endp = end;
+ return NULL;
+ }
+
+ *endp = end;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source == source && link->sink == sink)
+ return link;
+ }
+
+ media_dbg(media, "No link between \"%s\":%d and \"%s\":%d\n",
+ source->entity->info.name, source->index,
+ sink->entity->info.name, sink->index);
+ return NULL;
+}
+
+int media_parse_setup_link(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct media_link *link;
+ __u32 flags;
+ char *end;
+
+ link = media_parse_link(media, p, &end);
+ if (link == NULL) {
+ media_dbg(media,
+ "%s: Unable to parse link\n", __func__);
+ *endp = end;
+ return -EINVAL;
+ }
+
+ p = end;
+ if (*p++ != '[') {
+ media_dbg(media, "Unable to parse link flags: expected '['.\n");
+ *endp = (char *)p - 1;
+ return -EINVAL;
+ }
+
+ flags = strtoul(p, &end, 10);
+ for (p = end; isspace(*p); p++);
+ if (*p++ != ']') {
+ media_dbg(media, "Unable to parse link flags: expected ']'.\n");
+ *endp = (char *)p - 1;
+ return -EINVAL;
+ }
+
+ for (; isspace(*p); p++);
+ *endp = (char *)p;
+
+ media_dbg(media,
+ "Setting up link %u:%u -> %u:%u [%u]\n",
+ link->source->entity->info.id, link->source->index,
+ link->sink->entity->info.id, link->sink->index,
+ flags);
+
+ return media_setup_link(media, link->source, link->sink, flags);
+}
+
+void media_print_streampos(struct media_device *media, const char *p,
+ const char *end)
+{
+ int pos;
+
+ pos = end - p + 1;
+
+ if (pos < 0)
+ pos = 0;
+ if (pos > strlen(p))
+ pos = strlen(p);
+
+ media_dbg(media, "\n");
+ media_dbg(media, " %s\n", p);
+ media_dbg(media, " %*s\n", pos, "^");
+}
+
+int media_parse_setup_links(struct media_device *media, const char *p)
+{
+ char *end;
+ int ret;
+
+ do {
+ ret = media_parse_setup_link(media, p, &end);
+ if (ret < 0) {
+ media_print_streampos(media, p, end);
+ return ret;
+ }
+
+ p = end + 1;
+ } while (*end == ',');
+
+ return *end ? -EINVAL : 0;
+}
diff --git a/utils/media-ctl/libmediactl.pc.in b/utils/media-ctl/libmediactl.pc.in
new file mode 100644
index 00000000..dab2ff0a
--- /dev/null
+++ b/utils/media-ctl/libmediactl.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libmediactl
+Description: Media controller library.
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lmediactl
diff --git a/utils/media-ctl/libv4l2subdev.c b/utils/media-ctl/libv4l2subdev.c
new file mode 100644
index 00000000..8015330d
--- /dev/null
+++ b/utils/media-ctl/libv4l2subdev.c
@@ -0,0 +1,757 @@
+/*
+ * V4L2 subdev interface library
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <linux/v4l2-subdev.h>
+
+#include "mediactl.h"
+#include "mediactl-priv.h"
+#include "tools.h"
+#include "v4l2subdev.h"
+
+int v4l2_subdev_open(struct media_entity *entity)
+{
+ if (entity->fd != -1)
+ return 0;
+
+ entity->fd = open(entity->devname, O_RDWR);
+ if (entity->fd == -1) {
+ int ret = -errno;
+ media_dbg(entity->media,
+ "%s: Failed to open subdev device node %s\n", __func__,
+ entity->devname);
+ return ret;
+ }
+
+ return 0;
+}
+
+void v4l2_subdev_close(struct media_entity *entity)
+{
+ close(entity->fd);
+ entity->fd = -1;
+}
+
+int v4l2_subdev_get_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_format fmt;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.pad = pad;
+ fmt.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FMT, &fmt);
+ if (ret < 0)
+ return -errno;
+
+ *format = fmt.format;
+ return 0;
+}
+
+int v4l2_subdev_set_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_format fmt;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.pad = pad;
+ fmt.which = which;
+ fmt.format = *format;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FMT, &fmt);
+ if (ret < 0)
+ return -errno;
+
+ *format = fmt.format;
+ return 0;
+}
+
+int v4l2_subdev_get_selection(struct media_entity *entity,
+ struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+ enum v4l2_subdev_format_whence which)
+{
+ union {
+ struct v4l2_subdev_selection sel;
+ struct v4l2_subdev_crop crop;
+ } u;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&u.sel, 0, sizeof(u.sel));
+ u.sel.pad = pad;
+ u.sel.target = target;
+ u.sel.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_SELECTION, &u.sel);
+ if (ret >= 0) {
+ *rect = u.sel.r;
+ return 0;
+ }
+ if (errno != ENOTTY || target != V4L2_SEL_TGT_CROP)
+ return -errno;
+
+ memset(&u.crop, 0, sizeof(u.crop));
+ u.crop.pad = pad;
+ u.crop.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_CROP, &u.crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = u.crop.rect;
+ return 0;
+}
+
+int v4l2_subdev_set_selection(struct media_entity *entity,
+ struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+ enum v4l2_subdev_format_whence which)
+{
+ union {
+ struct v4l2_subdev_selection sel;
+ struct v4l2_subdev_crop crop;
+ } u;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&u.sel, 0, sizeof(u.sel));
+ u.sel.pad = pad;
+ u.sel.target = target;
+ u.sel.which = which;
+ u.sel.r = *rect;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_SELECTION, &u.sel);
+ if (ret >= 0) {
+ *rect = u.sel.r;
+ return 0;
+ }
+ if (errno != ENOTTY || target != V4L2_SEL_TGT_CROP)
+ return -errno;
+
+ memset(&u.crop, 0, sizeof(u.crop));
+ u.crop.pad = pad;
+ u.crop.which = which;
+ u.crop.rect = *rect;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CROP, &u.crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = u.crop.rect;
+ return 0;
+}
+
+int v4l2_subdev_get_dv_timings_caps(struct media_entity *entity,
+ struct v4l2_dv_timings_cap *caps)
+{
+ unsigned int pad = caps->pad;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(caps, 0, sizeof(*caps));
+ caps->pad = pad;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_DV_TIMINGS_CAP, caps);
+ if (ret < 0)
+ return -errno;
+
+ return 0;
+}
+
+int v4l2_subdev_query_dv_timings(struct media_entity *entity,
+ struct v4l2_dv_timings *timings)
+{
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(timings, 0, sizeof(*timings));
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_QUERY_DV_TIMINGS, timings);
+ if (ret < 0)
+ return -errno;
+
+ return 0;
+}
+
+int v4l2_subdev_get_dv_timings(struct media_entity *entity,
+ struct v4l2_dv_timings *timings)
+{
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(timings, 0, sizeof(*timings));
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_DV_TIMINGS, timings);
+ if (ret < 0)
+ return -errno;
+
+ return 0;
+}
+
+int v4l2_subdev_set_dv_timings(struct media_entity *entity,
+ struct v4l2_dv_timings *timings)
+{
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_DV_TIMINGS, timings);
+ if (ret < 0)
+ return -errno;
+
+ return 0;
+}
+
+int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ struct v4l2_subdev_frame_interval ival;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&ival, 0, sizeof(ival));
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival);
+ if (ret < 0)
+ return -errno;
+
+ *interval = ival.interval;
+ return 0;
+}
+
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ struct v4l2_subdev_frame_interval ival;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&ival, 0, sizeof(ival));
+ ival.interval = *interval;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
+ if (ret < 0)
+ return -errno;
+
+ *interval = ival.interval;
+ return 0;
+}
+
+static int v4l2_subdev_parse_format(struct media_device *media,
+ struct v4l2_mbus_framefmt *format,
+ const char *p, char **endp)
+{
+ enum v4l2_mbus_pixelcode code;
+ unsigned int width, height;
+ char *end;
+
+ /*
+ * Compatibility with the old syntax: consider space as valid
+ * separator between the media bus pixel code and the size.
+ */
+ for (; isspace(*p); ++p);
+ for (end = (char *)p;
+ *end != '/' && *end != ' ' && *end != '\0'; ++end);
+
+ code = v4l2_subdev_string_to_pixelcode(p, end - p);
+ if (code == (enum v4l2_mbus_pixelcode)-1) {
+ media_dbg(media, "Invalid pixel code '%.*s'\n", end - p, p);
+ return -EINVAL;
+ }
+
+ p = end + 1;
+ width = strtoul(p, &end, 10);
+ if (*end != 'x') {
+ media_dbg(media, "Expected 'x'\n");
+ return -EINVAL;
+ }
+
+ p = end + 1;
+ height = strtoul(p, &end, 10);
+ *endp = end;
+
+ memset(format, 0, sizeof(*format));
+ format->width = width;
+ format->height = height;
+ format->code = code;
+
+ return 0;
+}
+
+static int v4l2_subdev_parse_rectangle(struct media_device *media,
+ struct v4l2_rect *r, const char *p,
+ char **endp)
+{
+ char *end;
+
+ if (*p++ != '(') {
+ media_dbg(media, "Expected '('\n");
+ *endp = (char *)p - 1;
+ return -EINVAL;
+ }
+
+ r->left = strtoul(p, &end, 10);
+ if (*end != ',') {
+ media_dbg(media, "Expected ','\n");
+ *endp = end;
+ return -EINVAL;
+ }
+
+ p = end + 1;
+ r->top = strtoul(p, &end, 10);
+ if (*end++ != ')') {
+ media_dbg(media, "Expected ')'\n");
+ *endp = end - 1;
+ return -EINVAL;
+ }
+ if (*end != '/') {
+ media_dbg(media, "Expected '/'\n");
+ *endp = end;
+ return -EINVAL;
+ }
+
+ p = end + 1;
+ r->width = strtoul(p, &end, 10);
+ if (*end != 'x') {
+ media_dbg(media, "Expected 'x'\n");
+ *endp = end;
+ return -EINVAL;
+ }
+
+ p = end + 1;
+ r->height = strtoul(p, &end, 10);
+ *endp = end;
+
+ return 0;
+}
+
+static int v4l2_subdev_parse_frame_interval(struct media_device *media,
+ struct v4l2_fract *interval,
+ const char *p, char **endp)
+{
+ char *end;
+
+ for (; isspace(*p); ++p);
+
+ interval->numerator = strtoul(p, &end, 10);
+
+ for (p = end; isspace(*p); ++p);
+ if (*p++ != '/') {
+ media_dbg(media, "Expected '/'\n");
+ *endp = (char *)p - 1;
+ return -EINVAL;
+ }
+
+ for (; isspace(*p); ++p);
+ interval->denominator = strtoul(p, &end, 10);
+
+ *endp = end;
+ return 0;
+}
+
+/*
+ * The debate over whether this function should be named icanhasstr() instead
+ * has been strong and heated. If you feel like this would be an important
+ * change, patches are welcome (or not).
+ */
+static bool strhazit(const char *str, const char **p)
+{
+ int len = strlen(str);
+
+ if (strncmp(str, *p, len))
+ return false;
+
+ for (*p += len; isspace(**p); ++*p);
+ return true;
+}
+
+static struct media_pad *v4l2_subdev_parse_pad_format(
+ struct media_device *media, struct v4l2_mbus_framefmt *format,
+ struct v4l2_rect *crop, struct v4l2_rect *compose,
+ struct v4l2_fract *interval, const char *p, char **endp)
+{
+ struct media_pad *pad;
+ bool first;
+ char *end;
+ int ret;
+
+ for (; isspace(*p); ++p);
+
+ pad = media_parse_pad(media, p, &end);
+ if (pad == NULL) {
+ *endp = end;
+ return NULL;
+ }
+
+ for (p = end; isspace(*p); ++p);
+ if (*p++ != '[') {
+ media_dbg(media, "Expected '['\n");
+ *endp = (char *)p - 1;
+ return NULL;
+ }
+
+ for (first = true; ; first = false) {
+ for (; isspace(*p); p++);
+
+ /*
+ * Backward compatibility: if the first property starts with an
+ * uppercase later, process it as a format description.
+ */
+ if (strhazit("fmt:", &p) || (first && isupper(*p))) {
+ ret = v4l2_subdev_parse_format(media, format, p, &end);
+ if (ret < 0) {
+ *endp = end;
+ return NULL;
+ }
+
+ p = end;
+ continue;
+ }
+
+ /*
+ * Backward compatibility: crop rectangles can be specified
+ * implicitly without the 'crop:' property name.
+ */
+ if (strhazit("crop:", &p) || *p == '(') {
+ ret = v4l2_subdev_parse_rectangle(media, crop, p, &end);
+ if (ret < 0) {
+ *endp = end;
+ return NULL;
+ }
+
+ p = end;
+ continue;
+ }
+
+ if (strhazit("compose:", &p)) {
+ ret = v4l2_subdev_parse_rectangle(media, compose, p, &end);
+ if (ret < 0) {
+ *endp = end;
+ return NULL;
+ }
+
+ for (p = end; isspace(*p); p++);
+ continue;
+ }
+
+ if (*p == '@') {
+ ret = v4l2_subdev_parse_frame_interval(media, interval, ++p, &end);
+ if (ret < 0) {
+ *endp = end;
+ return NULL;
+ }
+
+ p = end;
+ continue;
+ }
+
+ break;
+ }
+
+ if (*p != ']') {
+ media_dbg(media, "Expected ']'\n");
+ *endp = (char *)p;
+ return NULL;
+ }
+
+ *endp = (char *)p + 1;
+ return pad;
+}
+
+static int set_format(struct media_pad *pad,
+ struct v4l2_mbus_framefmt *format)
+{
+ int ret;
+
+ if (format->width == 0 || format->height == 0)
+ return 0;
+
+ media_dbg(pad->entity->media,
+ "Setting up format %s %ux%u on pad %s/%u\n",
+ v4l2_subdev_pixelcode_to_string(format->code),
+ format->width, format->height,
+ pad->entity->info.name, pad->index);
+
+ ret = v4l2_subdev_set_format(pad->entity, format, pad->index,
+ V4L2_SUBDEV_FORMAT_ACTIVE);
+ if (ret < 0) {
+ media_dbg(pad->entity->media,
+ "Unable to set format: %s (%d)\n",
+ strerror(-ret), ret);
+ return ret;
+ }
+
+ media_dbg(pad->entity->media,
+ "Format set: %s %ux%u\n",
+ v4l2_subdev_pixelcode_to_string(format->code),
+ format->width, format->height);
+
+ return 0;
+}
+
+static int set_selection(struct media_pad *pad, unsigned int target,
+ struct v4l2_rect *rect)
+{
+ int ret;
+
+ if (rect->left == -1 || rect->top == -1)
+ return 0;
+
+ media_dbg(pad->entity->media,
+ "Setting up selection target %u rectangle (%u,%u)/%ux%u on pad %s/%u\n",
+ target, rect->left, rect->top, rect->width, rect->height,
+ pad->entity->info.name, pad->index);
+
+ ret = v4l2_subdev_set_selection(pad->entity, rect, pad->index,
+ target, V4L2_SUBDEV_FORMAT_ACTIVE);
+ if (ret < 0) {
+ media_dbg(pad->entity->media,
+ "Unable to set selection rectangle: %s (%d)\n",
+ strerror(-ret), ret);
+ return ret;
+ }
+
+ media_dbg(pad->entity->media,
+ "Selection rectangle set: (%u,%u)/%ux%u\n",
+ rect->left, rect->top, rect->width, rect->height);
+
+ return 0;
+}
+
+static int set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ int ret;
+
+ if (interval->numerator == 0)
+ return 0;
+
+ media_dbg(entity->media,
+ "Setting up frame interval %u/%u on entity %s\n",
+ interval->numerator, interval->denominator,
+ entity->info.name);
+
+ ret = v4l2_subdev_set_frame_interval(entity, interval);
+ if (ret < 0) {
+ media_dbg(entity->media,
+ "Unable to set frame interval: %s (%d)",
+ strerror(-ret), ret);
+ return ret;
+ }
+
+ media_dbg(entity->media, "Frame interval set: %u/%u\n",
+ interval->numerator, interval->denominator);
+
+ return 0;
+}
+
+
+static int v4l2_subdev_parse_setup_format(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct v4l2_mbus_framefmt format = { 0, 0, 0 };
+ struct media_pad *pad;
+ struct v4l2_rect crop = { -1, -1, -1, -1 };
+ struct v4l2_rect compose = crop;
+ struct v4l2_fract interval = { 0, 0 };
+ unsigned int i;
+ char *end;
+ int ret;
+
+ pad = v4l2_subdev_parse_pad_format(media, &format, &crop, &compose,
+ &interval, p, &end);
+ if (pad == NULL) {
+ media_print_streampos(media, p, end);
+ media_dbg(media, "Unable to parse format\n");
+ return -EINVAL;
+ }
+
+ if (pad->flags & MEDIA_PAD_FL_SINK) {
+ ret = set_format(pad, &format);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = set_selection(pad, V4L2_SEL_TGT_CROP, &crop);
+ if (ret < 0)
+ return ret;
+
+ ret = set_selection(pad, V4L2_SEL_TGT_COMPOSE, &compose);
+ if (ret < 0)
+ return ret;
+
+ if (pad->flags & MEDIA_PAD_FL_SOURCE) {
+ ret = set_format(pad, &format);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = set_frame_interval(pad->entity, &interval);
+ if (ret < 0)
+ return ret;
+
+
+ /* If the pad is an output pad, automatically set the same format on
+ * the remote subdev input pads, if any.
+ */
+ if (pad->flags & MEDIA_PAD_FL_SOURCE) {
+ for (i = 0; i < pad->entity->num_links; ++i) {
+ struct media_link *link = &pad->entity->links[i];
+ struct v4l2_mbus_framefmt remote_format;
+
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+ continue;
+
+ if (link->source == pad &&
+ link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) {
+ remote_format = format;
+ set_format(link->sink, &remote_format);
+ }
+ }
+ }
+
+ *endp = end;
+ return 0;
+}
+
+int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p)
+{
+ char *end;
+ int ret;
+
+ do {
+ ret = v4l2_subdev_parse_setup_format(media, p, &end);
+ if (ret < 0)
+ return ret;
+
+ p = end + 1;
+ } while (*end == ',');
+
+ return *end ? -EINVAL : 0;
+}
+
+static struct {
+ const char *name;
+ enum v4l2_mbus_pixelcode code;
+} mbus_formats[] = {
+ { "Y8", V4L2_MBUS_FMT_Y8_1X8},
+ { "Y10", V4L2_MBUS_FMT_Y10_1X10 },
+ { "Y12", V4L2_MBUS_FMT_Y12_1X12 },
+ { "YUYV", V4L2_MBUS_FMT_YUYV8_1X16 },
+ { "YUYV1_5X8", V4L2_MBUS_FMT_YUYV8_1_5X8 },
+ { "YUYV2X8", V4L2_MBUS_FMT_YUYV8_2X8 },
+ { "UYVY", V4L2_MBUS_FMT_UYVY8_1X16 },
+ { "UYVY1_5X8", V4L2_MBUS_FMT_UYVY8_1_5X8 },
+ { "UYVY2X8", V4L2_MBUS_FMT_UYVY8_2X8 },
+ { "SBGGR8", V4L2_MBUS_FMT_SBGGR8_1X8 },
+ { "SGBRG8", V4L2_MBUS_FMT_SGBRG8_1X8 },
+ { "SGRBG8", V4L2_MBUS_FMT_SGRBG8_1X8 },
+ { "SRGGB8", V4L2_MBUS_FMT_SRGGB8_1X8 },
+ { "SBGGR10", V4L2_MBUS_FMT_SBGGR10_1X10 },
+ { "SGBRG10", V4L2_MBUS_FMT_SGBRG10_1X10 },
+ { "SGRBG10", V4L2_MBUS_FMT_SGRBG10_1X10 },
+ { "SRGGB10", V4L2_MBUS_FMT_SRGGB10_1X10 },
+ { "SBGGR10_DPCM8", V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 },
+ { "SGBRG10_DPCM8", V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 },
+ { "SGRBG10_DPCM8", V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 },
+ { "SRGGB10_DPCM8", V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 },
+ { "SBGGR12", V4L2_MBUS_FMT_SBGGR12_1X12 },
+ { "SGBRG12", V4L2_MBUS_FMT_SGBRG12_1X12 },
+ { "SGRBG12", V4L2_MBUS_FMT_SGRBG12_1X12 },
+ { "SRGGB12", V4L2_MBUS_FMT_SRGGB12_1X12 },
+ { "AYUV32", V4L2_MBUS_FMT_AYUV8_1X32 },
+ { "ARGB32", V4L2_MBUS_FMT_ARGB8888_1X32 },
+};
+
+const char *v4l2_subdev_pixelcode_to_string(enum v4l2_mbus_pixelcode code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
+ if (mbus_formats[i].code == code)
+ return mbus_formats[i].name;
+ }
+
+ return "unknown";
+}
+
+enum v4l2_mbus_pixelcode v4l2_subdev_string_to_pixelcode(const char *string,
+ unsigned int length)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
+ if (strncmp(mbus_formats[i].name, string, length) == 0)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(mbus_formats))
+ return (enum v4l2_mbus_pixelcode)-1;
+
+ return mbus_formats[i].code;
+}
diff --git a/utils/media-ctl/libv4l2subdev.pc.in b/utils/media-ctl/libv4l2subdev.pc.in
new file mode 100644
index 00000000..a601b781
--- /dev/null
+++ b/utils/media-ctl/libv4l2subdev.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libv4l2subdev
+Description: V4L2 subdevice library.
+Requires: libmediactl
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lv4l2subdev
diff --git a/utils/media-ctl/media-ctl.c b/utils/media-ctl/media-ctl.c
new file mode 100644
index 00000000..1c4dae45
--- /dev/null
+++ b/utils/media-ctl/media-ctl.c
@@ -0,0 +1,660 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <linux/media.h>
+#include <linux/types.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/v4l2-subdev.h>
+#include <linux/videodev2.h>
+
+#include "mediactl.h"
+#include "options.h"
+#include "tools.h"
+#include "v4l2subdev.h"
+
+/* -----------------------------------------------------------------------------
+ * Printing
+ */
+
+struct flag_name {
+ __u32 flag;
+ char *name;
+};
+
+static void print_flags(const struct flag_name *flag_names, unsigned int num_entries, __u32 flags)
+{
+ bool first = true;
+ unsigned int i;
+
+ for (i = 0; i < num_entries; i++) {
+ if (!(flags & flag_names[i].flag))
+ continue;
+ if (!first)
+ printf(",");
+ printf("%s", flag_names[i].name);
+ flags &= ~flag_names[i].flag;
+ first = false;
+ }
+
+ if (flags) {
+ if (!first)
+ printf(",");
+ printf("0x%x", flags);
+ }
+}
+
+static void v4l2_subdev_print_format(struct media_entity *entity,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_mbus_framefmt format;
+ struct v4l2_rect rect;
+ int ret;
+
+ ret = v4l2_subdev_get_format(entity, &format, pad, which);
+ if (ret != 0)
+ return;
+
+ printf("\t\t[fmt:%s/%ux%u",
+ v4l2_subdev_pixelcode_to_string(format.code),
+ format.width, format.height);
+
+ ret = v4l2_subdev_get_selection(entity, &rect, pad,
+ V4L2_SEL_TGT_CROP_BOUNDS,
+ which);
+ if (ret == 0)
+ printf("\n\t\t crop.bounds:(%u,%u)/%ux%u", rect.left, rect.top,
+ rect.width, rect.height);
+
+ ret = v4l2_subdev_get_selection(entity, &rect, pad,
+ V4L2_SEL_TGT_CROP,
+ which);
+ if (ret == 0)
+ printf("\n\t\t crop:(%u,%u)/%ux%u", rect.left, rect.top,
+ rect.width, rect.height);
+
+ ret = v4l2_subdev_get_selection(entity, &rect, pad,
+ V4L2_SEL_TGT_COMPOSE_BOUNDS,
+ which);
+ if (ret == 0)
+ printf("\n\t\t compose.bounds:(%u,%u)/%ux%u",
+ rect.left, rect.top, rect.width, rect.height);
+
+ ret = v4l2_subdev_get_selection(entity, &rect, pad,
+ V4L2_SEL_TGT_COMPOSE,
+ which);
+ if (ret == 0)
+ printf("\n\t\t compose:(%u,%u)/%ux%u",
+ rect.left, rect.top, rect.width, rect.height);
+
+ printf("]\n");
+}
+
+static const char *v4l2_dv_type_to_string(unsigned int type)
+{
+ static const struct {
+ __u32 type;
+ const char *name;
+ } types[] = {
+ { V4L2_DV_BT_656_1120, "BT.656/1120" },
+ };
+
+ static char unknown[20];
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(types); i++) {
+ if (types[i].type == type)
+ return types[i].name;
+ }
+
+ sprintf(unknown, "Unknown (%u)", type);
+ return unknown;
+}
+
+static const struct flag_name bt_standards[] = {
+ { V4L2_DV_BT_STD_CEA861, "CEA-861" },
+ { V4L2_DV_BT_STD_DMT, "DMT" },
+ { V4L2_DV_BT_STD_CVT, "CVT" },
+ { V4L2_DV_BT_STD_GTF, "GTF" },
+};
+
+static const struct flag_name bt_capabilities[] = {
+ { V4L2_DV_BT_CAP_INTERLACED, "interlaced" },
+ { V4L2_DV_BT_CAP_PROGRESSIVE, "progressive" },
+ { V4L2_DV_BT_CAP_REDUCED_BLANKING, "reduced-blanking" },
+ { V4L2_DV_BT_CAP_CUSTOM, "custom" },
+};
+
+static const struct flag_name bt_flags[] = {
+ { V4L2_DV_FL_REDUCED_BLANKING, "reduced-blanking" },
+ { V4L2_DV_FL_CAN_REDUCE_FPS, "can-reduce-fps" },
+ { V4L2_DV_FL_REDUCED_FPS, "reduced-fps" },
+ { V4L2_DV_FL_HALF_LINE, "half-line" },
+};
+
+static void v4l2_subdev_print_dv_timings(const struct v4l2_dv_timings *timings,
+ const char *name)
+{
+ printf("\t\t[dv.%s:%s", name, v4l2_dv_type_to_string(timings->type));
+
+ switch (timings->type) {
+ case V4L2_DV_BT_656_1120: {
+ const struct v4l2_bt_timings *bt = &timings->bt;
+ unsigned int htotal, vtotal;
+
+ htotal = V4L2_DV_BT_FRAME_WIDTH(bt);
+ vtotal = V4L2_DV_BT_FRAME_HEIGHT(bt);
+
+ printf(" %ux%u%s%llu (%ux%u)",
+ bt->width, bt->height, bt->interlaced ? "i" : "p",
+ (htotal * vtotal) > 0 ? (bt->pixelclock / (htotal * vtotal)) : 0,
+ htotal, vtotal);
+
+ printf(" stds:");
+ print_flags(bt_standards, ARRAY_SIZE(bt_standards),
+ bt->standards);
+ printf(" flags:");
+ print_flags(bt_flags, ARRAY_SIZE(bt_flags),
+ bt->flags);
+
+ break;
+ }
+ }
+
+ printf("]\n");
+}
+
+static void v4l2_subdev_print_pad_dv(struct media_entity *entity,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_dv_timings_cap caps;
+ int ret;
+
+ caps.pad = pad;
+ ret = v4l2_subdev_get_dv_timings_caps(entity, &caps);
+ if (ret != 0)
+ return;
+
+ printf("\t\t[dv.caps:%s", v4l2_dv_type_to_string(caps.type));
+
+ switch (caps.type) {
+ case V4L2_DV_BT_656_1120:
+ printf(" min:%ux%u@%llu max:%ux%u@%llu",
+ caps.bt.min_width, caps.bt.min_height, caps.bt.min_pixelclock,
+ caps.bt.max_width, caps.bt.max_height, caps.bt.max_pixelclock);
+
+ printf(" stds:");
+ print_flags(bt_standards, ARRAY_SIZE(bt_standards),
+ caps.bt.standards);
+ printf(" caps:");
+ print_flags(bt_capabilities, ARRAY_SIZE(bt_capabilities),
+ caps.bt.capabilities);
+
+ break;
+ }
+
+ printf("]\n");
+}
+
+static void v4l2_subdev_print_subdev_dv(struct media_entity *entity)
+{
+ struct v4l2_dv_timings timings;
+ int ret;
+
+ ret = v4l2_subdev_query_dv_timings(entity, &timings);
+ switch (ret) {
+ case -ENOLINK:
+ printf("\t\t[dv.query:no-link]\n");
+ break;
+ case -ENOLCK:
+ printf("\t\t[dv.query:no-lock]\n");
+ break;
+ case -ERANGE:
+ printf("\t\t[dv.query:out-of-range]\n");
+ break;
+ case 0:
+ v4l2_subdev_print_dv_timings(&timings, "detect");
+ break;
+ default:
+ return;
+ }
+
+ ret = v4l2_subdev_get_dv_timings(entity, &timings);
+ if (ret == 0)
+ v4l2_subdev_print_dv_timings(&timings, "current");
+}
+
+static const char *media_entity_type_to_string(unsigned type)
+{
+ static const struct {
+ __u32 type;
+ const char *name;
+ } types[] = {
+ { MEDIA_ENT_T_DEVNODE, "Node" },
+ { MEDIA_ENT_T_V4L2_SUBDEV, "V4L2 subdev" },
+ };
+
+ unsigned int i;
+
+ type &= MEDIA_ENT_TYPE_MASK;
+
+ for (i = 0; i < ARRAY_SIZE(types); i++) {
+ if (types[i].type == type)
+ return types[i].name;
+ }
+
+ return "Unknown";
+}
+
+static const char *media_entity_subtype_to_string(unsigned type)
+{
+ static const char *node_types[] = {
+ "Unknown",
+ "V4L",
+ "FB",
+ "ALSA",
+ "DVB",
+ };
+ static const char *subdev_types[] = {
+ "Unknown",
+ "Sensor",
+ "Flash",
+ "Lens",
+ };
+
+ unsigned int subtype = type & MEDIA_ENT_SUBTYPE_MASK;
+
+ switch (type & MEDIA_ENT_TYPE_MASK) {
+ case MEDIA_ENT_T_DEVNODE:
+ if (subtype >= ARRAY_SIZE(node_types))
+ subtype = 0;
+ return node_types[subtype];
+
+ case MEDIA_ENT_T_V4L2_SUBDEV:
+ if (subtype >= ARRAY_SIZE(subdev_types))
+ subtype = 0;
+ return subdev_types[subtype];
+ default:
+ return node_types[0];
+ }
+}
+
+static const char *media_pad_type_to_string(unsigned flag)
+{
+ static const struct {
+ __u32 flag;
+ const char *name;
+ } flags[] = {
+ { MEDIA_PAD_FL_SINK, "Sink" },
+ { MEDIA_PAD_FL_SOURCE, "Source" },
+ };
+
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(flags); i++) {
+ if (flags[i].flag & flag)
+ return flags[i].name;
+ }
+
+ return "Unknown";
+}
+
+static void media_print_topology_dot(struct media_device *media)
+{
+ unsigned int nents = media_get_entities_count(media);
+ unsigned int i, j;
+
+ printf("digraph board {\n");
+ printf("\trankdir=TB\n");
+
+ for (i = 0; i < nents; ++i) {
+ struct media_entity *entity = media_get_entity(media, i);
+ const struct media_entity_desc *info = media_entity_get_info(entity);
+ const char *devname = media_entity_get_devname(entity);
+ unsigned int num_links = media_entity_get_links_count(entity);
+ unsigned int npads;
+
+ switch (media_entity_type(entity)) {
+ case MEDIA_ENT_T_DEVNODE:
+ printf("\tn%08x [label=\"%s\\n%s\", shape=box, style=filled, "
+ "fillcolor=yellow]\n",
+ info->id, info->name, devname);
+ break;
+
+ case MEDIA_ENT_T_V4L2_SUBDEV:
+ printf("\tn%08x [label=\"{{", info->id);
+
+ for (j = 0, npads = 0; j < info->pads; ++j) {
+ const struct media_pad *pad = media_entity_get_pad(entity, j);
+
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ continue;
+
+ printf("%s<port%u> %u", npads ? " | " : "", j, j);
+ npads++;
+ }
+
+ printf("} | %s", info->name);
+ if (devname)
+ printf("\\n%s", devname);
+ printf(" | {");
+
+ for (j = 0, npads = 0; j < info->pads; ++j) {
+ const struct media_pad *pad = media_entity_get_pad(entity, j);
+
+ if (!(pad->flags & MEDIA_PAD_FL_SOURCE))
+ continue;
+
+ printf("%s<port%u> %u", npads ? " | " : "", j, j);
+ npads++;
+ }
+
+ printf("}}\", shape=Mrecord, style=filled, fillcolor=green]\n");
+ break;
+
+ default:
+ continue;
+ }
+
+ for (j = 0; j < num_links; j++) {
+ const struct media_link *link = media_entity_get_link(entity, j);
+ const struct media_pad *source = link->source;
+ const struct media_pad *sink = link->sink;
+
+ if (source->entity != entity)
+ continue;
+
+ printf("\tn%08x", media_entity_get_info(source->entity)->id);
+ if (media_entity_type(source->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
+ printf(":port%u", source->index);
+ printf(" -> ");
+ printf("n%08x", media_entity_get_info(sink->entity)->id);
+ if (media_entity_type(sink->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
+ printf(":port%u", sink->index);
+
+ if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
+ printf(" [style=bold]");
+ else if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+ printf(" [style=dashed]");
+ printf("\n");
+ }
+ }
+
+ printf("}\n");
+}
+
+static void media_print_pad_text(struct media_entity *entity,
+ const struct media_pad *pad)
+{
+ if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ return;
+
+ v4l2_subdev_print_format(entity, pad->index, V4L2_SUBDEV_FORMAT_ACTIVE);
+ v4l2_subdev_print_pad_dv(entity, pad->index, V4L2_SUBDEV_FORMAT_ACTIVE);
+
+ if (pad->flags & MEDIA_PAD_FL_SOURCE)
+ v4l2_subdev_print_subdev_dv(entity);
+}
+
+static void media_print_topology_text(struct media_device *media)
+{
+ static const struct flag_name link_flags[] = {
+ { MEDIA_LNK_FL_ENABLED, "ENABLED" },
+ { MEDIA_LNK_FL_IMMUTABLE, "IMMUTABLE" },
+ { MEDIA_LNK_FL_DYNAMIC, "DYNAMIC" },
+ };
+
+ unsigned int nents = media_get_entities_count(media);
+ unsigned int i, j, k;
+ unsigned int padding;
+
+ printf("Device topology\n");
+
+ for (i = 0; i < nents; ++i) {
+ struct media_entity *entity = media_get_entity(media, i);
+ const struct media_entity_desc *info = media_entity_get_info(entity);
+ const char *devname = media_entity_get_devname(entity);
+ unsigned int num_links = media_entity_get_links_count(entity);
+
+ padding = printf("- entity %u: ", info->id);
+ printf("%s (%u pad%s, %u link%s)\n", info->name,
+ info->pads, info->pads > 1 ? "s" : "",
+ num_links, num_links > 1 ? "s" : "");
+ printf("%*ctype %s subtype %s flags %x\n", padding, ' ',
+ media_entity_type_to_string(info->type),
+ media_entity_subtype_to_string(info->type),
+ info->flags);
+ if (devname)
+ printf("%*cdevice node name %s\n", padding, ' ', devname);
+
+ for (j = 0; j < info->pads; j++) {
+ const struct media_pad *pad = media_entity_get_pad(entity, j);
+
+ printf("\tpad%u: %s\n", j, media_pad_type_to_string(pad->flags));
+
+ media_print_pad_text(entity, pad);
+
+ for (k = 0; k < num_links; k++) {
+ const struct media_link *link = media_entity_get_link(entity, k);
+ const struct media_pad *source = link->source;
+ const struct media_pad *sink = link->sink;
+
+ if (source->entity == entity && source->index == j)
+ printf("\t\t-> \"%s\":%u [",
+ media_entity_get_info(sink->entity)->name,
+ sink->index);
+ else if (sink->entity == entity && sink->index == j)
+ printf("\t\t<- \"%s\":%u [",
+ media_entity_get_info(source->entity)->name,
+ source->index);
+ else
+ continue;
+
+ print_flags(link_flags, ARRAY_SIZE(link_flags), link->flags);
+
+ printf("]\n");
+ }
+ }
+ printf("\n");
+ }
+}
+
+void media_print_topology(struct media_device *media, int dot)
+{
+ if (dot)
+ media_print_topology_dot(media);
+ else
+ media_print_topology_text(media);
+}
+
+int main(int argc, char **argv)
+{
+ struct media_device *media;
+ int ret = -1;
+
+ if (parse_cmdline(argc, argv))
+ return EXIT_FAILURE;
+
+ media = media_device_new(media_opts.devname);
+ if (media == NULL) {
+ printf("Failed to create media device\n");
+ goto out;
+ }
+
+ if (media_opts.verbose)
+ media_debug_set_handler(media,
+ (void (*)(void *, ...))fprintf, stdout);
+
+ /* Enumerate entities, pads and links. */
+ ret = media_device_enumerate(media);
+ if (ret < 0) {
+ printf("Failed to enumerate %s (%d)\n", media_opts.devname, ret);
+ goto out;
+ }
+
+ if (media_opts.print) {
+ const struct media_device_info *info = media_get_info(media);
+
+ printf("Media controller API version %u.%u.%u\n\n",
+ (info->media_version >> 16) & 0xff,
+ (info->media_version >> 8) & 0xff,
+ (info->media_version >> 0) & 0xff);
+ printf("Media device information\n"
+ "------------------------\n"
+ "driver %s\n"
+ "model %s\n"
+ "serial %s\n"
+ "bus info %s\n"
+ "hw revision 0x%x\n"
+ "driver version %u.%u.%u\n\n",
+ info->driver, info->model,
+ info->serial, info->bus_info,
+ info->hw_revision,
+ (info->driver_version >> 16) & 0xff,
+ (info->driver_version >> 8) & 0xff,
+ (info->driver_version >> 0) & 0xff);
+ }
+
+ if (media_opts.entity) {
+ struct media_entity *entity;
+
+ entity = media_get_entity_by_name(media, media_opts.entity,
+ strlen(media_opts.entity));
+ if (entity == NULL) {
+ printf("Entity '%s' not found\n", media_opts.entity);
+ goto out;
+ }
+
+ printf("%s\n", media_entity_get_devname(entity));
+ }
+
+ if (media_opts.fmt_pad) {
+ struct media_pad *pad;
+
+ pad = media_parse_pad(media, media_opts.fmt_pad, NULL);
+ if (pad == NULL) {
+ printf("Pad '%s' not found\n", media_opts.fmt_pad);
+ goto out;
+ }
+
+ v4l2_subdev_print_format(pad->entity, pad->index,
+ V4L2_SUBDEV_FORMAT_ACTIVE);
+ }
+
+ if (media_opts.dv_pad) {
+ struct v4l2_dv_timings timings;
+ struct media_pad *pad;
+
+ pad = media_parse_pad(media, media_opts.dv_pad, NULL);
+ if (pad == NULL) {
+ printf("Pad '%s' not found\n", media_opts.dv_pad);
+ goto out;
+ }
+
+ ret = v4l2_subdev_query_dv_timings(pad->entity, &timings);
+ if (ret < 0) {
+ printf("Failed to query DV timings: %s\n", strerror(-ret));
+ goto out;
+ }
+
+ ret = v4l2_subdev_set_dv_timings(pad->entity, &timings);
+ if (ret < 0) {
+ printf("Failed to set DV timings: %s\n", strerror(-ret));
+ goto out;
+ }
+ }
+
+ if (media_opts.print || media_opts.print_dot) {
+ media_print_topology(media, media_opts.print_dot);
+ printf("\n");
+ }
+
+ if (media_opts.reset) {
+ if (media_opts.verbose)
+ printf("Resetting all links to inactive\n");
+ ret = media_reset_links(media);
+ if (ret) {
+ printf("Unable to reset links: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto out;
+ }
+ }
+
+ if (media_opts.links) {
+ ret = media_parse_setup_links(media, media_opts.links);
+ if (ret) {
+ printf("Unable to parse link: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto out;
+ }
+ }
+
+ if (media_opts.formats) {
+ ret = v4l2_subdev_parse_setup_formats(media,
+ media_opts.formats);
+ if (ret) {
+ printf("Unable to setup formats: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto out;
+ }
+ }
+
+ if (media_opts.interactive) {
+ while (1) {
+ char buffer[32];
+ char *end;
+
+ printf("Enter a link to modify or enter to stop\n");
+ if (fgets(buffer, sizeof buffer, stdin) == NULL)
+ break;
+
+ if (buffer[0] == '\n')
+ break;
+
+ ret = media_parse_setup_link(media, buffer, &end);
+ if (ret)
+ printf("Unable to parse link: %s (%d)\n",
+ strerror(-ret), -ret);
+ }
+ }
+
+ ret = 0;
+
+out:
+ if (media)
+ media_device_unref(media);
+
+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
diff --git a/utils/media-ctl/mediactl-priv.h b/utils/media-ctl/mediactl-priv.h
new file mode 100644
index 00000000..a0d3a55a
--- /dev/null
+++ b/utils/media-ctl/mediactl-priv.h
@@ -0,0 +1,64 @@
+/*
+ * Media controller interface library
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MEDIA_PRIV_H__
+#define __MEDIA_PRIV_H__
+
+#include <linux/media.h>
+
+#include "mediactl.h"
+
+struct media_entity {
+ struct media_device *media;
+ struct media_entity_desc info;
+ struct media_pad *pads;
+ struct media_link *links;
+ unsigned int max_links;
+ unsigned int num_links;
+
+ char devname[32];
+ int fd;
+};
+
+struct media_device {
+ int fd;
+ int refcount;
+ char *devnode;
+
+ struct media_device_info info;
+ struct media_entity *entities;
+ unsigned int entities_count;
+
+ void (*debug_handler)(void *, ...);
+ void *debug_priv;
+
+ struct {
+ struct media_entity *v4l;
+ struct media_entity *fb;
+ struct media_entity *alsa;
+ struct media_entity *dvb;
+ } def;
+};
+
+#define media_dbg(media, ...) \
+ (media)->debug_handler((media)->debug_priv, __VA_ARGS__)
+
+#endif /* __MEDIA_PRIV_H__ */
diff --git a/utils/media-ctl/mediactl.h b/utils/media-ctl/mediactl.h
new file mode 100644
index 00000000..77ac1820
--- /dev/null
+++ b/utils/media-ctl/mediactl.h
@@ -0,0 +1,423 @@
+/*
+ * Media controller interface library
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MEDIA_H__
+#define __MEDIA_H__
+
+#include <linux/media.h>
+
+struct media_link {
+ struct media_pad *source;
+ struct media_pad *sink;
+ struct media_link *twin;
+ __u32 flags;
+ __u32 padding[3];
+};
+
+struct media_pad {
+ struct media_entity *entity;
+ __u32 index;
+ __u32 flags;
+ __u32 padding[3];
+};
+
+struct media_device;
+struct media_entity;
+
+/**
+ * @brief Create a new media device.
+ * @param devnode - device node path.
+ *
+ * Create a media device instance for the given device node and return it. The
+ * device node is not accessed by this function, device node access errors will
+ * not be caught and reported here. The media device needs to be enumerated
+ * before it can be accessed, see media_device_enumerate().
+ *
+ * Media devices are reference-counted, see media_device_ref() and
+ * media_device_unref() for more information.
+ *
+ * @return A pointer to the new media device or NULL if memory cannot be
+ * allocated.
+ */
+struct media_device *media_device_new(const char *devnode);
+
+/**
+ * @brief Create a new emulated media device.
+ * @param info - device information.
+ *
+ * Emulated media devices are userspace-only objects not backed by a kernel
+ * media device. They are created for ALSA and V4L2 devices that are not
+ * associated with a media controller device.
+ *
+ * Only device query functions are available for media devices. Enumerating or
+ * setting up links is invalid.
+ *
+ * @return A pointer to the new media device or NULL if memory cannot be
+ * allocated.
+ */
+struct media_device *media_device_new_emulated(struct media_device_info *info);
+
+/**
+ * @brief Take a reference to the device.
+ * @param media - device instance.
+ *
+ * Media devices are reference-counted. Taking a reference to a device prevents
+ * it from being freed until all references are released. The reference count is
+ * initialized to 1 when the device is created.
+ *
+ * @return A pointer to @a media.
+ */
+struct media_device *media_device_ref(struct media_device *media);
+
+/**
+ * @brief Release a reference to the device.
+ * @param media - device instance.
+ *
+ * Release a reference to the media device. When the reference count reaches 0
+ * this function frees the device.
+ */
+void media_device_unref(struct media_device *media);
+
+/**
+ * @brief Add an entity to an existing media device
+ * @param media - device instance.
+ * @param desc - description of the entity to be added
+ * @param devnode - device node corresponding to the entity
+ *
+ * Entities are usually created and added to media devices automatically when
+ * the media device is enumerated through the media controller API. However,
+ * when an emulated media device (thus not backed with a kernel-side media
+ * controller device) is created, entities need to be manually added.
+ *
+ * Entities can also be manually added to a successfully enumerated media device
+ * to group several functions provided by separate kernel devices. The most
+ * common use case is to group the audio and video functions of a USB webcam in
+ * a single media device. Those functions are exposed through separate USB
+ * interfaces and handled through unrelated kernel drivers, they must thus be
+ * manually added to the same media device.
+ *
+ * This function adds a new entity to the given media device and initializes it
+ * from the given entity description and device node name. Only the following
+ * fields of the description are copied over to the new entity:
+ *
+ * - type
+ * - flags (MEDIA_ENT_FL_DEFAULT only)
+ * - name
+ * - v4l, fb, alsa or dvb (depending on the device type)
+ *
+ * All other fields of the newly created entity id are initialized to 0,
+ * including the entity ID.
+ *
+ * @return Zero on success or -ENOMEM if memory cannot be allocated.
+ */
+int media_device_add_entity(struct media_device *media,
+ const struct media_entity_desc *desc,
+ const char *devnode);
+
+/**
+ * @brief Set a handler for debug messages.
+ * @param media - device instance.
+ * @param debug_handler - debug message handler
+ * @param debug_priv - first argument to debug message handler
+ *
+ * Set a handler for debug messages that will be called whenever
+ * debugging information is to be printed. The handler expects an
+ * fprintf-like function.
+ */
+void media_debug_set_handler(
+ struct media_device *media, void (*debug_handler)(void *, ...),
+ void *debug_priv);
+
+/**
+ * @brief Enumerate the device topology
+ * @param media - device instance.
+ *
+ * Enumerate the media device entities, pads and links. Calling this function is
+ * mandatory before accessing the media device contents.
+ *
+ * @return Zero on success or a negative error code on failure.
+ */
+int media_device_enumerate(struct media_device *media);
+
+/**
+ * @brief Locate the pad at the other end of a link.
+ * @param pad - sink pad at one end of the link.
+ *
+ * Locate the source pad connected to @a pad through an enabled link. As only one
+ * link connected to a sink pad can be enabled at a time, the connected source
+ * pad is guaranteed to be unique.
+ *
+ * @return A pointer to the connected source pad, or NULL if all links connected
+ * to @a pad are disabled. Return NULL also if @a pad is not a sink pad.
+ */
+struct media_pad *media_entity_remote_source(struct media_pad *pad);
+
+/**
+ * @brief Get information about a media entity
+ * @param entity - media entity.
+ *
+ * The information structure is owned by the media entity object and will be
+ * freed when the object is destroyed.
+ *
+ * @return A pointer to the media entity information
+ */
+const struct media_entity_desc *media_entity_get_info(struct media_entity *entity);
+
+/**
+ * @brief Get an entity pad
+ * @param entity - media entity.
+ * @param index - pad index.
+ *
+ * This function returns a pointer to the pad object identified by its index
+ * for the given entity. If the pad index is out of bounds it will return NULL.
+ *
+ * @return A pointer to the pad
+ */
+const struct media_pad *media_entity_get_pad(struct media_entity *entity,
+ unsigned int index);
+
+/**
+ * @brief Get the number of links
+ * @param entity - media entity.
+ *
+ * This function returns the total number of links that originate from or arrive
+ * at the the media entity.
+ *
+ * @return The number of links for the entity
+ */
+unsigned int media_entity_get_links_count(struct media_entity *entity);
+
+/**
+ * @brief Get an entity link
+ * @param entity - media entity.
+ * @param index - link index.
+ *
+ * This function returns a pointer to the link object identified by its index
+ * for the given entity. If the link index is out of bounds it will return NULL.
+ *
+ * @return A pointer to the link
+ */
+const struct media_link *media_entity_get_link(struct media_entity *entity,
+ unsigned int index);
+
+/**
+ * @brief Get the device node name for an entity
+ * @param entity - media entity.
+ *
+ * This function returns the full path and name to the device node corresponding
+ * to the given entity.
+ *
+ * @return A pointer to the device node name or NULL if the entity has no
+ * associated device node
+ */
+const char *media_entity_get_devname(struct media_entity *entity);
+
+/**
+ * @brief Get the type of an entity.
+ * @param entity - the entity.
+ *
+ * @return The type of @a entity.
+ */
+static inline unsigned int media_entity_type(struct media_entity *entity)
+{
+ return media_entity_get_info(entity)->type & MEDIA_ENT_TYPE_MASK;
+}
+
+/**
+ * @brief Find an entity by its name.
+ * @param media - media device.
+ * @param name - entity name.
+ * @param length - size of @a name.
+ *
+ * Search for an entity with a name equal to @a name.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *media_get_entity_by_name(struct media_device *media,
+ const char *name, size_t length);
+
+/**
+ * @brief Find an entity by its ID.
+ * @param media - media device.
+ * @param id - entity ID.
+ *
+ * This function searches for an entity based on its ID using an exact match or
+ * next ID method based on the given @a id. If @a id is ORed with
+ * MEDIA_ENT_ID_FLAG_NEXT, the function will return the entity with the smallest
+ * ID larger than @a id. Otherwise it will return the entity with an ID equal to
+ * @a id.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *media_get_entity_by_id(struct media_device *media,
+ __u32 id);
+
+/**
+ * @brief Get the number of entities
+ * @param media - media device.
+ *
+ * This function returns the total number of entities in the media device. If
+ * entities haven't been enumerated yet it will return 0.
+ *
+ * @return The number of entities in the media device
+ */
+unsigned int media_get_entities_count(struct media_device *media);
+
+/**
+ * @brief Get the entities
+ * @param media - media device.
+ *
+ * This function returns a pointer to the array of entities for the media
+ * device. If entities haven't been enumerated yet it will return NULL.
+ *
+ * The array of entities is owned by the media device object and will be freed
+ * when the media object is destroyed.
+ *
+ * @return A pointer to an array of entities
+ */
+struct media_entity *media_get_entity(struct media_device *media, unsigned int index);
+
+/**
+ * @brief Get the default entity for a given type
+ * @param media - media device.
+ * @param type - entity type.
+ *
+ * This function returns the default entity of the requested type. @a type must
+ * be one of
+ *
+ * MEDIA_ENT_T_DEVNODE_V4L
+ * MEDIA_ENT_T_DEVNODE_FB
+ * MEDIA_ENT_T_DEVNODE_ALSA
+ * MEDIA_ENT_T_DEVNODE_DVB
+ *
+ * @return A pointer to the default entity for the type if it exists, or NULL
+ * otherwise.
+ */
+struct media_entity *media_get_default_entity(struct media_device *media,
+ unsigned int type);
+
+/**
+ * @brief Get the media device information
+ * @param media - media device.
+ *
+ * The information structure is owned by the media device object and will be freed
+ * when the media object is destroyed.
+ *
+ * @return A pointer to the media device information
+ */
+const struct media_device_info *media_get_info(struct media_device *media);
+
+/**
+ * @brief Get the media device node name
+ * @param media - media device.
+ *
+ * The device node name string is owned by the media device object and will be
+ * freed when the media object is destroyed.
+ *
+ * @return A pointer to the media device node name
+ */
+const char *media_get_devnode(struct media_device *media);
+
+/**
+ * @brief Configure a link.
+ * @param media - media device.
+ * @param source - source pad at the link origin.
+ * @param sink - sink pad at the link target.
+ * @param flags - configuration flags.
+ *
+ * Locate the link between @a source and @a sink, and configure it by applying
+ * the new @a flags.
+ *
+ * Only the MEDIA_LINK_FLAG_ENABLED flag is writable.
+ *
+ * @return 0 on success, -1 on failure:
+ * -ENOENT: link not found
+ * - other error codes returned by MEDIA_IOC_SETUP_LINK
+ */
+int media_setup_link(struct media_device *media,
+ struct media_pad *source, struct media_pad *sink,
+ __u32 flags);
+
+/**
+ * @brief Reset all links to the disabled state.
+ * @param media - media device.
+ *
+ * Disable all links in the media device. This function is usually used after
+ * opening a media device to reset all links to a known state.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_reset_links(struct media_device *media);
+
+/**
+ * @brief Parse string to a pad on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string where parsing ended
+ *
+ * Parse NULL terminated string describing a pad and return its struct
+ * media_pad instance.
+ *
+ * @return Pointer to struct media_pad on success, NULL on failure.
+ */
+struct media_pad *media_parse_pad(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to a link on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to p where parsing ended
+ *
+ * Parse NULL terminated string p describing a link and return its struct
+ * media_link instance.
+ *
+ * @return Pointer to struct media_link on success, NULL on failure.
+ */
+struct media_link *media_parse_link(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to a link on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing a link and its configuration
+ * and configure the link.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_parse_setup_link(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to link(s) on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing link(s) separated by
+ * commas (,) and configure the link(s).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_parse_setup_links(struct media_device *media, const char *p);
+
+#endif
diff --git a/utils/media-ctl/options.c b/utils/media-ctl/options.c
new file mode 100644
index 00000000..ffaffcd5
--- /dev/null
+++ b/utils/media-ctl/options.c
@@ -0,0 +1,178 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "options.h"
+
+#define MEDIA_DEVNAME_DEFAULT "/dev/media0"
+
+struct media_options media_opts = {
+ .devname = MEDIA_DEVNAME_DEFAULT,
+};
+
+static void usage(const char *argv0)
+{
+ printf("%s [options]\n", argv0);
+ printf("-d, --device dev Media device name (default: %s)\n", MEDIA_DEVNAME_DEFAULT);
+ printf("-e, --entity name Print the device name associated with the given entity\n");
+ printf("-V, --set-v4l2 v4l2 Comma-separated list of formats to setup\n");
+ printf(" --get-v4l2 pad Print the active format on a given pad\n");
+ printf(" --set-dv pad Configure DV timings on a given pad\n");
+ printf("-h, --help Show verbose help and exit\n");
+ printf("-i, --interactive Modify links interactively\n");
+ printf("-l, --links links Comma-separated list of link descriptors to setup\n");
+ printf("-p, --print-topology Print the device topology\n");
+ printf(" --print-dot Print the device topology as a dot graph\n");
+ printf("-r, --reset Reset all links to inactive\n");
+ printf("-v, --verbose Be verbose\n");
+ printf("\n");
+ printf("Links and formats are defined as\n");
+ printf("\tlinks = link { ',' link } ;\n");
+ printf("\tlink = pad '->' pad '[' flags ']' ;\n");
+ printf("\tpad = entity ':' pad-number ;\n");
+ printf("\tentity = entity-number | ( '\"' entity-name '\"' ) ;\n");
+ printf("\n");
+ printf("\tv4l2 = pad '[' v4l2-properties ']' ;\n");
+ printf("\tv4l2-properties = v4l2-property { ',' v4l2-property } ;\n");
+ printf("\tv4l2-property = v4l2-mbusfmt | v4l2-crop | v4l2-interval\n");
+ printf("\t | v4l2-compose | v4l2-interval ;\n");
+ printf("\tv4l2-mbusfmt = 'fmt:' fcc '/' size ;\n");
+ printf("\tv4l2-crop = 'crop:' rectangle ;\n");
+ printf("\tv4l2-compose = 'compose:' rectangle ;\n");
+ printf("\tv4l2-interval = '@' numerator '/' denominator ;\n");
+ printf("\n");
+ printf("\trectangle = '(' left ',' top, ')' '/' size ;\n");
+ printf("\tsize = width 'x' height ;\n");
+ printf("\n");
+ printf("where the fields are\n");
+ printf("\tentity-number Entity numeric identifier\n");
+ printf("\tentity-name Entity name (string) \n");
+ printf("\tpad-number Pad numeric identifier\n");
+ printf("\tflags Link flags (0: inactive, 1: active)\n");
+ printf("\tfcc Format FourCC\n");
+ printf("\twidth Image width in pixels\n");
+ printf("\theight Image height in pixels\n");
+ printf("\tnumerator Frame interval numerator\n");
+ printf("\tdenominator Frame interval denominator\n");
+}
+
+#define OPT_PRINT_DOT 256
+#define OPT_GET_FORMAT 257
+#define OPT_SET_DV 258
+
+static struct option opts[] = {
+ {"device", 1, 0, 'd'},
+ {"entity", 1, 0, 'e'},
+ {"set-format", 1, 0, 'f'},
+ {"set-v4l2", 1, 0, 'V'},
+ {"get-format", 1, 0, OPT_GET_FORMAT},
+ {"get-v4l2", 1, 0, OPT_GET_FORMAT},
+ {"set-dv", 1, 0, OPT_SET_DV},
+ {"help", 0, 0, 'h'},
+ {"interactive", 0, 0, 'i'},
+ {"links", 1, 0, 'l'},
+ {"print-dot", 0, 0, OPT_PRINT_DOT},
+ {"print-topology", 0, 0, 'p'},
+ {"reset", 0, 0, 'r'},
+ {"verbose", 0, 0, 'v'},
+};
+
+int parse_cmdline(int argc, char **argv)
+{
+ int opt;
+
+ if (argc == 1) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ /* parse options */
+ while ((opt = getopt_long(argc, argv, "d:e:f:hil:prvV:", opts, NULL)) != -1) {
+ switch (opt) {
+ case 'd':
+ media_opts.devname = optarg;
+ break;
+
+ case 'e':
+ media_opts.entity = optarg;
+ break;
+
+ /* 'f' is supported for backward compatibility reasons and will
+ * be removed later.
+ */
+ case 'f':
+ fprintf(stderr, "Warning: the -f option is deprecated "
+ "and has been replaced by -V.\n");
+ /* fall through */
+ case 'V':
+ media_opts.formats = optarg;
+ break;
+
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+
+ case 'i':
+ media_opts.interactive = 1;
+ break;
+
+ case 'l':
+ media_opts.links = optarg;
+ break;
+
+ case 'p':
+ media_opts.print = 1;
+ break;
+
+ case 'r':
+ media_opts.reset = 1;
+ break;
+
+ case 'v':
+ media_opts.verbose = 1;
+ break;
+
+ case OPT_PRINT_DOT:
+ media_opts.print_dot = 1;
+ break;
+
+ case OPT_GET_FORMAT:
+ media_opts.fmt_pad = optarg;
+ break;
+
+ case OPT_SET_DV:
+ media_opts.dv_pad = optarg;
+ break;
+
+ default:
+ printf("Invalid option -%c\n", opt);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/utils/media-ctl/options.h b/utils/media-ctl/options.h
new file mode 100644
index 00000000..9b5f314e
--- /dev/null
+++ b/utils/media-ctl/options.h
@@ -0,0 +1,45 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OPTIONS_H
+#define __OPTIONS_H
+
+struct media_options
+{
+ const char *devname;
+ unsigned int interactive:1,
+ print:1,
+ print_dot:1,
+ reset:1,
+ verbose:1;
+ const char *entity;
+ const char *formats;
+ const char *links;
+ const char *fmt_pad;
+ const char *dv_pad;
+};
+
+extern struct media_options media_opts;
+
+extern int parse_cmdline(int argc, char **argv);
+
+#endif /* __OPTIONS_H */
+
diff --git a/utils/media-ctl/tools.h b/utils/media-ctl/tools.h
new file mode 100644
index 00000000..815534ce
--- /dev/null
+++ b/utils/media-ctl/tools.h
@@ -0,0 +1,32 @@
+/*
+ * Media controller test application
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOLS_H__
+#define __TOOLS_H__
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+
+void media_print_streampos(struct media_device *media, const char *p,
+ const char *end);
+
+#endif /* __TOOLS_H__ */
+
diff --git a/utils/media-ctl/v4l2subdev.h b/utils/media-ctl/v4l2subdev.h
new file mode 100644
index 00000000..1cb53ffb
--- /dev/null
+++ b/utils/media-ctl/v4l2subdev.h
@@ -0,0 +1,258 @@
+/*
+ * V4L2 subdev interface library
+ *
+ * Copyright (C) 2010-2014 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SUBDEV_H__
+#define __SUBDEV_H__
+
+#include <linux/v4l2-subdev.h>
+
+struct media_entity;
+
+/**
+ * @brief Open a sub-device.
+ * @param entity - sub-device media entity.
+ *
+ * Open the V4L2 subdev device node associated with @a entity. The file
+ * descriptor is stored in the media_entity structure.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_open(struct media_entity *entity);
+
+/**
+ * @brief Close a sub-device.
+ * @param entity - sub-device media entity.
+ *
+ * Close the V4L2 subdev device node associated with the @a entity and opened by
+ * a previous call to v4l2_subdev_open() (either explicit or implicit).
+ */
+void v4l2_subdev_close(struct media_entity *entity);
+
+/**
+ * @brief Retrieve the format on a pad.
+ * @param entity - subdev-device media entity.
+ * @param format - format to be filled.
+ * @param pad - pad number.
+ * @param which - identifier of the format to get.
+ *
+ * Retrieve the current format on the @a entity @a pad and store it in the
+ * @a format structure.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try format stored
+ * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the current
+ * active format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Set the format on a pad.
+ * @param entity - subdev-device media entity.
+ * @param format - format.
+ * @param pad - pad number.
+ * @param which - identifier of the format to set.
+ *
+ * Set the format on the @a entity @a pad to @a format. The driver is allowed to
+ * modify the requested format, in which case @a format is updated with the
+ * modifications.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try format stored in the
+ * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the device with an
+ * active format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Retrieve a selection rectangle on a pad.
+ * @param entity - subdev-device media entity.
+ * @param r - rectangle to be filled.
+ * @param pad - pad number.
+ * @param target - selection target
+ * @param which - identifier of the format to get.
+ *
+ * Retrieve the @a target selection rectangle on the @a entity @a pad
+ * and store it in the @a rect structure.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try
+ * selection rectangle stored in the file handle, or
+ * V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the current active selection
+ * rectangle.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_selection(struct media_entity *entity,
+ struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Set a selection rectangle on a pad.
+ * @param entity - subdev-device media entity.
+ * @param rect - crop rectangle.
+ * @param pad - pad number.
+ * @param target - selection target
+ * @param which - identifier of the format to set.
+ *
+ * Set the @a target selection rectangle on the @a entity @a pad to @a
+ * rect. The driver is allowed to modify the requested rectangle, in
+ * which case @a rect is updated with the modifications.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try crop rectangle
+ * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the
+ * device with an active crop rectangle.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_selection(struct media_entity *entity,
+ struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Query the digital video capabilities of a pad.
+ * @param entity - subdev-device media entity.
+ * @param cap - capabilities to be filled.
+ *
+ * Retrieve the digital video capabilities of the @a entity pad specified by
+ * @a cap.pad and store it in the @a cap structure.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_dv_timings_caps(struct media_entity *entity,
+ struct v4l2_dv_timings_cap *caps);
+
+/**
+ * @brief Query the digital video timings of a sub-device
+ * @param entity - subdev-device media entity.
+ * @param timings timings to be filled.
+ *
+ * Retrieve the detected digital video timings for the currently selected input
+ * of @a entity and store them in the @a timings structure.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_query_dv_timings(struct media_entity *entity,
+ struct v4l2_dv_timings *timings);
+
+/**
+ * @brief Get the current digital video timings of a sub-device
+ * @param entity - subdev-device media entity.
+ * @param timings timings to be filled.
+ *
+ * Retrieve the current digital video timings for the currently selected input
+ * of @a entity and store them in the @a timings structure.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_dv_timings(struct media_entity *entity,
+ struct v4l2_dv_timings *timings);
+
+/**
+ * @brief Set the digital video timings of a sub-device
+ * @param entity - subdev-device media entity.
+ * @param timings timings to be set.
+ *
+ * Set the digital video timings of @a entity to @a timings. The driver is
+ * allowed to modify the requested format, in which case @a timings is updated
+ * with the modifications.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_dv_timings(struct media_entity *entity,
+ struct v4l2_dv_timings *timings);
+
+/**
+ * @brief Retrieve the frame interval on a sub-device.
+ * @param entity - subdev-device media entity.
+ * @param interval - frame interval to be filled.
+ *
+ * Retrieve the current frame interval on subdev @a entity and store it in the
+ * @a interval structure.
+ *
+ * Frame interval retrieving is usually supported only on devices at the
+ * beginning of video pipelines, such as sensors.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+
+int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval);
+
+/**
+ * @brief Set the frame interval on a sub-device.
+ * @param entity - subdev-device media entity.
+ * @param interval - frame interval.
+ *
+ * Set the frame interval on subdev @a entity to @a interval. The driver is
+ * allowed to modify the requested frame interval, in which case @a interval is
+ * updated with the modifications.
+ *
+ * Frame interval setting is usually supported only on devices at the beginning
+ * of video pipelines, such as sensors.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval);
+
+/**
+ * @brief Parse a string and apply format, crop and frame interval settings.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string p where parsing ended (return)
+ *
+ * Parse string @a p and apply format, crop and frame interval settings to a
+ * subdev pad specified in @a p. @a endp will be written a pointer where
+ * parsing of @a p ended.
+ *
+ * Format strings are separeted by commas (,).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p);
+
+/**
+ * @brief Convert media bus pixel code to string.
+ * @param code - input string
+ *
+ * Convert media bus pixel code @a code to a human-readable string.
+ *
+ * @return A pointer to a string on success, NULL on failure.
+ */
+const char *v4l2_subdev_pixelcode_to_string(enum v4l2_mbus_pixelcode code);
+
+/**
+ * @brief Parse string to media bus pixel code.
+ * @param string - input string
+ * @param lenght - length of the string
+ *
+ * Parse human readable string @a string to an media bus pixel code.
+ *
+ * @return media bus pixelcode on success, -1 on failure.
+ */
+enum v4l2_mbus_pixelcode v4l2_subdev_string_to_pixelcode(const char *string,
+ unsigned int length);
+#endif
diff --git a/utils/qv4l2/Makefile.am b/utils/qv4l2/Makefile.am
index bdc64fd6..40f69970 100644
--- a/utils/qv4l2/Makefile.am
+++ b/utils/qv4l2/Makefile.am
@@ -21,7 +21,7 @@ qv4l2_LDFLAGS += $(ALSA_LIBS) -pthread
EXTRA_DIST = exit.png fileopen.png qv4l2_24x24.png qv4l2_64x64.png qv4l2.png qv4l2.svg snapshot.png \
video-television.png fileclose.png qv4l2_16x16.png qv4l2_32x32.png qv4l2.desktop qv4l2.qrc record.png \
- saveraw.png qv4l2.pro
+ saveraw.png qv4l2.pro qv4l2.1
clean-local:
-rm -vf moc_*.cpp qrc_*.cpp qrc_*.o ui_*.h
diff --git a/utils/qv4l2/capture-win-gl.cpp b/utils/qv4l2/capture-win-gl.cpp
index 5df1c708..135de12b 100644
--- a/utils/qv4l2/capture-win-gl.cpp
+++ b/utils/qv4l2/capture-win-gl.cpp
@@ -46,19 +46,30 @@ void CaptureWinGL::stop()
void CaptureWinGL::resizeEvent(QResizeEvent *event)
{
#ifdef HAVE_QTGL
+ // Get size of frame viewport. Can't use size of m_videoSurface
+ // since it is a subwidget of this widget.
QSize margins = getMargins();
- m_videoSurface.setSize(width() - margins.width(), height() - margins.height());
+ m_windowSize = size() - margins;
+ // Re-calculate sizes
+ m_frame.updated = true;
+ CaptureWin::updateSize();
+ // Lock viewport size to follow calculated size
+ m_videoSurface.lockSize(m_scaledSize);
#endif
event->accept();
}
-void CaptureWinGL::setFrame(int width, int height, __u32 format,
- unsigned char *data, unsigned char *data2, const QString &info)
+void CaptureWinGL::setRenderFrame()
{
#ifdef HAVE_QTGL
- m_videoSurface.setFrame(width, height, format, data, data2);
+ m_videoSurface.setFrame(m_frame.size.width(), m_frame.size.height(),
+ m_crop.delta.width(), m_crop.delta.height(),
+ m_frame.format,
+ m_frame.planeData[0],
+ m_frame.planeData[1]);
#endif
- m_information.setText(info);
+ m_frame.updated = false;
+ m_crop.updated = false;
}
bool CaptureWinGL::hasNativeFormat(__u32 format)
@@ -79,14 +90,47 @@ bool CaptureWinGL::isSupported()
#endif
}
+void CaptureWinGL::setColorspace(unsigned colorspace)
+{
+#ifdef HAVE_QTGL
+ m_videoSurface.setColorspace(colorspace);
+#endif
+}
+
+void CaptureWinGL::setDisplayColorspace(unsigned colorspace)
+{
+#ifdef HAVE_QTGL
+ m_videoSurface.setDisplayColorspace(colorspace);
+#endif
+}
+
+void CaptureWinGL::setField(unsigned field)
+{
+#ifdef HAVE_QTGL
+ m_videoSurface.setField(field);
+#endif
+}
+
+void CaptureWinGL::setBlending(bool enable)
+{
+#ifdef HAVE_QTGL
+ m_videoSurface.setBlending(enable);
+#endif
+}
+
#ifdef HAVE_QTGL
CaptureWinGLEngine::CaptureWinGLEngine() :
- m_frameHeight(0),
m_frameWidth(0),
+ m_frameHeight(0),
+ m_WCrop(0),
+ m_HCrop(0),
+ m_colorspace(V4L2_COLORSPACE_REC709),
+ m_displayColorspace(V4L2_COLORSPACE_SRGB),
m_screenTextureCount(0),
m_formatChange(false),
m_frameFormat(0),
- m_frameData(NULL)
+ m_frameData(NULL),
+ m_blending(false)
{
m_glfunction.initializeGLFunctions(context());
}
@@ -96,6 +140,68 @@ CaptureWinGLEngine::~CaptureWinGLEngine()
clearShader();
}
+void CaptureWinGLEngine::setColorspace(unsigned colorspace)
+{
+ switch (colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_SMPTE240M:
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ case V4L2_COLORSPACE_SRGB:
+ break;
+ default:
+ // If the colorspace was not specified, then guess
+ // based on the pixel format.
+ switch (m_frameFormat) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_NV16M:
+ case V4L2_PIX_FMT_NV61M:
+ // SDTV or HDTV?
+ if (m_frameWidth <= 720 && m_frameHeight <= 575)
+ colorspace = V4L2_COLORSPACE_SMPTE170M;
+ else
+ colorspace = V4L2_COLORSPACE_REC709;
+ break;
+ default:
+ colorspace = V4L2_COLORSPACE_SRGB;
+ break;
+ }
+ break;
+ }
+ if (m_colorspace == colorspace)
+ return;
+ m_colorspace = colorspace;
+ m_formatChange = true;
+}
+
+void CaptureWinGLEngine::setDisplayColorspace(unsigned colorspace)
+{
+ if (colorspace == m_displayColorspace)
+ return;
+ m_displayColorspace = colorspace;
+ if (m_haveFramebufferSRGB) {
+ if (m_displayColorspace == V4L2_COLORSPACE_SRGB)
+ glEnable(GL_FRAMEBUFFER_SRGB);
+ else
+ glDisable(GL_FRAMEBUFFER_SRGB);
+ }
+ m_formatChange = true;
+}
+
+void CaptureWinGLEngine::setField(unsigned field)
+{
+ if (m_field == field)
+ return;
+ m_field = field;
+ m_formatChange = true;
+}
+
void CaptureWinGLEngine::clearShader()
{
glDeleteTextures(m_screenTextureCount, m_screenTexture);
@@ -115,21 +221,27 @@ void CaptureWinGLEngine::initializeGL()
{
glShadeModel(GL_FLAT);
glEnable(GL_TEXTURE_2D);
-
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glEnable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+
+ // Check if the the GL_FRAMEBUFFER_SRGB feature is available.
+ // If it is, then the GPU can perform the SRGB transfer function
+ // for us.
+ GLint res = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &res);
+ m_haveFramebufferSRGB = res;
+ if (m_haveFramebufferSRGB)
+ glEnable(GL_FRAMEBUFFER_SRGB);
+
+ glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ glBlendFunc(GL_ONE, GL_ZERO);
checkError("InitializeGL");
}
-void CaptureWinGLEngine::setSize(int width, int height)
+void CaptureWinGLEngine::lockSize(QSize size)
{
- QSize sizedFrame = CaptureWin::scaleFrameSize(QSize(width, height), QSize(m_frameWidth, m_frameHeight));
-
- width = sizedFrame.width();
- height = sizedFrame.height();
-
- if (width > 0 && height > 0) {
- setMaximumSize(width, height);
- resizeGL(width, height);
+ if ((size.width() > 0) && (size.height() > 0)) {
+ setFixedSize(size);
}
}
@@ -138,12 +250,16 @@ void CaptureWinGLEngine::resizeGL(int width, int height)
glViewport(0, 0, width, height);
}
-void CaptureWinGLEngine::setFrame(int width, int height, __u32 format, unsigned char *data, unsigned char *data2)
+void CaptureWinGLEngine::setFrame(int width, int height, int WCrop, int HCrop,
+ __u32 format, unsigned char *data, unsigned char *data2)
{
- if (format != m_frameFormat || width != m_frameWidth || height != m_frameHeight) {
+ if (format != m_frameFormat || width != m_frameWidth || height != m_frameHeight
+ || WCrop != m_WCrop || HCrop != m_HCrop) {
m_formatChange = true;
m_frameWidth = width;
m_frameHeight = height;
+ m_WCrop = WCrop;
+ m_HCrop = HCrop;
m_frameFormat = format;
}
@@ -158,35 +274,33 @@ void CaptureWinGLEngine::checkError(const char *msg)
if (err) fprintf(stderr, "OpenGL Error 0x%x: %s.\n", err, msg);
}
-struct supported_fmt {
- __u32 fmt;
- bool uses_shader;
-};
-
bool CaptureWinGLEngine::hasNativeFormat(__u32 format)
{
- static const struct supported_fmt supported_fmts[] = {
- { V4L2_PIX_FMT_RGB32, false },
- { V4L2_PIX_FMT_BGR32, false },
- { V4L2_PIX_FMT_RGB24, false },
- { V4L2_PIX_FMT_BGR24, true },
- { V4L2_PIX_FMT_RGB565, false },
- { V4L2_PIX_FMT_RGB555, false },
- { V4L2_PIX_FMT_YUYV, true },
- { V4L2_PIX_FMT_YVYU, true },
- { V4L2_PIX_FMT_UYVY, true },
- { V4L2_PIX_FMT_VYUY, true },
- { V4L2_PIX_FMT_YVU420, true },
- { V4L2_PIX_FMT_YUV420, true },
- { V4L2_PIX_FMT_NV16M, true },
- { V4L2_PIX_FMT_NV61M, true },
- { 0, false }
+ static const __u32 supported_fmts[] = {
+ V4L2_PIX_FMT_RGB32,
+ V4L2_PIX_FMT_BGR32,
+ V4L2_PIX_FMT_RGB24,
+ V4L2_PIX_FMT_BGR24,
+ V4L2_PIX_FMT_RGB565,
+ V4L2_PIX_FMT_RGB565X,
+ V4L2_PIX_FMT_RGB555,
+ V4L2_PIX_FMT_RGB555X,
+ V4L2_PIX_FMT_YUYV,
+ V4L2_PIX_FMT_YVYU,
+ V4L2_PIX_FMT_UYVY,
+ V4L2_PIX_FMT_VYUY,
+ V4L2_PIX_FMT_YVU420,
+ V4L2_PIX_FMT_YUV420,
+ V4L2_PIX_FMT_NV16M,
+ V4L2_PIX_FMT_NV61M,
+ 0
};
- bool haveShaders = m_glfunction.hasOpenGLFeature(QGLFunctions::Shaders);
- for (int i = 0; supported_fmts[i].fmt; i++)
- if (supported_fmts[i].fmt == format &&
- (!supported_fmts[i].uses_shader || haveShaders))
+ if (!m_glfunction.hasOpenGLFeature(QGLFunctions::Shaders))
+ return false;
+
+ for (int i = 0; supported_fmts[i]; i++)
+ if (supported_fmts[i] == format)
return true;
return false;
@@ -221,73 +335,49 @@ void CaptureWinGLEngine::changeShader()
shader_YUV();
break;
- case V4L2_PIX_FMT_RGB32:
- m_screenTextureCount = 1;
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(m_screenTextureCount, m_screenTexture);
- configureTexture(0);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, m_frameWidth, m_frameHeight, 0,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL);
- checkError("RGB32 shader");
- break;
-
- case V4L2_PIX_FMT_BGR32:
- m_screenTextureCount = 1;
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(m_screenTextureCount, m_screenTexture);
- configureTexture(0);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, m_frameWidth, m_frameHeight, 0,
- GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, NULL);
- checkError("BGR32 shader");
- break;
-
case V4L2_PIX_FMT_RGB555:
- m_screenTextureCount = 1;
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(m_screenTextureCount, m_screenTexture);
- configureTexture(0);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, m_frameWidth, m_frameHeight, 0,
- GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
- checkError("RGB555 shader");
- break;
-
+ case V4L2_PIX_FMT_RGB555X:
case V4L2_PIX_FMT_RGB565:
- m_screenTextureCount = 1;
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(m_screenTextureCount, m_screenTexture);
- configureTexture(0);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_frameWidth, m_frameHeight, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
- checkError("RGB565 shader");
- break;
- case V4L2_PIX_FMT_BGR24:
- shader_BGR();
- break;
+ case V4L2_PIX_FMT_RGB565X:
case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_BGR32:
default:
- m_screenTextureCount = 1;
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(m_screenTextureCount, m_screenTexture);
- configureTexture(0);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_frameWidth, m_frameHeight, 0,
- GL_RGB, GL_UNSIGNED_BYTE, NULL);
- checkError("Default shader");
+ shader_RGB();
break;
}
-
- glClear(GL_COLOR_BUFFER_BIT);
}
void CaptureWinGLEngine::paintFrame()
{
- float cropH = (float)CaptureWin::cropHeight(m_frameWidth, m_frameHeight) / m_frameHeight;
- float cropW = (float)CaptureWin::cropWidth(m_frameWidth, m_frameHeight) / m_frameWidth;
+ float HCrop_f = (float)m_HCrop / m_frameHeight;
+ float WCrop_f = (float)m_WCrop / m_frameWidth;
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(WCrop_f, HCrop_f); glVertex2f(0, 0);
+ glTexCoord2f(1.0f - WCrop_f, HCrop_f); glVertex2f(m_frameWidth, 0);
+ glTexCoord2f(1.0f - WCrop_f, 1.0f - HCrop_f); glVertex2f(m_frameWidth, m_frameHeight);
+ glTexCoord2f(WCrop_f, 1.0f - HCrop_f); glVertex2f(0, m_frameHeight);
+ glEnd();
+}
+
+void CaptureWinGLEngine::paintSquare()
+{
+ // Draw a black square on the white background to
+ // test the alpha channel.
+ unsigned w4 = m_frameWidth / 4;
+ unsigned h4 = m_frameHeight / 4;
+
+ glClear(GL_COLOR_BUFFER_BIT);
+ glBindTexture(GL_TEXTURE_2D, 0);
glBegin(GL_QUADS);
- glTexCoord2f(cropW, cropH); glVertex2f(0, 0);
- glTexCoord2f(1.0f - cropW, cropH); glVertex2f(m_frameWidth, 0);
- glTexCoord2f(1.0f - cropW, 1.0f - cropH); glVertex2f(m_frameWidth, m_frameHeight);
- glTexCoord2f(cropW, 1.0f - cropH); glVertex2f(0, m_frameHeight);
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ glVertex2f(w4, h4);
+ glVertex2f(w4, 3 * h4);
+ glVertex2f(3 * w4, 3 * h4);
+ glVertex2f(3 * w4, h4);
glEnd();
}
@@ -305,6 +395,11 @@ void CaptureWinGLEngine::paintGL()
return;
}
+ if (m_blending) {
+ paintSquare();
+ glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+ }
+
switch (m_frameFormat) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
@@ -323,43 +418,22 @@ void CaptureWinGLEngine::paintGL()
render_YUV(m_frameFormat);
break;
- case V4L2_PIX_FMT_RGB32:
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, m_frameData);
- checkError("RGB32 paint");
- break;
-
- case V4L2_PIX_FMT_BGR32:
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, m_frameData);
- checkError("BGR32 paint");
- break;
-
case V4L2_PIX_FMT_RGB555:
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight,
- GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, m_frameData);
- checkError("RGB555 paint");
- break;
-
+ case V4L2_PIX_FMT_RGB555X:
case V4L2_PIX_FMT_RGB565:
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, m_frameData);
- checkError("RGB565 paint");
- break;
-
- case V4L2_PIX_FMT_BGR24:
- render_BGR();
- break;
+ case V4L2_PIX_FMT_RGB565X:
case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_BGR32:
default:
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_frameWidth, m_frameHeight,
- GL_RGB, GL_UNSIGNED_BYTE, m_frameData);
- checkError("Default paint");
+ render_RGB();
break;
}
paintFrame();
+
+ if (m_blending)
+ glBlendFunc(GL_ONE, GL_ZERO);
}
void CaptureWinGLEngine::configureTexture(size_t idx)
@@ -371,6 +445,147 @@ void CaptureWinGLEngine::configureTexture(size_t idx)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
+// Convert Y'CbCr (aka YUV) to R'G'B', taking into account the
+// colorspace.
+QString CaptureWinGLEngine::codeYUV2RGB()
+{
+ switch (m_colorspace) {
+ case V4L2_COLORSPACE_SMPTE240M:
+ // Old obsolete HDTV standard. Replaced by REC 709.
+ // SMPTE 240M has its own luma coefficients
+ return QString(" float r = y + 1.8007 * v;"
+ " float g = y - 0.2575 * u - 0.57143 * v;"
+ " float b = y + 2.088 * u;"
+ );
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ // These SDTV colorspaces all use the BT.601 luma coefficients
+ return QString(" float r = y + 1.5958 * v;"
+ " float g = y - 0.39173 * u - 0.81290 * v;"
+ " float b = y + 2.017 * u;"
+ );
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
+ default:
+ // The HDTV/graphics colorspaces all use REC 709 luma coefficients
+ return QString(" float r = y + 1.79274 * v;"
+ " float g = y - 0.21325 * u - 0.53291 * v;"
+ " float b = y + 2.1124 * u;"
+ );
+ }
+}
+
+// Convert non-linear R'G'B' to linear RGB, taking into account the
+// colorspace.
+QString CaptureWinGLEngine::codeTransformToLinear()
+{
+ switch (m_colorspace) {
+ case V4L2_COLORSPACE_SMPTE240M:
+ // Old obsolete HDTV standard. Replaced by REC 709.
+ // This is the transfer function for SMPTE 240M
+ return QString(" r = (r < 0.0913) ? r / 4.0 : pow((r + 0.1115) / 1.1115, 1.0 / 0.45);"
+ " g = (g < 0.0913) ? g / 4.0 : pow((g + 0.1115) / 1.1115, 1.0 / 0.45);"
+ " b = (b < 0.0913) ? b / 4.0 : pow((b + 0.1115) / 1.1115, 1.0 / 0.45);"
+ );
+ case V4L2_COLORSPACE_SRGB:
+ // This is used for sRGB as specified by the IEC FDIS 61966-2-1 standard
+ return QString(" r = (r <= 0.03928) ? r / 12.92 : pow((r + 0.055) / 1.055, 2.4);"
+ " g = (g <= 0.03928) ? g / 12.92 : pow((g + 0.055) / 1.055, 2.4);"
+ " b = (b <= 0.03928) ? b / 12.92 : pow((b + 0.055) / 1.055, 2.4);"
+ );
+ case V4L2_COLORSPACE_REC709:
+ default:
+ // All others use the transfer function specified by REC 709
+ return QString(" r = (r < 0.081) ? r / 4.5 : pow((r + 0.099) / 1.099, 1.0 / 0.45);"
+ " g = (g < 0.081) ? g / 4.5 : pow((g + 0.099) / 1.099, 1.0 / 0.45);"
+ " b = (b < 0.081) ? b / 4.5 : pow((b + 0.099) / 1.099, 1.0 / 0.45);"
+ );
+ }
+}
+
+// Convert the given colorspace to the REC 709/sRGB colorspace. All colors are
+// specified as linear RGB.
+QString CaptureWinGLEngine::codeColorspaceConversion()
+{
+ switch (m_colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ // Current SDTV standard, although slowly being replaced by REC 709.
+ // Use the SMPTE 170M aka SMPTE-C aka SMPTE RP 145 conversion matrix.
+ return QString(" float rr = 0.939536 * r + 0.050215 * g + 0.001789 * b;"
+ " float gg = 0.017743 * r + 0.965758 * g + 0.016243 * b;"
+ " float bb = -0.001591 * r - 0.004356 * g + 1.005951 * b;"
+ " r = rr; g = gg; b = bb;"
+ );
+ case V4L2_COLORSPACE_SMPTE240M:
+ // Old obsolete HDTV standard. Replaced by REC 709.
+ // Use the SMPTE 240M conversion matrix.
+ return QString(" float rr = 1.4086 * r - 0.4086 * g;"
+ " float gg = -0.0257 * r + 1.0457 * g;"
+ " float bb = -0.0254 * r - 0.0440 * g + 1.0695 * b;"
+ " r = rr; g = gg; b = bb;"
+ );
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ // Old obsolete NTSC standard. Replaced by REC 709.
+ // Use the NTSC 1953 conversion matrix.
+ return QString(" float rr = 1.5073 * r - 0.3725 * g - 0.0832 * b;"
+ " float gg = -0.0275 * r + 0.9350 * g + 0.0670 * b;"
+ " float bb = -0.0272 * r - 0.0401 * g + 1.1677 * b;"
+ " r = rr; g = gg; b = bb;"
+ );
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ // Old obsolete PAL/SECAM standard. Replaced by REC 709.
+ // Use the EBU Tech. 3213 conversion matrix.
+ return QString(" float rr = 1.0440 * r - 0.0440 * g;"
+ " float bb = -0.0119 * g + 1.0119 * b;"
+ " r = rr; b = bb;"
+ );
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
+ default:
+ return "";
+ }
+}
+
+// Convert linear RGB to non-linear R'G'B', taking into account the
+// given display colorspace.
+QString CaptureWinGLEngine::codeTransformToNonLinear()
+{
+ switch (m_displayColorspace) {
+ case 0: // Keep as linear RGB
+ return "";
+
+ case V4L2_COLORSPACE_SMPTE240M:
+ // Use the SMPTE 240M transfer function
+ return QString(" r = (r < 0.0228) ? r * 4.0 : 1.1115 * pow(r, 0.45) - 0.1115;"
+ " g = (g < 0.0228) ? g * 4.0 : 1.1115 * pow(g, 0.45) - 0.1115;"
+ " b = (b < 0.0228) ? b * 4.0 : 1.1115 * pow(b, 0.45) - 0.1115;"
+ );
+ case V4L2_COLORSPACE_SRGB:
+ // Use the sRGB transfer function. Do nothing if the GL_FRAMEBUFFER_SRGB
+ // is available.
+ if (m_haveFramebufferSRGB)
+ return "";
+ return QString(" r = (r <= 0.0031308) ? r * 12.92 : 1.055 * pow(r, 1.0 / 2.4) - 0.055;"
+ " g = (g <= 0.0031308) ? g * 12.92 : 1.055 * pow(g, 1.0 / 2.4) - 0.055;"
+ " b = (b <= 0.0031308) ? b * 12.92 : 1.055 * pow(b, 1.0 / 2.4) - 0.055;"
+ );
+ case V4L2_COLORSPACE_REC709:
+ default:
+ // Use the REC 709 transfer function
+ return QString(" r = (r < 0.018) ? r * 4.5 : 1.099 * pow(r, 0.45) - 0.099;"
+ " g = (g < 0.018) ? g * 4.5 : 1.099 * pow(g, 0.45) - 0.099;"
+ " b = (b < 0.018) ? b * 4.5 : 1.099 * pow(b, 0.45) - 0.099;"
+ );
+ }
+}
+
+static const QString codeSuffix(" gl_FragColor = vec4(r, g, b, 0.0);"
+ "}");
+
+static const QString codeSuffixWithAlpha(" gl_FragColor = vec4(r, g, b, a);"
+ "}");
+
void CaptureWinGLEngine::shader_YUV()
{
m_screenTextureCount = 3;
@@ -394,23 +609,32 @@ void CaptureWinGLEngine::shader_YUV()
GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
checkError("YUV shader texture 2");
+ QString codeHead = QString("uniform sampler2D ytex;"
+ "uniform sampler2D utex;"
+ "uniform sampler2D vtex;"
+ "uniform float tex_h;"
+ "void main()"
+ "{"
+ " vec2 xy = vec2(gl_TexCoord[0].xy);"
+ " float ycoord = floor(xy.y * tex_h);");
+
+ if (m_field == V4L2_FIELD_SEQ_TB)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 : xy.y / 2.0 + 0.5;";
+ else if (m_field == V4L2_FIELD_SEQ_BT)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 + 0.5 : xy.y / 2.0;";
+
+ codeHead += " float y = 1.1640625 * (texture2D(ytex, xy).r - 0.0625);"
+ " float u = texture2D(utex, xy).r - 0.5;"
+ " float v = texture2D(vtex, xy).r - 0.5;";
+
+ QString codeTail = codeYUV2RGB() +
+ codeTransformToLinear() +
+ codeColorspaceConversion() +
+ codeTransformToNonLinear() +
+ codeSuffix;
+
bool src_c = m_shaderProgram.addShaderFromSourceCode(
- QGLShader::Fragment,
- "uniform sampler2D ytex;"
- "uniform sampler2D utex;"
- "uniform sampler2D vtex;"
- "void main()"
- "{"
- " vec2 xy = vec2(gl_TexCoord[0].xy);"
- " float y = 1.1640625 * (texture2D(ytex, xy).r - 0.0625);"
- " float u = texture2D(utex, xy).r - 0.5;"
- " float v = texture2D(vtex, xy).r - 0.5;"
- " float r = y + 1.59765625 * v;"
- " float g = y - 0.390625 * u - 0.8125 *v;"
- " float b = y + 2.015625 * u;"
- " gl_FragColor = vec4(r, g, b, 1.0);"
- "}"
- );
+ QGLShader::Fragment, codeHead + codeTail);
if (!src_c)
fprintf(stderr, "OpenGL Error: YUV shader compilation failed.\n");
@@ -422,6 +646,7 @@ void CaptureWinGLEngine::render_YUV(__u32 format)
{
int idxU;
int idxV;
+
if (format == V4L2_PIX_FMT_YUV420) {
idxU = m_frameWidth * m_frameHeight;
idxV = idxU + (idxU / 4);
@@ -430,6 +655,9 @@ void CaptureWinGLEngine::render_YUV(__u32 format)
idxU = idxV + (idxV / 4);
}
+ int idx = glGetUniformLocation(m_shaderProgram.programId(), "tex_h"); // Texture height
+ glUniform1f(idx, m_frameHeight);
+
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
GLint Y = m_glfunction.glGetUniformLocation(m_shaderProgram.programId(), "ytex");
@@ -460,21 +688,21 @@ QString CaptureWinGLEngine::shader_NV16M_invariant(__u32 format)
switch (format) {
case V4L2_PIX_FMT_NV16M:
return QString("if (mod(xcoord, 2.0) == 0.0) {"
- " u = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;"
- " v = texture2D(uvtex, vec2(pixelx + texl_w, pixely)).r - 0.5;"
+ " u = texture2D(uvtex, xy).r - 0.5;"
+ " v = texture2D(uvtex, vec2(xy.x + texl_w, xy.y)).r - 0.5;"
"} else {"
- " u = texture2D(uvtex, vec2(pixelx - texl_w, pixely)).r - 0.5;"
- " v = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;"
+ " u = texture2D(uvtex, vec2(xy.x - texl_w, xy.y)).r - 0.5;"
+ " v = texture2D(uvtex, xy).r - 0.5;"
"}"
);
case V4L2_PIX_FMT_NV61M:
return QString("if (mod(xcoord, 2.0) == 0.0) {"
- " u = texture2D(uvtex, vec2(pixelx + texl_w, pixely)).r - 0.5;"
- " v = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;"
+ " u = texture2D(uvtex, vec2(xy.x + texl_w, xy.y)).r - 0.5;"
+ " v = texture2D(uvtex, xy).r - 0.5;"
"} else {"
- " u = texture2D(uvtex, vec2(pixelx, pixely)).r - 0.5;"
- " v = texture2D(uvtex, vec2(pixelx - texl_w, pixely)).r - 0.5;"
+ " u = texture2D(uvtex, xy).r - 0.5;"
+ " v = texture2D(uvtex, vec2(xy.x - texl_w, xy.y)).r - 0.5;"
"}"
);
@@ -504,24 +732,30 @@ void CaptureWinGLEngine::shader_NV16M(__u32 format)
"uniform sampler2D uvtex;"
"uniform float texl_w;"
"uniform float tex_w;"
+ "uniform float tex_h;"
"void main()"
"{"
" vec2 xy = vec2(gl_TexCoord[0].xy);"
- " float y = 1.1640625 * (texture2D(ytex, xy).r - 0.0625);"
- " float u, v;"
- " float pixelx = gl_TexCoord[0].x;"
- " float pixely = gl_TexCoord[0].y;"
- " float xcoord = floor(pixelx * tex_w);"
- );
+ " float ycoord = floor(xy.y * tex_h);");
+
+ if (m_field == V4L2_FIELD_SEQ_TB)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 : xy.y / 2.0 + 0.5;";
+ else if (m_field == V4L2_FIELD_SEQ_BT)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 + 0.5 : xy.y / 2.0;";
+
+ codeHead += " float u, v;"
+ " float xcoord = floor(xy.x * tex_w);"
+ " float y = 1.1640625 * (texture2D(ytex, xy).r - 0.0625);";
+
+
QString codeBody = shader_NV16M_invariant(format);
- QString codeTail = QString(" float r = y + 1.5958 * v;"
- " float g = y - 0.39173 * u - 0.81290 * v;"
- " float b = y + 2.017 * u;"
- " gl_FragColor = vec4(r, g, b, 1.0);"
- "}"
- );
+ QString codeTail = codeYUV2RGB() +
+ codeTransformToLinear() +
+ codeColorspaceConversion() +
+ codeTransformToNonLinear() +
+ codeSuffix;
bool src_ok = m_shaderProgram.addShaderFromSourceCode(
QGLShader::Fragment, QString("%1%2%3").arg(codeHead, codeBody, codeTail)
@@ -540,6 +774,8 @@ void CaptureWinGLEngine::render_NV16M(__u32 format)
glUniform1f(idx, 1.0 / m_frameWidth);
idx = glGetUniformLocation(m_shaderProgram.programId(), "tex_w"); // Texture width
glUniform1f(idx, m_frameWidth);
+ idx = glGetUniformLocation(m_shaderProgram.programId(), "tex_h"); // Texture height
+ glUniform1f(idx, m_frameHeight);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
@@ -563,10 +799,10 @@ QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format)
switch (format) {
case V4L2_PIX_FMT_YUYV:
return QString("if (mod(xcoord, 2.0) == 0.0) {"
- " luma_chroma = texture2D(tex, vec2(pixelx, pixely));"
+ " luma_chroma = texture2D(tex, xy);"
" y = (luma_chroma.r - 0.0625) * 1.1643;"
"} else {"
- " luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely));"
+ " luma_chroma = texture2D(tex, vec2(xy.x - texl_w, xy.y));"
" y = (luma_chroma.b - 0.0625) * 1.1643;"
"}"
"u = luma_chroma.g - 0.5;"
@@ -575,10 +811,10 @@ QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format)
case V4L2_PIX_FMT_YVYU:
return QString("if (mod(xcoord, 2.0) == 0.0) {"
- " luma_chroma = texture2D(tex, vec2(pixelx, pixely));"
+ " luma_chroma = texture2D(tex, xy);"
" y = (luma_chroma.r - 0.0625) * 1.1643;"
"} else {"
- " luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely));"
+ " luma_chroma = texture2D(tex, vec2(xy.x - texl_w, xy.y));"
" y = (luma_chroma.b - 0.0625) * 1.1643;"
"}"
"u = luma_chroma.a - 0.5;"
@@ -587,10 +823,10 @@ QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format)
case V4L2_PIX_FMT_UYVY:
return QString("if (mod(xcoord, 2.0) == 0.0) {"
- " luma_chroma = texture2D(tex, vec2(pixelx, pixely));"
+ " luma_chroma = texture2D(tex, xy);"
" y = (luma_chroma.g - 0.0625) * 1.1643;"
"} else {"
- " luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely));"
+ " luma_chroma = texture2D(tex, vec2(xy.x - texl_w, xy.y));"
" y = (luma_chroma.a - 0.0625) * 1.1643;"
"}"
"u = luma_chroma.r - 0.5;"
@@ -599,10 +835,10 @@ QString CaptureWinGLEngine::shader_YUY2_invariant(__u32 format)
case V4L2_PIX_FMT_VYUY:
return QString("if (mod(xcoord, 2.0) == 0.0) {"
- " luma_chroma = texture2D(tex, vec2(pixelx, pixely));"
+ " luma_chroma = texture2D(tex, xy);"
" y = (luma_chroma.g - 0.0625) * 1.1643;"
"} else {"
- " luma_chroma = texture2D(tex, vec2(pixelx - texl_w, pixely));"
+ " luma_chroma = texture2D(tex, vec2(xy.x - texl_w, xy.y));"
" y = (luma_chroma.a - 0.0625) * 1.1643;"
"}"
"u = luma_chroma.b - 0.5;"
@@ -621,28 +857,33 @@ void CaptureWinGLEngine::shader_YUY2(__u32 format)
configureTexture(0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_frameWidth / 2, m_frameHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
checkError("YUY2 shader");
QString codeHead = QString("uniform sampler2D tex;"
"uniform float texl_w;"
"uniform float tex_w;"
+ "uniform float tex_h;"
"void main()"
"{"
" float y, u, v;"
" vec4 luma_chroma;"
- " float pixelx = gl_TexCoord[0].x;"
- " float pixely = gl_TexCoord[0].y;"
- " float xcoord = floor(pixelx * tex_w);"
- );
+ " vec2 xy = vec2(gl_TexCoord[0].xy);"
+ " float xcoord = floor(xy.x * tex_w);"
+ " float ycoord = floor(xy.y * tex_h);");
+
+ if (m_field == V4L2_FIELD_SEQ_TB)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 : xy.y / 2.0 + 0.5;";
+ else if (m_field == V4L2_FIELD_SEQ_BT)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 + 0.5 : xy.y / 2.0;";
QString codeBody = shader_YUY2_invariant(format);
- QString codeTail = QString(" float r = y + 1.5958 * v;"
- " float g = y - 0.39173 * u - 0.81290 * v;"
- " float b = y + 2.017 * u;"
- " gl_FragColor = vec4(r, g, b, 1.0);"
- "}"
- );
+ QString codeTail = codeYUV2RGB() +
+ codeTransformToLinear() +
+ codeColorspaceConversion() +
+ codeTransformToNonLinear() +
+ codeSuffix;
bool src_ok = m_shaderProgram.addShaderFromSourceCode(
QGLShader::Fragment, QString("%1%2%3").arg(codeHead, codeBody, codeTail)
@@ -661,6 +902,8 @@ void CaptureWinGLEngine::render_YUY2()
glUniform1f(idx, 1.0 / m_frameWidth);
idx = glGetUniformLocation(m_shaderProgram.programId(), "tex_w"); // Texture width
glUniform1f(idx, m_frameWidth);
+ idx = glGetUniformLocation(m_shaderProgram.programId(), "tex_h"); // Texture height
+ glUniform1f(idx, m_frameHeight);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
@@ -671,38 +914,155 @@ void CaptureWinGLEngine::render_YUY2()
checkError("YUY2 paint");
}
-void CaptureWinGLEngine::shader_BGR()
+void CaptureWinGLEngine::shader_RGB()
{
+ bool hasAlpha = false;
+
m_screenTextureCount = 1;
glGenTextures(m_screenTextureCount, m_screenTexture);
+ glActiveTexture(GL_TEXTURE0);
configureTexture(0);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_frameWidth, m_frameHeight, 0,
- GL_RGB, GL_UNSIGNED_BYTE, NULL);
- checkError("BGR shader");
- bool src_c = m_shaderProgram.addShaderFromSourceCode(
- QGLShader::Fragment,
- "uniform sampler2D tex;"
- "void main()"
- "{"
- " vec4 color = texture2D(tex, gl_TexCoord[0].xy);"
- " gl_FragColor = vec4(color.b, color.g, color.r, 1.0);"
- "}"
+ GLint internalFmt = m_colorspace == V4L2_COLORSPACE_SRGB ?
+ GL_SRGB8_ALPHA8 : GL_RGBA8;
+
+ switch (m_frameFormat) {
+ case V4L2_PIX_FMT_RGB555:
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0,
+ GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
+ hasAlpha = true;
+ break;
+
+ case V4L2_PIX_FMT_RGB555X:
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0,
+ GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
+ hasAlpha = true;
+ break;
+
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL);
+ hasAlpha = true;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0,
+ GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, NULL);
+ hasAlpha = true;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ default:
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_frameWidth, m_frameHeight, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ break;
+ }
+
+ checkError("RGB shader");
+
+ QString codeHead = QString("uniform sampler2D tex;"
+ "uniform float tex_h;"
+ "void main()"
+ "{"
+ " vec2 xy = vec2(gl_TexCoord[0].xy);"
+ " float ycoord = floor(xy.y * tex_h);");
+
+ if (m_field == V4L2_FIELD_SEQ_TB)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 : xy.y / 2.0 + 0.5;";
+ else if (m_field == V4L2_FIELD_SEQ_BT)
+ codeHead += " xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 + 0.5 : xy.y / 2.0;";
+
+ codeHead += " vec4 color = texture2D(tex, xy);"
+ " float a = color.a;";
+
+ if (m_frameFormat == V4L2_PIX_FMT_BGR24)
+ codeHead += " float r = color.b;"
+ " float g = color.g;"
+ " float b = color.r;";
+ else
+ codeHead += " float r = color.r;"
+ " float g = color.g;"
+ " float b = color.b;";
+
+ QString codeTail;
+
+ if (m_colorspace != V4L2_COLORSPACE_SRGB)
+ codeTail += codeTransformToLinear();
+
+ codeTail += codeColorspaceConversion() +
+ codeTransformToNonLinear() +
+ (hasAlpha ? codeSuffixWithAlpha : codeSuffix);
+
+ bool src_ok = m_shaderProgram.addShaderFromSourceCode(
+ QGLShader::Fragment, QString("%1%2").arg(codeHead, codeTail)
);
- if (!src_c)
- fprintf(stderr, "OpenGL Error: BGR shader compilation failed.\n");
+
+ if (!src_ok)
+ fprintf(stderr, "OpenGL Error: RGB shader compilation failed.\n");
m_shaderProgram.bind();
}
-void CaptureWinGLEngine::render_BGR()
+void CaptureWinGLEngine::render_RGB()
{
glActiveTexture(GL_TEXTURE0);