diff options
Diffstat (limited to 'Documentation/video4linux')
26 files changed, 2107 insertions, 197 deletions
diff --git a/Documentation/video4linux/API.html b/Documentation/video4linux/API.html index d749d41f647..d72fd2aa915 100644 --- a/Documentation/video4linux/API.html +++ b/Documentation/video4linux/API.html @@ -17,7 +17,7 @@ </tr> <tr> <td> - <a href="http://www.linuxtv.org/downloads/video4linux/API/V4L2_API">V4L2 API</a> + <a href="http://v4l2spec.bytesex.org/spec-single/v4l2.html">V4L2 API</a> </td> <td>Should be used for new projects </td> diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index f11c583295e..4739d568430 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -100,7 +100,7 @@ 99 -> AD-TVK503 100 -> Hercules Smart TV Stereo 101 -> Pace TV & Radio Card -102 -> IVC-200 [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155] +102 -> IVC-200 [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155,0800:a155,0801:a155,0802:a155,0803:a155] 103 -> Grand X-Guard / Trust 814PCI [0304:0102] 104 -> Nebula Electronics DigiTV [0071:0101] 105 -> ProVideo PV143 [aa00:1430,aa00:1431,aa00:1432,aa00:1433,aa03:1433] diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 7539e8fa1ff..87c46347bd6 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -17,12 +17,13 @@ 16 -> DVBWorld DVB-S2 2005 [0001:2005] 17 -> NetUP Dual DVB-S2 CI [1b55:2a2c] 18 -> Hauppauge WinTV-HVR1270 [0070:2211] - 19 -> Hauppauge WinTV-HVR1275 [0070:2215] - 20 -> Hauppauge WinTV-HVR1255 [0070:2251] - 21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295] + 19 -> Hauppauge WinTV-HVR1275 [0070:2215,0070:221d,0070:22f2] + 20 -> Hauppauge WinTV-HVR1255 [0070:2251,0070:2259,0070:22f1] + 21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295,0070:2299,0070:229d,0070:22f0,0070:22f3,0070:22f4,0070:22f5] 22 -> Mygica X8506 DMB-TH [14f1:8651] 23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657] 24 -> Hauppauge WinTV-HVR1850 [0070:8541] 25 -> Compro VideoMate E800 [1858:e800] 26 -> Hauppauge WinTV-HVR1290 [0070:8551] 27 -> Mygica X8558 PRO DMB-TH [14f1:8578] + 28 -> LEADTEK WinFast PxTV1200 [107d:6f22] diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 7ec3c4e4b60..f2510541373 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -82,3 +82,4 @@ 81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654] 82 -> WinFast DTV2000 H rev. J [107d:6f2b] 83 -> Prof 7301 DVB-S/S2 [b034:3034] + 84 -> Samsung SMT 7020 DVB-S [18ac:dc00,18ac:dccd] diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 0c166ff003a..5c568757c30 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -1,5 +1,5 @@ 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] - 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] + 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] @@ -27,6 +27,7 @@ 26 -> Hercules Smart TV USB 2.0 (em2820/em2840) 27 -> Pinnacle PCTV USB 2 (Philips FM1216ME) (em2820/em2840) 28 -> Leadtek Winfast USB II Deluxe (em2820/em2840) + 29 -> EM2860/TVP5150 Reference Design (em2860) 30 -> Videology 20K14XUSB USB2.0 (em2820/em2840) 31 -> Usbgear VD204v9 (em2821) 32 -> Supercomp USB 2.0 TV (em2821) @@ -70,3 +71,5 @@ 72 -> Gadmei UTV330+ (em2861) 73 -> Reddo DVB-C USB TV Box (em2870) 74 -> Actionmaster/LinXcel/Digitus VC211A (em2800) + 75 -> Dikom DK300 (em2882) + 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index fce1e7eb047..4000c29fcfb 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -174,3 +174,9 @@ 173 -> Zolid Hybrid TV Tuner PCI [1131:2004] 174 -> Asus Europa Hybrid OEM [1043:4847] 175 -> Leadtek Winfast DTV1000S [107d:6655] +176 -> Beholder BeholdTV 505 RDS [0000:5051] +177 -> Hawell HW-404M7 +178 -> Beholder BeholdTV H7 [5ace:7190] +179 -> Beholder BeholdTV A7 [5ace:7090] +180 -> Avermedia PCI M733A [1461:4155,1461:4255] +181 -> TechoTrend TT-budget T-3000 [13c2:2804] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index e0d298fe883..e67c1db9685 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -81,3 +81,5 @@ tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough tuner=81 - Partsnic (Daewoo) PTI-5NF05 tuner=82 - Philips CU1216L tuner=83 - NXP TDA18271 +tuner=84 - Sony BTF-Pxn01Z +tuner=85 - Philips FQ1236 MK5 diff --git a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt index d230878e473..8977e7ce4da 100644 --- a/Documentation/video4linux/CQcam.txt +++ b/Documentation/video4linux/CQcam.txt @@ -203,11 +203,11 @@ The V4L2 API spec: http://v4l2spec.bytesex.org/ Some web pages about the quickcams: - http://www.dkfz-heidelberg.de/Macromol/wedemann/mini-HOWTO-cqcam.html + http://www.pingouin-land.com/howto/QuickCam-HOWTO.html http://www.crynwr.com/qcpc/ QuickCam Third-Party Drivers http://www.crynwr.com/qcpc/re.html Some Reverse Engineering - http://cse.unl.edu/~cluening/gqcam/ v4l client + http://www.wirelesscouch.net/software/gqcam/ v4l client http://phobos.illtel.denver.co.us/pub/qcread/ doesn't use v4l ftp://ftp.cs.unm.edu/pub/chris/quickcam/ Has lots of drivers http://www.cs.duke.edu/~reynolds/quickcam/ Has lots of information diff --git a/Documentation/video4linux/README.cpia b/Documentation/video4linux/README.cpia index 19cd3bf2498..8a747fee661 100644 --- a/Documentation/video4linux/README.cpia +++ b/Documentation/video4linux/README.cpia @@ -185,7 +185,7 @@ THANKS (in no particular order): --------------------------------------------------------------------------- REFERENCES - 1. http://www.risc.uni-linz.ac.at/people/ppregler + 1. http://www.risc.uni-linz.ac.at/ mailto:Peter_Pregler@email.com 2. see the file COPYING in the top directory of the kernel tree 3. http://webcam.sourceforge.net/ diff --git a/Documentation/video4linux/README.ivtv b/Documentation/video4linux/README.ivtv index 73df22c40bf..42b06686eb7 100644 --- a/Documentation/video4linux/README.ivtv +++ b/Documentation/video4linux/README.ivtv @@ -10,7 +10,7 @@ Hauppauge PVR-350. NOTE: this driver requires the latest encoder firmware (version 2.06.039, size 376836 bytes). Get the firmware from here: -http://dl.ivtvdriver.org/ivtv/firmware/firmware.tar.gz +http://dl.ivtvdriver.org/ivtv/firmware/ NOTE: 'normal' TV applications do not work with this driver, you need an application that can handle MPEG input such as mplayer, xine, MythTV, diff --git a/Documentation/video4linux/README.tlg2300 b/Documentation/video4linux/README.tlg2300 new file mode 100644 index 00000000000..416ccb93d8c --- /dev/null +++ b/Documentation/video4linux/README.tlg2300 @@ -0,0 +1,47 @@ +tlg2300 release notes +==================== + +This is a v4l2/dvb device driver for the tlg2300 chip. + + +current status +============== + +video + - support mmap and read().(no overlay) + +audio + - The driver will register a ALSA card for the audio input. + +vbi + - Works for almost TV norms. + +dvb-t + - works for DVB-T + +FM + - Works for radio. + +--------------------------------------------------------------------------- +TESTED APPLICATIONS: + +-VLC1.0.4 test the video and dvb. The GUI is friendly to use. + +-Mplayer test the video. + +-Mplayer test the FM. The mplayer should be compiled with --enable-radio and + --enable-radio-capture. + The command runs as this(The alsa audio registers to card 1): + #mplayer radio://103.7/capture/ -radio adevice=hw=1,0:arate=48000 \ + -rawaudio rate=48000:channels=2 + +--------------------------------------------------------------------------- +KNOWN PROBLEMS: +about preemphasis: + You can set the preemphasis for radio by the following command: + #v4l2-ctl -d /dev/radio0 --set-ctrl=pre_emphasis_settings=1 + + "pre_emphasis_settings=1" means that you select the 50us. If you want + to select the 75us, please use "pre_emphasis_settings=2" + + diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran index 0e89e767629..00e3f926781 100644 --- a/Documentation/video4linux/Zoran +++ b/Documentation/video4linux/Zoran @@ -174,7 +174,7 @@ and is used in Argentinia, Uruguay, an a few others We do not talk about how the audio is broadcast ! A rather good sites about the TV standards are: -http://www.sony.jp/ServiceArea/Voltage_map/ +http://www.sony.jp/support/ http://info.electronicwerkstatt.de/bereiche/fernsehtechnik/frequenzen_und_normen/Fernsehnormen/ and http://www.cabl.com/restaurant/channel.html @@ -330,7 +330,7 @@ These extensions are known as the v4l/mjpeg extensions. See zoran.h for details (structs/ioctls). Information - video4linux: -http://roadrunner.swansea.linux.org.uk/v4lapi.shtml +http://linux.bytesex.org/v4l2/API.html Documentation/video4linux/API.html /usr/include/linux/videodev.h @@ -390,7 +390,7 @@ BUZIOC_G_STATUS Get the status of the input lines (video source connected/norm). For programming example, please, look at lavrec.c and lavplay.c code in -lavtools-1.2p2 package (URL: http://www.cicese.mx/~mirsev/DC10plus/) +lavtools-1.2p2 package (URL: http://www.cicese.mx/) and the 'examples' directory in the original Buz driver distribution. Additional notes for software developers: diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards index d3389655ad9..12217fc4972 100644 --- a/Documentation/video4linux/bttv/Cards +++ b/Documentation/video4linux/bttv/Cards @@ -802,7 +802,7 @@ Kworld (www.kworld.com.tw) -JTT/ Justy Corp.http://www.justy.co.jp/ (www.jtt.com.jp website down) +JTT/ Justy Corp.(http://www.jtt.ne.jp/) --------------------------------------------------------------------- JTT-02 (JTT TV) "TV watchmate pro" (bt848) @@ -828,7 +828,7 @@ Eline www.eline-net.com/ Eline Vision TVMaster / TVMaster FM (ELV-TVM/ ELV-TVM-FM) = LR26 (bt878) Eline Vision TVMaster-2000 (ELV-TVM-2000, ELV-TVM-2000-FM)= LR138 (saa713x) -Spirit http://www.spiritmodems.com.au/ +Spirit ------ Spirit TV Tuner/Video Capture Card (bt848) @@ -959,6 +959,6 @@ Asus www.asuscom.com Hoontech -------- -http://www.hoontech.com/korean/download/down_driver_list03.html +http://www.hoontech.de/ HART Vision 848 (H-ART Vision 848) HART Vision 878 (H-Art Vision 878) diff --git a/Documentation/video4linux/bttv/MAKEDEV b/Documentation/video4linux/bttv/MAKEDEV index 6c29ba43b6c..9d112f7fd5f 100644 --- a/Documentation/video4linux/bttv/MAKEDEV +++ b/Documentation/video4linux/bttv/MAKEDEV @@ -14,7 +14,7 @@ function makedev () { ln -s /dev/${1}0 /dev/$1 } -# see http://roadrunner.swansea.uk.linux.org/v4lapi.shtml +# see http://linux.bytesex.org/v4l2/API.html echo "*** new device names ***" makedev video 0 diff --git a/Documentation/video4linux/bttv/Specs b/Documentation/video4linux/bttv/Specs index 79b9e576fe7..f32466cdae0 100644 --- a/Documentation/video4linux/bttv/Specs +++ b/Documentation/video4linux/bttv/Specs @@ -1,3 +1,3 @@ Philips http://www.Semiconductors.COM/pip/ -Conexant http://www.conexant.com/techinfo/default.asp -Micronas http://www.micronas.de/pages/product_documentation/index.html +Conexant http://www.conexant.com/ +Micronas http://www.micronas.com/en/home/index.html diff --git a/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt index faccee68f60..f4329a38878 100644 --- a/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt +++ b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt @@ -44,7 +44,7 @@ http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf This data sheet (google search) seems to have a lovely description of the RC5 basics -http://users.pandora.be/nenya/electronics/rc5/ and more data +http://www.nenya.be/beor/electronics/rc5.htm and more data http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt and even a reference to how to decode a bi-phase data stream. diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl index 2cb816047fc..47877deae6d 100644 --- a/Documentation/video4linux/extract_xc3028.pl +++ b/Documentation/video4linux/extract_xc3028.pl @@ -5,12 +5,18 @@ # # In order to use, you need to: # 1) Download the windows driver with something like: +# Version 2.4 +# wget http://www.twinhan.com/files/AW/BDA T/20080303_V1.0.6.7.zip +# or wget http://www.stefanringel.de/pub/20080303_V1.0.6.7.zip +# Version 2.7 # wget http://www.steventoth.net/linux/xc5000/HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip -# 2) Extract the file hcw85bda.sys from the zip into the current dir: +# 2) Extract the files from the zip into the current dir: +# unzip -j 20080303_V1.0.6.7.zip 20080303_v1.0.6.7/UDXTTM6000.sys # unzip -j HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip Driver85/hcw85bda.sys # 3) run the script: # ./extract_xc3028.pl -# 4) copy the generated file: +# 4) copy the generated files: +# cp xc3028-v24.fw /lib/firmware # cp xc3028-v27.fw /lib/firmware #use strict; @@ -135,7 +141,7 @@ sub write_hunk_fix_endian($$) } } -sub main_firmware($$$$) +sub main_firmware_24($$$$) { my $out; my $j=0; @@ -146,8 +152,774 @@ sub main_firmware($$$$) for ($j = length($name); $j <32; $j++) { $name = $name.chr(0); + } + + open OUTFILE, ">$outfile"; + syswrite(OUTFILE, $name); + write_le16($version); + write_le16($nr_desc); + + # + # Firmware 0, type: BASE FW F8MHZ (0x00000003), id: (0000000000000000), size: 6635 + # + + write_le32(0x00000003); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(6635); # Size + write_hunk_fix_endian(257752, 6635); + + # + # Firmware 1, type: BASE FW F8MHZ MTS (0x00000007), id: (0000000000000000), size: 6635 + # + + write_le32(0x00000007); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(6635); # Size + write_hunk_fix_endian(264392, 6635); + + # + # Firmware 2, type: BASE FW FM (0x00000401), id: (0000000000000000), size: 6525 + # + + write_le32(0x00000401); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(6525); # Size + write_hunk_fix_endian(271040, 6525); + + # + # Firmware 3, type: BASE FW FM INPUT1 (0x00000c01), id: (0000000000000000), size: 6539 + # + + write_le32(0x00000c01); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(6539); # Size + write_hunk_fix_endian(277568, 6539); + + # + # Firmware 4, type: BASE FW (0x00000001), id: (0000000000000000), size: 6633 + # + + write_le32(0x00000001); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(6633); # Size + write_hunk_fix_endian(284120, 6633); + + # + # Firmware 5, type: BASE FW MTS (0x00000005), id: (0000000000000000), size: 6617 + # + + write_le32(0x00000005); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(6617); # Size + write_hunk_fix_endian(290760, 6617); + + # + # Firmware 6, type: STD FW (0x00000000), id: PAL/BG A2/A (0000000100000007), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000001, 0x00000007); # ID + write_le32(161); # Size + write_hunk_fix_endian(297384, 161); + + # + # Firmware 7, type: STD FW MTS (0x00000004), id: PAL/BG A2/A (0000000100000007), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000001, 0x00000007); # ID + write_le32(169); # Size + write_hunk_fix_endian(297552, 169); + + # + # Firmware 8, type: STD FW (0x00000000), id: PAL/BG A2/B (0000000200000007), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000002, 0x00000007); # ID + write_le32(161); # Size + write_hunk_fix_endian(297728, 161); + + # + # Firmware 9, type: STD FW MTS (0x00000004), id: PAL/BG A2/B (0000000200000007), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000002, 0x00000007); # ID + write_le32(169); # Size + write_hunk_fix_endian(297896, 169); + + # + # Firmware 10, type: STD FW (0x00000000), id: PAL/BG NICAM/A (0000000400000007), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000004, 0x00000007); # ID + write_le32(161); # Size + write_hunk_fix_endian(298072, 161); + + # + # Firmware 11, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/A (0000000400000007), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000004, 0x00000007); # ID + write_le32(169); # Size + write_hunk_fix_endian(298240, 169); + + # + # Firmware 12, type: STD FW (0x00000000), id: PAL/BG NICAM/B (0000000800000007), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000008, 0x00000007); # ID + write_le32(161); # Size + write_hunk_fix_endian(298416, 161); + + # + # Firmware 13, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/B (0000000800000007), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000008, 0x00000007); # ID + write_le32(169); # Size + write_hunk_fix_endian(298584, 169); + + # + # Firmware 14, type: STD FW (0x00000000), id: PAL/DK A2 (00000003000000e0), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000003, 0x000000e0); # ID + write_le32(161); # Size + write_hunk_fix_endian(298760, 161); + + # + # Firmware 15, type: STD FW MTS (0x00000004), id: PAL/DK A2 (00000003000000e0), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000003, 0x000000e0); # ID + write_le32(169); # Size + write_hunk_fix_endian(298928, 169); + + # + # Firmware 16, type: STD FW (0x00000000), id: PAL/DK NICAM (0000000c000000e0), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x0000000c, 0x000000e0); # ID + write_le32(161); # Size + write_hunk_fix_endian(299104, 161); + + # + # Firmware 17, type: STD FW MTS (0x00000004), id: PAL/DK NICAM (0000000c000000e0), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x0000000c, 0x000000e0); # ID + write_le32(169); # Size + write_hunk_fix_endian(299272, 169); + + # + # Firmware 18, type: STD FW (0x00000000), id: SECAM/K1 (0000000000200000), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000000, 0x00200000); # ID + write_le32(161); # Size + write_hunk_fix_endian(299448, 161); + + # + # Firmware 19, type: STD FW MTS (0x00000004), id: SECAM/K1 (0000000000200000), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000000, 0x00200000); # ID + write_le32(169); # Size + write_hunk_fix_endian(299616, 169); + + # + # Firmware 20, type: STD FW (0x00000000), id: SECAM/K3 (0000000004000000), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000000, 0x04000000); # ID + write_le32(161); # Size + write_hunk_fix_endian(299792, 161); + + # + # Firmware 21, type: STD FW MTS (0x00000004), id: SECAM/K3 (0000000004000000), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000000, 0x04000000); # ID + write_le32(169); # Size + write_hunk_fix_endian(299960, 169); + + # + # Firmware 22, type: STD FW D2633 DTV6 ATSC (0x00010030), id: (0000000000000000), size: 149 + # + + write_le32(0x00010030); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(300136, 149); + + # + # Firmware 23, type: STD FW D2620 DTV6 QAM (0x00000068), id: (0000000000000000), size: 149 + # + + write_le32(0x00000068); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(300296, 149); + + # + # Firmware 24, type: STD FW D2633 DTV6 QAM (0x00000070), id: (0000000000000000), size: 149 + # + + write_le32(0x00000070); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(300448, 149); + + # + # Firmware 25, type: STD FW D2620 DTV7 (0x00000088), id: (0000000000000000), size: 149 + # + + write_le32(0x00000088); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(300608, 149); + + # + # Firmware 26, type: STD FW D2633 DTV7 (0x00000090), id: (0000000000000000), size: 149 + # + + write_le32(0x00000090); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(300760, 149); + + # + # Firmware 27, type: STD FW D2620 DTV78 (0x00000108), id: (0000000000000000), size: 149 + # + + write_le32(0x00000108); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(300920, 149); + + # + # Firmware 28, type: STD FW D2633 DTV78 (0x00000110), id: (0000000000000000), size: 149 + # + + write_le32(0x00000110); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(301072, 149); + + # + # Firmware 29, type: STD FW D2620 DTV8 (0x00000208), id: (0000000000000000), size: 149 + # + + write_le32(0x00000208); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(301232, 149); + + # + # Firmware 30, type: STD FW D2633 DTV8 (0x00000210), id: (0000000000000000), size: 149 + # + + write_le32(0x00000210); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(149); # Size + write_hunk_fix_endian(301384, 149); + + # + # Firmware 31, type: STD FW FM (0x00000400), id: (0000000000000000), size: 135 + # + + write_le32(0x00000400); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le32(135); # Size + write_hunk_fix_endian(301554, 135); + + # + # Firmware 32, type: STD FW (0x00000000), id: PAL/I (0000000000000010), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000000, 0x00000010); # ID + write_le32(161); # Size + write_hunk_fix_endian(301688, 161); + + # + # Firmware 33, type: STD FW MTS (0x00000004), id: PAL/I (0000000000000010), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000000, 0x00000010); # ID + write_le32(169); # Size + write_hunk_fix_endian(301856, 169); + + # + # Firmware 34, type: STD FW (0x00000000), id: SECAM/L AM (0000001000400000), size: 169 + # + + # + # Firmware 35, type: STD FW (0x00000000), id: SECAM/L NICAM (0000000c00400000), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x0000000c, 0x00400000); # ID + write_le32(161); # Size + write_hunk_fix_endian(302032, 161); + + # + # Firmware 36, type: STD FW (0x00000000), id: SECAM/Lc (0000000000800000), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000000, 0x00800000); # ID + write_le32(161); # Size + write_hunk_fix_endian(302200, 161); + + # + # Firmware 37, type: STD FW (0x00000000), id: NTSC/M Kr (0000000000008000), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000000, 0x00008000); # ID + write_le32(161); # Size + write_hunk_fix_endian(302368, 161); + + # + # Firmware 38, type: STD FW LCD (0x00001000), id: NTSC/M Kr (0000000000008000), size: 161 + # + + write_le32(0x00001000); # Type + write_le64(0x00000000, 0x00008000); # ID + write_le32(161); # Size + write_hunk_fix_endian(302536, 161); + + # + # Firmware 39, type: STD FW LCD NOGD (0x00003000), id: NTSC/M Kr (0000000000008000), size: 161 + # + + write_le32(0x00003000); # Type + write_le64(0x00000000, 0x00008000); # ID + write_le32(161); # Size + write_hunk_fix_endian(302704, 161); + + # + # Firmware 40, type: STD FW MTS (0x00000004), id: NTSC/M Kr (0000000000008000), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000000, 0x00008000); # ID + write_le32(169); # Size + write_hunk_fix_endian(302872, 169); + + # + # Firmware 41, type: STD FW (0x00000000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000000, 0x0000b700); # ID + write_le32(161); # Size + write_hunk_fix_endian(303048, 161); + + # + # Firmware 42, type: STD FW LCD (0x00001000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161 + # + + write_le32(0x00001000); # Type + write_le64(0x00000000, 0x0000b700); # ID + write_le32(161); # Size + write_hunk_fix_endian(303216, 161); + + # + # Firmware 43, type: STD FW LCD NOGD (0x00003000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161 + # + + write_le32(0x00003000); # Type + write_le64(0x00000000, 0x0000b700); # ID + write_le32(161); # Size + write_hunk_fix_endian(303384, 161); + + # + # Firmware 44, type: STD FW (0x00000000), id: NTSC/M Jp (0000000000002000), size: 161 + # + + write_le32(0x00000000); # Type + write_le64(0x00000000, 0x00002000); # ID + write_le32(161); # Size + write_hunk_fix_endian(303552, 161); + + # + # Firmware 45, type: STD FW MTS (0x00000004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169 + # + + write_le32(0x00000004); # Type + write_le64(0x00000000, 0x0000b700); # ID + write_le32(169); # Size + write_hunk_fix_endian(303720, 169); + + # + # Firmware 46, type: STD FW MTS LCD (0x00001004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169 + # + + write_le32(0x00001004); # Type + write_le64(0x00000000, 0x0000b700); # ID + write_le32(169); # Size + write_hunk_fix_endian(303896, 169); + + # + # Firmware 47, type: STD FW MTS LCD NOGD (0x00003004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169 + # + + write_le32(0x00003004); # Type + write_le64(0x00000000, 0x0000b700); # ID + write_le32(169); # Size + write_hunk_fix_endian(304072, 169); + + # + # Firmware 48, type: SCODE FW HAS IF (0x60000000), IF = 3.28 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(3280); # IF + write_le32(192); # Size + write_hunk(309048, 192); + + # + # Firmware 49, type: SCODE FW HAS IF (0x60000000), IF = 3.30 MHz id: (0000000000000000), size: 192 + # + +# write_le32(0x60000000); # Type +# write_le64(0x00000000, 0x00000000); # ID +# write_le16(3300); # IF +# write_le32(192); # Size +# write_hunk(304440, 192); + + # + # Firmware 50, type: SCODE FW HAS IF (0x60000000), IF = 3.44 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(3440); # IF + write_le32(192); # Size + write_hunk(309432, 192); + + # + # Firmware 51, type: SCODE FW HAS IF (0x60000000), IF = 3.46 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(3460); # IF + write_le32(192); # Size + write_hunk(309624, 192); + + # + # Firmware 52, type: SCODE FW DTV6 ATSC OREN36 HAS IF (0x60210020), IF = 3.80 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60210020); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(3800); # IF + write_le32(192); # Size + write_hunk(306936, 192); + + # + # Firmware 53, type: SCODE FW HAS IF (0x60000000), IF = 4.00 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(4000); # IF + write_le32(192); # Size + write_hunk(309240, 192); + + # + # Firmware 54, type: SCODE FW DTV6 ATSC TOYOTA388 HAS IF (0x60410020), IF = 4.08 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60410020); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(4080); # IF + write_le32(192); # Size + write_hunk(307128, 192); + + # + # Firmware 55, type: SCODE FW HAS IF (0x60000000), IF = 4.20 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(4200); # IF + write_le32(192); # Size + write_hunk(308856, 192); + + # + # Firmware 56, type: SCODE FW MONO HAS IF (0x60008000), IF = 4.32 MHz id: NTSC/M Kr (0000000000008000), size: 192 + # + + write_le32(0x60008000); # Type + write_le64(0x00000000, 0x00008000); # ID + write_le16(4320); # IF + write_le32(192); # Size + write_hunk(305208, 192); + + # + # Firmware 57, type: SCODE FW HAS IF (0x60000000), IF = 4.45 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(4450); # IF + write_le32(192); # Size + write_hunk(309816, 192); + + # + # Firmware 58, type: SCODE FW MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192 + # + + write_le32(0x6002b004); # Type + write_le64(0x00000000, 0x0000b700); # ID + write_le16(4500); # IF + write_le32(192); # Size + write_hunk(304824, 192); + + # + # Firmware 59, type: SCODE FW LCD NOGD IF HAS IF (0x60023000), IF = 4.60 MHz id: NTSC/M Kr (0000000000008000), size: 192 + # + + write_le32(0x60023000); # Type + write_le64(0x00000000, 0x00008000); # ID + write_le16(4600); # IF + write_le32(192); # Size + write_hunk(305016, 192); + + # + # Firmware 60, type: SCODE FW DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x620003e0); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(4760); # IF + write_le32(192); # Size + write_hunk(304440, 192); + + # + # Firmware 61, type: SCODE FW HAS IF (0x60000000), IF = 4.94 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(4940); # IF + write_le32(192); # Size + write_hunk(308664, 192); + + # + # Firmware 62, type: SCODE FW HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(5260); # IF + write_le32(192); # Size + write_hunk(307704, 192); + + # + # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192 + # + + write_le32(0x60008000); # Type + write_le64(0x0000000f, 0x00000007); # ID + write_le16(5320); # IF + write_le32(192); # Size + write_hunk(307896, 192); + + # + # Firmware 64, type: SCODE FW DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x65000380); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(5400); # IF + write_le32(192); # Size + write_hunk(304248, 192); + + # + # Firmware 65, type: SCODE FW DTV6 ATSC OREN538 HAS IF (0x60110020), IF = 5.58 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60110020); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(5580); # IF + write_le32(192); # Size + write_hunk(306744, 192); + + # + # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000003, 0x00000007); # ID + write_le16(5640); # IF + write_le32(192); # Size + write_hunk(305592, 192); + + # + # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x0000000c, 0x00000007); # ID + write_le16(5740); # IF + write_le32(192); # Size + write_hunk(305784, 192); + + # + # Firmware 68, type: SCODE FW HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(5900); # IF + write_le32(192); # Size + write_hunk(307512, 192); + + # + # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192 + # + + write_le32(0x60008000); # Type + write_le64(0x0000000c, 0x04c000f0); # ID + write_le16(6000); # IF + write_le32(192); # Size + write_hunk(305576, 192); + + # + # Firmware 70, type: SCODE FW DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x68050060); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(6200); # IF + write_le32(192); # Size + write_hunk(306552, 192); + + # + # Firmware 71, type: SCODE FW HAS IF (0x60000000), IF = 6.24 MHz id: PAL/I (0000000000000010), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00000010); # ID + write_le16(6240); # IF + write_le32(192); # Size + write_hunk(305400, 192); + + # + # Firmware 72, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.32 MHz id: SECAM/K1 (0000000000200000), size: 192 + # + + write_le32(0x60008000); # Type + write_le64(0x00000000, 0x00200000); # ID + write_le16(6320); # IF + write_le32(192); # Size + write_hunk(308472, 192); + + # + # Firmware 73, type: SCODE FW HAS IF (0x60000000), IF = 6.34 MHz id: SECAM/K1 (0000000000200000), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000000, 0x00200000); # ID + write_le16(6340); # IF + write_le32(192); # Size + write_hunk(306360, 192); + + # + # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192 + # + + write_le32(0x60008000); # Type + write_le64(0x0000000c, 0x044000e0); # ID + write_le16(6500); # IF + write_le32(192); # Size + write_hunk(308280, 192); + + # + # Firmware 75, type: SCODE FW DTV6 ATSC ATI638 HAS IF (0x60090020), IF = 6.58 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60090020); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(6580); # IF + write_le32(192); # Size + write_hunk(304632, 192); + + # + # Firmware 76, type: SCODE FW HAS IF (0x60000000), IF = 6.60 MHz id: PAL/DK A2 (00000003000000e0), size: 192 + # + + write_le32(0x60000000); # Type + write_le64(0x00000003, 0x000000e0); # ID + write_le16(6600); # IF + write_le32(192); # Size + write_hunk(306168, 192); + + # + # Firmware 77, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.68 MHz id: PAL/DK A2 (00000003000000e0), size: 192 + # + + write_le32(0x60008000); # Type + write_le64(0x00000003, 0x000000e0); # ID + write_le16(6680); # IF + write_le32(192); # Size + write_hunk(308088, 192); + + # + # Firmware 78, type: SCODE FW DTV6 ATSC TOYOTA794 HAS IF (0x60810020), IF = 8.14 MHz id: (0000000000000000), size: 192 + # + + write_le32(0x60810020); # Type + write_le64(0x00000000, 0x00000000); # ID + write_le16(8140); # IF + write_le32(192); # Size + write_hunk(307320, 192); + + # + # Firmware 79, type: SCODE FW HAS IF (0x60000000), IF = 8.20 MHz id: (0000000000000000), size: 192 + # + +# write_le32(0x60000000); # Type +# write_le64(0x00000000, 0x00000000); # ID +# write_le16(8200); # IF +# write_le32(192); # Size +# write_hunk(308088, 192); } +sub main_firmware_27($$$$) +{ + my $out; + my $j=0; + my $outfile = shift; + my $name = shift; + my $version = shift; + my $nr_desc = shift; + + for ($j = length($name); $j <32; $j++) { + $name = $name.chr(0); + } + open OUTFILE, ">$outfile"; syswrite(OUTFILE, $name); write_le16($version); @@ -906,20 +1678,39 @@ sub main_firmware($$$$) write_hunk(812856, 192); } + sub extract_firmware { - my $sourcefile = "hcw85bda.sys"; - my $hash = "0e44dbf63bb0169d57446aec21881ff2"; - my $outfile = "xc3028-v27.fw"; - my $name = "xc2028 firmware"; - my $version = 519; - my $nr_desc = 80; + my $sourcefile_24 = "UDXTTM6000.sys"; + my $hash_24 = "cb9deb5508a5e150af2880f5b0066d78"; + my $outfile_24 = "xc3028-v24.fw"; + my $name_24 = "xc2028 firmware"; + my $version_24 = 516; + my $nr_desc_24 = 77; + my $out; + + my $sourcefile_27 = "hcw85bda.sys"; + my $hash_27 = "0e44dbf63bb0169d57446aec21881ff2"; + my $outfile_27 = "xc3028-v27.fw"; + my $name_27 = "xc2028 firmware"; + my $version_27 = 519; + my $nr_desc_27 = 80; my $out; - verify($sourcefile, $hash); + if (-e $sourcefile_24) { + verify($sourcefile_24, $hash_24); + + open INFILE, "<$sourcefile_24"; + main_firmware_24($outfile_24, $name_24, $version_24, $nr_desc_24); + close INFILE; + } - open INFILE, "<$sourcefile"; - main_firmware($outfile, $name, $version, $nr_desc); - close INFILE; + if (-e $sourcefile_27) { + verify($sourcefile_27, $hash_27); + + open INFILE, "<$sourcefile_27"; + main_firmware_27($outfile_27, $name_27, $version_27, $nr_desc_27); + close INFILE; + } } extract_firmware; diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 1800a62cf13..56ba7bba716 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -29,8 +29,12 @@ zc3xx 041e:4029 Creative WebCam Vista Pro zc3xx 041e:4034 Creative Instant P0620 zc3xx 041e:4035 Creative Instant P0620D zc3xx 041e:4036 Creative Live ! +sq930x 041e:4038 Creative Joy-IT zc3xx 041e:403a Creative Nx Pro 2 spca561 041e:403b Creative Webcam Vista (VF0010) +sq930x 041e:403c Creative Live! Ultra +sq930x 041e:403d Creative Live! Ultra for Notebooks +sq930x 041e:4041 Creative Live! Motion zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250) ov519 041e:4052 Creative Live! VISTA IM zc3xx 041e:4053 Creative Live!Cam Video IM @@ -42,6 +46,7 @@ ov519 041e:4064 Creative Live! VISTA VF0420 ov519 041e:4067 Creative Live! Cam Video IM (VF0350) ov519 041e:4068 Creative Live! VISTA VF0470 spca561 0458:7004 Genius VideoCAM Express V2 +sn9c2028 0458:7005 Genius Smart 300, version 2 sunplus 0458:7006 Genius Dsc 1.3 Smart zc3xx 0458:7007 Genius VideoCam V2 zc3xx 0458:700c Genius VideoCam V3 @@ -49,6 +54,8 @@ zc3xx 0458:700f Genius VideoCam Web V2 sonixj 0458:7025 Genius Eye 311Q sn9c20x 0458:7029 Genius Look 320s sonixj 0458:702e Genius Slim 310 NB +sn9c20x 0458:704a Genius Slim 1320 +sn9c20x 0458:704c Genius i-Look 1321 sn9c20x 045e:00f4 LifeCam VX-6000 (SN9C20x + OV9650) sonixj 045e:00f5 MicroSoft VX3000 sonixj 045e:00f7 MicroSoft VX1000 @@ -109,6 +116,7 @@ sunplus 04a5:3003 Benq DC 1300 sunplus 04a5:3008 Benq DC 1500 sunplus 04a5:300a Benq DC 3410 spca500 04a5:300c Benq DC 1016 +benq 04a5:3035 Benq DC E300 finepix 04cb:0104 Fujifilm FinePix 4800 finepix 04cb:0109 Fujifilm FinePix A202 finepix 04cb:010b Fujifilm FinePix A203 @@ -134,6 +142,7 @@ finepix 04cb:013d Fujifilm FinePix unknown model finepix 04cb:013f Fujifilm FinePix F420 sunplus 04f1:1001 JVC GC A50 spca561 04fc:0561 Flexcam 100 +spca1528 04fc:1528 Sunplus MD80 clone sunplus 04fc:500c Sunplus CA500C sunplus 04fc:504a Aiptek Mini PenCam 1.3 sunplus 04fc:504b Maxell MaxPocket LE 1.3 @@ -142,6 +151,7 @@ sunplus 04fc:5360 Sunplus Generic spca500 04fc:7333 PalmPixDC85 sunplus 04fc:ffff Pure DigitalDakota spca501 0506:00df 3Com HomeConnect Lite +sunplus 052b:1507 Megapixel 5 Pretec DC-1007 sunplus 052b:1513 Megapix V4 sunplus 052b:1803 MegaImage VI tv8532 0545:808b Veo Stingray @@ -151,6 +161,7 @@ sunplus 0546:3191 Polaroid Ion 80 sunplus 0546:3273 Polaroid PDC2030 ov519 054c:0154 Sonny toy4 ov519 054c:0155 Sonny toy5 +cpia1 0553:0002 CPIA CPiA (version1) based cameras zc3xx 055f:c005 Mustek Wcam300A spca500 055f:c200 Mustek Gsmart 300 sunplus 055f:c211 Kowa Bs888e Microcamera @@ -188,8 +199,7 @@ spca500 06bd:0404 Agfa CL20 spca500 06be:0800 Optimedia sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom spca506 06e1:a190 ADS Instant VCD -ov534 06f8:3002 Hercules Blog Webcam -ov534 06f8:3003 Hercules Dualpix HD Weblog +ov534_9 06f8:3003 Hercules Dualpix HD Weblog sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3008 Hercules Deluxe Optical Glass pac7302 06f8:3009 Hercules Classic Link @@ -204,6 +214,7 @@ sunplus 0733:2221 Mercury Digital Pro 3.1p sunplus 0733:3261 Concord 3045 spca536a sunplus 0733:3281 Cyberpix S550V spca506 0734:043b 3DeMon USB Capture aka +cpia1 0813:0001 QX3 camera ov519 0813:0002 Dual Mode USB Camera Plus spca500 084d:0003 D-Link DSC-350 spca500 08ca:0103 Aiptek PocketDV @@ -225,7 +236,8 @@ sunplus 08ca:2050 Medion MD 41437 sunplus 08ca:2060 Aiptek PocketDV5300 tv8532 0923:010f ICM532 cams mars 093a:050f Mars-Semi Pc-Camera -mr97310a 093a:010f Sakar Digital no. 77379 +mr97310a 093a:010e All known CIF cams with this ID +mr97310a 093a:010f All known VGA cams with this ID pac207 093a:2460 Qtec Webcam 100 pac207 093a:2461 HP Webcam pac207 093a:2463 Philips SPC 220 NC @@ -246,6 +258,7 @@ pac7302 093a:2620 Apollo AC-905 pac7302 093a:2621 PAC731x pac7302 093a:2622 Genius Eye 312 pac7302 093a:2624 PAC7302 +pac7302 093a:2625 Genius iSlim 310 pac7302 093a:2626 Labtec 2200 pac7302 093a:2628 Genius iLook 300 pac7302 093a:2629 Genious iSlim 300 @@ -283,6 +296,7 @@ sonixb 0c45:602e Genius VideoCam Messenger sonixj 0c45:6040 Speed NVC 350K sonixj 0c45:607c Sonix sn9c102p Hv7131R sonixj 0c45:60c0 Sangha Sn535 +sonixj 0c45:60ce USB-PC-Camera-168 (TALK-5067) sonixj 0c45:60ec SN9C105+MO4000 sonixj 0c45:60fb Surfer NoName sonixj 0c45:60fc LG-LIC300 @@ -300,11 +314,14 @@ sonixj 0c45:6138 Sn9c120 Mo4000 sonixj 0c45:613a Microdia Sonix PC Camera sonixj 0c45:613b Surfer SN-206 sonixj 0c45:613c Sonix Pccam168 +sonixj 0c45:6142 Hama PC-Webcam AC-150 sonixj 0c45:6143 Sonix Pccam168 sonixj 0c45:6148 Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia +sonixj 0c45:614a Frontech E-Ccam (JIL-2225) sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001) sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111) sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655) +sn9c20x 0c45:624c PC Camera (SN9C201 + MT9M112) sn9c20x 0c45:624e PC Camera (SN9C201 + SOI968) sn9c20x 0c45:624f PC Camera (SN9C201 + OV9650) sn9c20x 0c45:6251 PC Camera (SN9C201 + OV9650) @@ -317,6 +334,7 @@ sn9c20x 0c45:627f PC Camera (SN9C201 + OV9650) sn9c20x 0c45:6280 PC Camera (SN9C202 + MT9M001) sn9c20x 0c45:6282 PC Camera (SN9C202 + MT9M111) sn9c20x 0c45:6288 PC Camera (SN9C202 + OV9655) +sn9c20x 0c45:628c PC Camera (SN9C201 + MT9M112) sn9c20x 0c45:628e PC Camera (SN9C202 + SOI968) sn9c20x 0c45:628f PC Camera (SN9C202 + OV9650) sn9c20x 0c45:62a0 PC Camera (SN9C202 + OV7670) @@ -324,6 +342,10 @@ sn9c20x 0c45:62b0 PC Camera (SN9C202 + MT9V011/MT9V111/MT9V112) sn9c20x 0c45:62b3 PC Camera (SN9C202 + OV9655) sn9c20x 0c45:62bb PC Camera (SN9C202 + OV7660) sn9c20x 0c45:62bc PC Camera (SN9C202 + HV7131R) +sn9c2028 0c45:8001 Wild Planet Digital Spy Camera +sn9c2028 0c45:8003 Sakar #11199, #6637x, #67480 keychain cams +sn9c2028 0c45:8008 Mini-Shotz ms-350 +sn9c2028 0c45:800a Vivitar Vivicam 3350B sunplus 0d64:0303 Sunplus FashionCam DXG ov519 0e96:c001 TRUST 380 USB2 SPACEC@M etoms 102c:6151 Qcam Sangha CIF @@ -341,10 +363,13 @@ spca501 1776:501c Arowana 300K CMOS Camera t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC pac207 2001:f115 D-Link DSB-C120 -sq905c 2770:9050 sq905c -sq905c 2770:905c DualCamera -sq905 2770:9120 Argus Digital Camera DC1512 -sq905c 2770:913d sq905c +sq905c 2770:9050 Disney pix micro (CIF) +sq905c 2770:9052 Disney pix micro 2 (VGA) +sq905c 2770:905c All 11 known cameras with this ID +sq905 2770:9120 All 24 known cameras with this ID +sq905c 2770:913d All 4 known cameras with this ID +sq930x 2770:930b Sweex Motion Tracking / I-Tec iCam Tracer +sq930x 2770:930c Trust WB-3500T / NSG Robbie 2.0 spca500 2899:012c Toptro Industrial ov519 8020:ef04 ov519 spca508 8086:0110 Intel Easy PC Camera diff --git a/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt index faccee68f60..a2fd363c40c 100644 --- a/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt +++ b/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt @@ -44,7 +44,7 @@ http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf This data sheet (google search) seems to have a lovely description of the RC5 basics -http://users.pandora.be/nenya/electronics/rc5/ and more data +http://www.nenya.be/beor/electronics/rc5.htm and more data http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt and even a reference to how to decode a bi-phase data stream. diff --git a/Documentation/video4linux/ibmcam.txt b/Documentation/video4linux/ibmcam.txt index 397a94eb77b..a51055211e6 100644 --- a/Documentation/video4linux/ibmcam.txt +++ b/Documentation/video4linux/ibmcam.txt @@ -27,9 +27,8 @@ SUPPORTED CAMERAS: Xirlink "C-It" camera, also known as "IBM PC Camera". The device uses proprietary ASIC (and compression method); -it is manufactured by Xirlink. See http://www.xirlink.com/ -(renamed to http://www.veo.com), http://www.ibmpccamera.com, -or http://www.c-itnow.com/ for details and pictures. +it is manufactured by Xirlink. See http://xirlinkwebcam.sourceforge.net, +http://www.ibmpccamera.com, or http://www.c-itnow.com/ for details and pictures. This very chipset ("X Chip", as marked at the factory) is used in several other cameras, and they are supported diff --git a/Documentation/video4linux/se401.txt b/Documentation/video4linux/se401.txt index 7b9d1c960a1..bd6526ec8dd 100644 --- a/Documentation/video4linux/se401.txt +++ b/Documentation/video4linux/se401.txt @@ -49,6 +49,6 @@ order to increase the throughput (and thus framerate). HELP: The latest info on this driver can be found at: -http://www.chello.nl/~j.vreeken/se401/ +http://members.chello.nl/~j.vreeken/se401/ And questions to me can be send to: pe1rxq@amsat.org diff --git a/Documentation/video4linux/sh_mobile_ceu_camera.txt b/Documentation/video4linux/sh_mobile_ceu_camera.txt index 2ae16349a78..cb47e723af7 100644 --- a/Documentation/video4linux/sh_mobile_ceu_camera.txt +++ b/Documentation/video4linux/sh_mobile_ceu_camera.txt @@ -17,18 +17,18 @@ Generic scaling / cropping scheme -2-- -\ | --\ | --\ -+-5-- -\ -- -3-- -| ---\ -| --- -4-- -\ -| -\ -| - -6-- ++-5-- . -- -3-- -\ +| `... -\ +| `... -4-- . - -7.. +| `. +| `. .6-- | -| - -6'- -| -/ -| --- -4'- -/ -| ---/ -+-5'- -/ -| -- -3'- +| . .6'- +| .´ +| ... -4'- .´ +| ...´ - -7'. ++-5'- .´ -/ +| -- -3'- -/ | --/ | --/ -2'- -/ @@ -36,7 +36,11 @@ Generic scaling / cropping scheme | -1'- -Produced by user requests: +In the above chart minuses and slashes represent "real" data amounts, points and +accents represent "useful" data, basically, CEU scaled amd cropped output, +mapped back onto the client's source plane. + +Such a configuration can be produced by user requests: S_CROP(left / top = (5) - (1), width / height = (5') - (5)) S_FMT(width / height = (6') - (6)) @@ -106,52 +110,30 @@ window: S_CROP ------ -If old scale applied to new crop is invalid produce nearest new scale possible - -1. Calculate current combined scales. - - scale_comb = (((4') - (4)) / ((6') - (6))) * (((2') - (2)) / ((3') - (3))) - -2. Apply iterative sensor S_CROP for new input window. - -3. If old combined scales applied to new crop produce an impossible user window, -adjust scales to produce nearest possible window. - - width_u_out = ((5') - (5)) / scale_comb +The API at http://v4l2spec.bytesex.org/spec/x1904.htm says: - if (width_u_out > max) - scale_comb = ((5') - (5)) / max; - else if (width_u_out < min) - scale_comb = ((5') - (5)) / min; +"...specification does not define an origin or units. However by convention +drivers should horizontally count unscaled samples relative to 0H." -4. Issue G_CROP to retrieve actual input window. +We choose to follow the advise and interpret cropping units as client input +pixels. -5. Using actual input window and calculated combined scales calculate sensor -target output window. - - width_s_out = ((3') - (3)) = ((2') - (2)) / scale_comb - -6. Apply iterative S_FMT for new sensor target output window. - -7. Issue G_FMT to retrieve the actual sensor output window. - -8. Calculate sensor scales. - - scale_s = ((3') - (3)) / ((2') - (2)) +Cropping is performed in the following 6 steps: -9. Calculate sensor output subwindow to be cropped on CEU by applying sensor -scales to the requested window. +1. Request exactly user rectangle from the sensor. - width_ceu = ((5') - (5)) / scale_s +2. If smaller - iterate until a larger one is obtained. Result: sensor cropped + to 2 : 2', target crop 5 : 5', current output format 6' - 6. -10. Use CEU cropping for above calculated window. +3. In the previous step the sensor has tried to preserve its output frame as + good as possible, but it could have changed. Retrieve it again. -11. Calculate CEU scales from sensor scales from results of (10) and user window -from (3) +4. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate + intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2) - scale_ceu = calc_scale(((5') - (5)), &width_u_out) +5. Calculate and apply host scale = (6' - 6) / (4' - 4) -12. Apply CEU scales. +6. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5) -- Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt new file mode 100644 index 00000000000..8773778d23f --- /dev/null +++ b/Documentation/video4linux/v4l2-controls.txt @@ -0,0 +1,648 @@ +Introduction +============ + +The V4L2 control API seems simple enough, but quickly becomes very hard to +implement correctly in drivers. But much of the code needed to handle controls +is actually not driver specific and can be moved to the V4L core framework. + +After all, the only part that a driver developer is interested in is: + +1) How do I add a control? +2) How do I set the control's value? (i.e. s_ctrl) + +And occasionally: + +3) How do I get the control's value? (i.e. g_volatile_ctrl) +4) How do I validate the user's proposed control value? (i.e. try_ctrl) + +All the rest is something that can be done centrally. + +The control framework was created in order to implement all the rules of the +V4L2 specification with respect to controls in a central place. And to make +life as easy as possible for the driver developer. + +Note that the control framework relies on the presence of a struct v4l2_device +for V4L2 drivers and struct v4l2_subdev for sub-device drivers. + + +Objects in the framework +======================== + +There are two main objects: + +The v4l2_ctrl object describes the control properties and keeps track of the +control's value (both the current value and the proposed new value). + +v4l2_ctrl_handler is the object that keeps track of controls. It maintains a +list of v4l2_ctrl objects that it owns and another list of references to +controls, possibly to controls owned by other handlers. + + +Basic usage for V4L2 and sub-device drivers +=========================================== + +1) Prepare the driver: + +1.1) Add the handler to your driver's top-level struct: + + struct foo_dev { + ... + struct v4l2_ctrl_handler ctrl_handler; + ... + }; + + struct foo_dev *foo; + +1.2) Initialize the handler: + + v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls); + + The second argument is a hint telling the function how many controls this + handler is expected to handle. It will allocate a hashtable based on this + information. It is a hint only. + +1.3) Hook the control handler into the driver: + +1.3.1) For V4L2 drivers do this: + + struct foo_dev { + ... + struct v4l2_device v4l2_dev; + ... + struct v4l2_ctrl_handler ctrl_handler; + ... + }; + + foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler; + + Where foo->v4l2_dev is of type struct v4l2_device. + + Finally, remove all control functions from your v4l2_ioctl_ops: + vidioc_queryctrl, vidioc_querymenu, vidioc_g_ctrl, vidioc_s_ctrl, + vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls. + Those are now no longer needed. + +1.3.2) For sub-device drivers do this: + + struct foo_dev { + ... + struct v4l2_subdev sd; + ... + struct v4l2_ctrl_handler ctrl_handler; + ... + }; + + foo->sd.ctrl_handler = &foo->ctrl_handler; + + Where foo->sd is of type struct v4l2_subdev. + + And set all core control ops in your struct v4l2_subdev_core_ops to these + helpers: + + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + + Note: this is a temporary solution only. Once all V4L2 drivers that depend + on subdev drivers are converted to the control framework these helpers will + no longer be needed. + +1.4) Clean up the handler at the end: + + v4l2_ctrl_handler_free(&foo->ctrl_handler); + + +2) Add controls: + +You add non-menu controls by calling v4l2_ctrl_new_std: + + struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, + const struct v4l2_ctrl_ops *ops, + u32 id, s32 min, s32 max, u32 step, s32 def); + +Menu controls are added by calling v4l2_ctrl_new_std_menu: + + struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, + const struct v4l2_ctrl_ops *ops, + u32 id, s32 max, s32 skip_mask, s32 def); + +These functions are typically called right after the v4l2_ctrl_handler_init: + + v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls); + v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); + v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 128); + v4l2_ctrl_new_std_menu(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_POWER_LINE_FREQUENCY, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); + ... + if (foo->ctrl_handler.error) { + int err = foo->ctrl_handler.error; + + v4l2_ctrl_handler_free(&foo->ctrl_handler); + return err; + } + +The v4l2_ctrl_new_std function returns the v4l2_ctrl pointer to the new +control, but if you do not need to access the pointer outside the control ops, +then there is no need to store it. + +The v4l2_ctrl_new_std function will fill in most fields based on the control +ID except for the min, max, step and default values. These are passed in the +last four arguments. These values are driver specific while control attributes +like type, name, flags are all global. The control's current value will be set +to the default value. + +The v4l2_ctrl_new_std_menu function is very similar but it is used for menu +controls. There is no min argument since that is always 0 for menu controls, +and instead of a step there is a skip_mask argument: if bit X is 1, then menu +item X is skipped. + +Note that if something fails, the function will return NULL or an error and +set ctrl_handler->error to the error code. If ctrl_handler->error was already +set, then it will just return and do nothing. This is also true for +v4l2_ctrl_handler_init if it cannot allocate the internal data structure. + +This makes it easy to init the handler and just add all controls and only check +the error code at the end. Saves a lot of repetitive error checking. + +It is recommended to add controls in ascending control ID order: it will be +a bit faster that way. + +3) Optionally force initial control setup: + + v4l2_ctrl_handler_setup(&foo->ctrl_handler); + +This will call s_ctrl for all controls unconditionally. Effectively this +initializes the hardware to the default control values. It is recommended +that you do this as this ensures that both the internal data structures and +the hardware are in sync. + +4) Finally: implement the v4l2_ctrl_ops + + static const struct v4l2_ctrl_ops foo_ctrl_ops = { + .s_ctrl = foo_s_ctrl, + }; + +Usually all you need is s_ctrl: + + static int foo_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + write_reg(0x123, ctrl->val); + break; + case V4L2_CID_CONTRAST: + write_reg(0x456, ctrl->val); + break; + } + return 0; + } + +The control ops are called with the v4l2_ctrl pointer as argument. +The new control value has already been validated, so all you need to do is +to actually update the hardware registers. + +You're done! And this is sufficient for most of the drivers we have. No need +to do any validation of control values, or implement QUERYCTRL/QUERYMENU. And +G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported. + + +============================================================================== + +The remainder of this document deals with more advanced topics and scenarios. +In practice the basic usage as described above is sufficient for most drivers. + +=============================================================================== + + +Inheriting Controls +=================== + +When a sub-device is registered with a V4L2 driver by calling +v4l2_device_register_subdev() and the ctrl_handler fields of both v4l2_subdev +and v4l2_device are set, then the controls of the subdev will become +automatically available in the V4L2 driver as well. If the subdev driver +contains controls that already exist in the V4L2 driver, then those will be +skipped (so a V4L2 driver can always override a subdev control). + +What happens here is that v4l2_device_register_subdev() calls +v4l2_ctrl_add_handler() adding the controls of the subdev to the controls +of v4l2_device. + + +Accessing Control Values +======================== + +The v4l2_ctrl struct contains these two unions: + + /* The current control value. */ + union { + s32 val; + s64 val64; + char *string; + } cur; + + /* The new control value. */ + union { + s32 val; + s64 val64; + char *string; + }; + +Within the control ops you can freely use these. The val and val64 speak for +themselves. The string pointers point to character buffers of length +ctrl->maximum + 1, and are always 0-terminated. + +In most cases 'cur' contains the current cached control value. When you create +a new control this value is made identical to the default value. After calling +v4l2_ctrl_handler_setup() this value is passed to the hardware. It is generally +a good idea to call this function. + +Whenever a new value is set that new value is automatically cached. This means +that most drivers do not need to implement the g_volatile_ctrl() op. The +exception is for controls that return a volatile register such as a signal +strength read-out that changes continuously. In that case you will need to +implement g_volatile_ctrl like this: + + static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl) + { + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->cur.val = read_reg(0x123); + break; + } + } + +The 'new value' union is not used in g_volatile_ctrl. In general controls +that need to implement g_volatile_ctrl are read-only controls. + +To mark a control as volatile you have to set the is_volatile flag: + + ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...); + if (ctrl) + ctrl->is_volatile = 1; + +For try/s_ctrl the new values (i.e. as passed by the user) are filled in and +you can modify them in try_ctrl or set them in s_ctrl. The 'cur' union +contains the current value, which you can use (but not change!) as well. + +If s_ctrl returns 0 (OK), then the control framework will copy the new final +values to the 'cur' union. + +While in g_volatile/s/try_ctrl you can access the value of all controls owned +by the same handler since the handler's lock is held. If you need to access +the value of controls owned by other handlers, then you have to be very careful +not to introduce deadlocks. + +Outside of the control ops you have to go through to helper functions to get +or set a single control value safely in your driver: + + s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl); + int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val); + +These functions go through the control framework just as VIDIOC_G/S_CTRL ioctls +do. Don't use these inside the control ops g_volatile/s/try_ctrl, though, that +will result in a deadlock since these helpers lock the handler as well. + +You can also take the handler lock yourself: + + mutex_lock(&state->ctrl_handler.lock); + printk(KERN_INFO "String value is '%s'\n", ctrl1->cur.string); + printk(KERN_INFO "Integer value is '%s'\n", ctrl2->cur.val); + mutex_unlock(&state->ctrl_handler.lock); + + +Menu Controls +============= + +The v4l2_ctrl struct contains this union: + + union { + u32 step; + u32 menu_skip_mask; + }; + +For menu controls menu_skip_mask is used. What it does is that it allows you +to easily exclude certain menu items. This is used in the VIDIOC_QUERYMENU +implementation where you can return -EINVAL if a certain menu item is not +present. Note that VIDIOC_QUERYCTRL always returns a step value of 1 for +menu controls. + +A good example is the MPEG Audio Layer II Bitrate menu control where the +menu is a list of standardized possible bitrates. But in practice hardware +implementations will only support a subset of those. By setting the skip +mask you can tell the framework which menu items should be skipped. Setting +it to 0 means that all menu items are supported. + +You set this mask either through the v4l2_ctrl_config struct for a custom +control, or by calling v4l2_ctrl_new_std_menu(). + + +Custom Controls +=============== + +Driver specific controls can be created using v4l2_ctrl_new_custom(): + + static const struct v4l2_ctrl_config ctrl_filter = { + .ops = &ctrl_custom_ops, + .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, + .name = "Spatial Filter", + .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, + .max = 15, + .step = 1, + }; + + ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_filter, NULL); + +The last argument is the priv pointer which can be set to driver-specific +private data. + +The v4l2_ctrl_config struct also has fields to set the is_private and is_volatile +flags. + +If the name field is not set, then the framework will assume this is a standard +control and will fill in the name, type and flags fields accordingly. + + +Active and Grabbed Controls +=========================== + +If you get more complex relationships between controls, then you may have to +activate and deactivate controls. For example, if the Chroma AGC control is +on, then the Chroma Gain control is inactive. That is, you may set it, but +the value will not be used by the hardware as long as the automatic gain +control is on. Typically user interfaces can disable such input fields. + +You can set the 'active' status using v4l2_ctrl_activate(). By default all +controls are active. Note that the framework does not check for this flag. +It is meant purely for GUIs. The function is typically called from within +s_ctrl. + +The other flag is the 'grabbed' flag. A grabbed control means that you cannot +change it because it is in use by some resource. Typical examples are MPEG +bitrate controls that cannot be changed while capturing is in progress. + +If a control is set to 'grabbed' using v4l2_ctrl_grab(), then the framework +will return -EBUSY if an attempt is made to set this control. The +v4l2_ctrl_grab() function is typically called from the driver when it +starts or stops streaming. + + +Control Clusters +================ + +By default all controls are independent from the others. But in more +complex scenarios you can get dependencies from one control to another. +In that case you need to 'cluster' them: + + struct foo { + struct v4l2_ctrl_handler ctrl_handler; +#define AUDIO_CL_VOLUME (0) +#define AUDIO_CL_MUTE (1) + struct v4l2_ctrl *audio_cluster[2]; + ... + }; + + state->audio_cluster[AUDIO_CL_VOLUME] = + v4l2_ctrl_new_std(&state->ctrl_handler, ...); + state->audio_cluster[AUDIO_CL_MUTE] = + v4l2_ctrl_new_std(&state->ctrl_handler, ...); + v4l2_ctrl_cluster(ARRAY_SIZE(state->audio_cluster), state->audio_cluster); + +From now on whenever one or more of the controls belonging to the same +cluster is set (or 'gotten', or 'tried'), only the control ops of the first +control ('volume' in this example) is called. You effectively create a new +composite control. Similar to how a 'struct' works in C. + +So when s_ctrl is called with V4L2_CID_AUDIO_VOLUME as argument, you should set +all two controls belonging to the audio_cluster: + + static int foo_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: { + struct v4l2_ctrl *mute = ctrl->cluster[AUDIO_CL_MUTE]; + + write_reg(0x123, mute->val ? 0 : ctrl->val); + break; + } + case V4L2_CID_CONTRAST: + write_reg(0x456, ctrl->val); + break; + } + return 0; + } + +In the example above the following are equivalent for the VOLUME case: + + ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == state->audio_cluster[AUDIO_CL_VOLUME] + ctrl->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE] + +Note that controls in a cluster may be NULL. For example, if for some +reason mute was never added (because the hardware doesn't support that +particular feature), then mute will be NULL. So in that case we have a +cluster of 2 controls, of which only 1 is actually instantiated. The +only restriction is that the first control of the cluster must always be +present, since that is the 'master' control of the cluster. The master +control is the one that identifies the cluster and that provides the +pointer to the v4l2_ctrl_ops struct that is used for that cluster. + +Obviously, all controls in the cluster array must be initialized to either +a valid control or to NULL. + + +VIDIOC_LOG_STATUS Support +========================= + +This ioctl allow you to dump the current status of a driver to the kernel log. +The v4l2_ctrl_handler_log_status(ctrl_handler, prefix) can be used to dump the +value of the controls owned by the given handler to the log. You can supply a +prefix as well. If the prefix didn't end with a space, then ': ' will be added +for you. + + +Different Handlers for Different Video Nodes +============================================ + +Usually the V4L2 driver has just one control handler that is global for +all video nodes. But you can also specify different control handlers for +different video nodes. You can do that by manually setting the ctrl_handler +field of struct video_device. + +That is no problem if there are no subdevs involved but if there are, then +you need to block the automatic merging of subdev controls to the global +control handler. You do that by simply setting the ctrl_handler field in +struct v4l2_device to NULL. Now v4l2_device_register_subdev() will no longer +merge subdev controls. + +After each subdev was added, you will then have to call v4l2_ctrl_add_handler +manually to add the subdev's control handler (sd->ctrl_handler) to the desired +control handler. This control handler may be specific to the video_device or +for a subset of video_device's. For example: the radio device nodes only have +audio controls, while the video and vbi device nodes share the same control +handler for the audio and video controls. + +If you want to have one handler (e.g. for a radio device node) have a subset +of another handler (e.g. for a video device node), then you should first add +the controls to the first handler, add the other controls to the second +handler and finally add the first handler to the second. For example: + + v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...); + v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...); + v4l2_ctrl_add_handler(&video_ctrl_handler, &radio_ctrl_handler); + +Or you can add specific controls to a handler: + + volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...); + v4l2_ctrl_add_ctrl(&radio_ctrl_handler, volume); + +What you should not do is make two identical controls for two handlers. +For example: + + v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_AUDIO_MUTE, ...); + +This would be bad since muting the radio would not change the video mute +control. The rule is to have one control for each hardware 'knob' that you +can twiddle. + + +Finding Controls +================ + +Normally you have created the controls yourself and you can store the struct +v4l2_ctrl pointer into your own struct. + +But sometimes you need to find a control from another handler that you do +not own. For example, if you have to find a volume control from a subdev. + +You can do that by calling v4l2_ctrl_find: + + struct v4l2_ctrl *volume; + + volume = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_AUDIO_VOLUME); + +Since v4l2_ctrl_find will lock the handler you have to be careful where you +use it. For example, this is not a good idea: + + struct v4l2_ctrl_handler ctrl_handler; + + v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...); + v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...); + +...and in video_ops.s_ctrl: + + case V4L2_CID_BRIGHTNESS: + contrast = v4l2_find_ctrl(&ctrl_handler, V4L2_CID_CONTRAST); + ... + +When s_ctrl is called by the framework the ctrl_handler.lock is already taken, so +attempting to find another control from the same handler will deadlock. + +It is recommended not to use this function from inside the control ops. + + +Inheriting Controls +=================== + +When one control handler is added to another using v4l2_ctrl_add_handler, then +by default all controls from one are merged to the other. But a subdev might +have low-level controls that make sense for some advanced embedded system, but +not when it is used in consumer-level hardware. In that case you want to keep +those low-level controls local to the subdev. You can do this by simply +setting the 'is_private' flag of the control to 1: + + static const struct v4l2_ctrl_config ctrl_private = { + .ops = &ctrl_custom_ops, + .id = V4L2_CID_..., + .name = "Some Private Control", + .type = V4L2_CTRL_TYPE_INTEGER, + .max = 15, + .step = 1, + .is_private = 1, + }; + + ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_private, NULL); + +These controls will now be skipped when v4l2_ctrl_add_handler is called. + + +V4L2_CTRL_TYPE_CTRL_CLASS Controls +================================== + +Controls of this type can be used by GUIs to get the name of the control class. +A fully featured GUI can make a dialog with multiple tabs with each tab +containing the controls belonging to a particular control class. The name of +each tab can be found by querying a special control with ID <control class | 1>. + +Drivers do not have to care about this. The framework will automatically add +a control of this type whenever the first control belonging to a new control +class is added. + + +Differences from the Spec +========================= + +There are a few places where the framework acts slightly differently from the +V4L2 Specification. Those differences are described in this section. We will +have to see whether we need to adjust the spec or not. + +1) It is no longer required to have all controls contained in a +v4l2_ext_control array be from the same control class. The framework will be +able to handle any type of control in the array. You need to set ctrl_class +to 0 in order to enable this. If ctrl_class is non-zero, then it will still +check that all controls belong to that control class. + +If you set ctrl_class to 0 and count to 0, then it will only return an error +if there are no controls at all. + +2) Clarified the way error_idx works. For get and set it will be equal to +count if nothing was done yet. If it is less than count then only the controls +up to error_idx-1 were successfully applied. + +3) When attempting to read a button control the framework will return -EACCES +instead of -EINVAL as stated in the spec. It seems to make more sense since +button controls are write-only controls. + +4) Attempting to write to a read-only control will return -EACCES instead of +-EINVAL as the spec says. + +5) The spec does not mention what should happen when you try to set/get a +control class controls. ivtv currently returns -EINVAL (indicating that the +control ID does not exist) while the framework will return -EACCES, which +makes more sense. + + +Proposals for Extensions +======================== + +Some ideas for future extensions to the spec: + +1) Add a V4L2_CTRL_FLAG_HEX to have values shown as hexadecimal instead of +decimal. Useful for e.g. video_mute_yuv. + +2) It is possible to mark in the controls array which controls have been +successfully written and which failed by for example adding a bit to the +control ID. Not sure if it is worth the effort, though. + +3) Trying to set volatile inactive controls should result in -EACCESS. + +4) Add a new flag to mark volatile controls. Any application that wants +to store the state of the controls can then skip volatile inactive controls. +Currently it is not possible to detect such controls. diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 74d677c8b03..e831aaca66f 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -545,12 +545,11 @@ unregister them: This will remove the device nodes from sysfs (causing udev to remove them from /dev). -After video_unregister_device() returns no new opens can be done. - -However, in the case of USB devices some application might still have one -of these device nodes open. You should block all new accesses to read, -write, poll, etc. except possibly for certain ioctl operations like -queueing buffers. +After video_unregister_device() returns no new opens can be done. However, +in the case of USB devices some application might still have one of these +device nodes open. So after the unregister all file operations will return +an error as well, except for the ioctl and unlocked_ioctl file operations: +those will still be passed on since some buffer ioctls may still be needed. When the last user of the video device node exits, then the vdev->release() callback is called and you can do the final cleanup there. @@ -599,99 +598,145 @@ video_device::minor fields. video buffer helper functions ----------------------------- -The v4l2 core API provides a standard method for dealing with video -buffers. Those methods allow a driver to implement read(), mmap() and -overlay() on a consistent way. - -There are currently methods for using video buffers on devices that -supports DMA with scatter/gather method (videobuf-dma-sg), DMA with -linear access (videobuf-dma-contig), and vmalloced buffers, mostly -used on USB drivers (videobuf-vmalloc). - -Any driver using videobuf should provide operations (callbacks) for -four handlers: - -ops->buf_setup - calculates the size of the video buffers and avoid they - to waste more than some maximum limit of RAM; -ops->buf_prepare - fills the video buffer structs and calls - videobuf_iolock() to alloc and prepare mmaped memory; -ops->buf_queue - advices the driver that another buffer were - requested (by read() or by QBUF); -ops->buf_release - frees any buffer that were allocated. - -In order to use it, the driver need to have a code (generally called at -interrupt context) that will properly handle the buffer request lists, -announcing that a new buffer were filled. - -The irq handling code should handle the videobuf task lists, in order -to advice videobuf that a new frame were filled, in order to honor to a -request. The code is generally like this one: - if (list_empty(&dma_q->active)) - return; - - buf = list_entry(dma_q->active.next, struct vbuffer, vb.queue); - - if (!waitqueue_active(&buf->vb.done)) - return; - - /* Some logic to handle the buf may be needed here */ - - list_del(&buf->vb.queue); - do_gettimeofday(&buf->vb.ts); - wake_up(&buf->vb.done); - -Those are the videobuffer functions used on drivers, implemented on -videobuf-core: - -- Videobuf init functions - videobuf_queue_sg_init() - Initializes the videobuf infrastructure. This function should be - called before any other videobuf function on drivers that uses DMA - Scatter/Gather buffers. - - videobuf_queue_dma_contig_init - Initializes the videobuf infrastructure. This function should be - called before any other videobuf function on drivers that need DMA - contiguous buffers. - - videobuf_queue_vmalloc_init() - Initializes the videobuf infrastructure. This function should be - called before any other videobuf function on USB (and other drivers) - that need a vmalloced type of videobuf. - -- videobuf_iolock() - Prepares the videobuf memory for the proper method (read, mmap, overlay). - -- videobuf_queue_is_busy() - Checks if a videobuf is streaming. - -- videobuf_queue_cancel() - Stops video handling. - -- videobuf_mmap_free() - frees mmap buffers. - -- videobuf_stop() - Stops video handling, ends mmap and frees mmap and other buffers. - -- V4L2 api functions. Those functions correspond to VIDIOC_foo ioctls: - videobuf_reqbufs(), videobuf_querybuf(), videobuf_qbuf(), - videobuf_dqbuf(), videobuf_streamon(), videobuf_streamoff(). - -- V4L1 api function (corresponds to VIDIOCMBUF ioctl): - videobuf_cgmbuf() - This function is used to provide backward compatibility with V4L1 - API. - -- Some help functions for read()/poll() operations: - videobuf_read_stream() - For continuous stream read() - videobuf_read_one() - For snapshot read() - videobuf_poll_stream() - polling help function - -The better way to understand it is to take a look at vivi driver. One -of the main reasons for vivi is to be a videobuf usage example. the -vivi_thread_tick() does the task that the IRQ callback would do on PCI -drivers (or the irq callback on USB). +The v4l2 core API provides a set of standard methods (called "videobuf") +for dealing with video buffers. Those methods allow a driver to implement +read(), mmap() and overlay() in a consistent way. There are currently +methods for using video buffers on devices that supports DMA with +scatter/gather method (videobuf-dma-sg), DMA with linear access +(videobuf-dma-contig), and vmalloced buffers, mostly used on USB drivers +(videobuf-vmalloc). + +Please see Documentation/video4linux/videobuf for more information on how +to use the videobuf layer. + +struct v4l2_fh +-------------- + +struct v4l2_fh provides a way to easily keep file handle specific data +that is used by the V4L2 framework. Using v4l2_fh is optional for +drivers. + +The users of v4l2_fh (in the V4L2 framework, not the driver) know +whether a driver uses v4l2_fh as its file->private_data pointer by +testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags. + +Useful functions: + +- v4l2_fh_init() + + Initialise the file handle. This *MUST* be performed in the driver's + v4l2_file_operations->open() handler. + +- v4l2_fh_add() + + Add a v4l2_fh to video_device file handle list. May be called after + initialising the file handle. + +- v4l2_fh_del() + + Unassociate the file handle from video_device(). The file handle + exit function may now be called. + +- v4l2_fh_exit() + + Uninitialise the file handle. After uninitialisation the v4l2_fh + memory can be freed. + +struct v4l2_fh is allocated as a part of the driver's own file handle +structure and is set to file->private_data in the driver's open +function by the driver. Drivers can extract their own file handle +structure by using the container_of macro. Example: + +struct my_fh { + int blah; + struct v4l2_fh fh; +}; + +... + +int my_open(struct file *file) +{ + struct my_fh *my_fh; + struct video_device *vfd; + int ret; + + ... + + ret = v4l2_fh_init(&my_fh->fh, vfd); + if (ret) + return ret; + + v4l2_fh_add(&my_fh->fh); + + file->private_data = &my_fh->fh; + + ... +} + +int my_release(struct file *file) +{ + struct v4l2_fh *fh = file->private_data; + struct my_fh *my_fh = container_of(fh, struct my_fh, fh); + + ... +} + +V4L2 events +----------- + +The V4L2 events provide a generic way to pass events to user space. +The driver must use v4l2_fh to be able to support V4L2 events. + +Useful functions: + +- v4l2_event_alloc() + + To use events, the driver must allocate events for the file handle. By + calling the function more than once, the driver may assure that at least n + events in total have been allocated. The function may not be called in + atomic context. + +- v4l2_event_queue() + + Queue events to video device. The driver's only responsibility is to fill + in the type and the data fields. The other fields will be filled in by + V4L2. + +- v4l2_event_subscribe() + + The video_device->ioctl_ops->vidioc_subscribe_event must check the driver + is able to produce events with specified event id. Then it calls + v4l2_event_subscribe() to subscribe the event. + +- v4l2_event_unsubscribe() + + vidioc_unsubscribe_event in struct v4l2_ioctl_ops. A driver may use + v4l2_event_unsubscribe() directly unless it wants to be involved in + unsubscription process. + + The special type V4L2_EVENT_ALL may be used to unsubscribe all events. The + drivers may want to handle this in a special way. + +- v4l2_event_pending() + + Returns the number of pending events. Useful when implementing poll. + +Drivers do not initialise events directly. The events are initialised +through v4l2_fh_init() if video_device->ioctl_ops->vidioc_subscribe_event is +non-NULL. This *MUST* be performed in the driver's +v4l2_file_operations->open() handler. + +Events are delivered to user space through the poll system call. The driver +can use v4l2_fh->events->wait wait_queue_head_t as the argument for +poll_wait(). + +There are standard and private events. New standard events must use the +smallest available event type. The drivers must allocate their events from +their own class starting from class base. Class base is +V4L2_EVENT_PRIVATE_START + n * 1000 where n is the lowest available number. +The first event type in the class is reserved for future use, so the first +available event type is 'class base + 1'. + +An example on how the V4L2 events may be used can be found in the OMAP +3 ISP driver available at <URL:http://gitorious.org/omap3camera> as of +writing this. diff --git a/Documentation/video4linux/videobuf b/Documentation/video4linux/videobuf new file mode 100644 index 00000000000..17a1f9abf26 --- /dev/null +++ b/Documentation/video4linux/videobuf @@ -0,0 +1,360 @@ +An introduction to the videobuf layer +Jonathan Corbet <corbet@lwn.net> +Current as of 2.6.33 + +The videobuf layer functions as a sort of glue layer between a V4L2 driver +and user space. It handles the allocation and management of buffers for +the storage of video frames. There is a set of functions which can be used +to implement many of the standard POSIX I/O system calls, including read(), +poll(), and, happily, mmap(). Another set of functions can be used to +implement the bulk of the V4L2 ioctl() calls related to streaming I/O, +including buffer allocation, queueing and dequeueing, and streaming +control. Using videobuf imposes a few design decisions on the driver +author, but the payback comes in the form of reduced code in the driver and +a consistent implementation of the V4L2 user-space API. + +Buffer types + +Not all video devices use the same kind of buffers. In fact, there are (at +least) three common variations: + + - Buffers which are scattered in both the physical and (kernel) virtual + address spaces. (Almost) all user-space buffers are like this, but it + makes great sense to allocate kernel-space buffers this way as well when + it is possible. Unfortunately, it is not always possible; working with + this kind of buffer normally requires hardware which can do + scatter/gather DMA operations. + + - Buffers which are physically scattered, but which are virtually + contiguous; buffers allocated with vmalloc(), in other words. These + buffers are just as hard to use for DMA operations, but they can be + useful in situations where DMA is not available but virtually-contiguous + buffers are convenient. + + - Buffers which are physically contiguous. Allocation of this kind of + buffer can be unreliable on fragmented systems, but simpler DMA + controllers cannot deal with anything else. + +Videobuf can work with all three types of buffers, but the driver author +must pick one at the outset and design the driver around that decision. + +[It's worth noting that there's a fourth kind of buffer: "overlay" buffers +which are located within the system's video memory. The overlay +functionality is considered to be deprecated for most use, but it still +shows up occasionally in system-on-chip drivers where the performance +benefits merit the use of this technique. Overlay buffers can be handled +as a form of scattered buffer, but there are very few implementations in +the kernel and a description of this technique is currently beyond the +scope of this document.] + +Data structures, callbacks, and initialization + +Depending on which type of buffers are being used, the driver should +include one of the following files: + + <media/videobuf-dma-sg.h> /* Physically scattered */ + <media/videobuf-vmalloc.h> /* vmalloc() buffers */ + <media/videobuf-dma-contig.h> /* Physically contiguous */ + +The driver's data structure describing a V4L2 device should include a +struct videobuf_queue instance for the management of the buffer queue, +along with a list_head for the queue of available buffers. There will also +need to be an interrupt-safe spinlock which is used to protect (at least) +the queue. + +The next step is to write four simple callbacks to help videobuf deal with +the management of buffers: + + struct videobuf_queue_ops { + int (*buf_setup)(struct videobuf_queue *q, + unsigned int *count, unsigned int *size); + int (*buf_prepare)(struct videobuf_queue *q, + struct videobuf_buffer *vb, + enum v4l2_field field); + void (*buf_queue)(struct videobuf_queue *q, + struct videobuf_buffer *vb); + void (*buf_release)(struct videobuf_queue *q, + struct videobuf_buffer *vb); + }; + +buf_setup() is called early in the I/O process, when streaming is being +initiated; its purpose is to tell videobuf about the I/O stream. The count +parameter will be a suggested number of buffers to use; the driver should +check it for rationality and adjust it if need be. As a practical rule, a +minimum of two buffers are needed for proper streaming, and there is +usually a maximum (which cannot exceed 32) which makes sense for each +device. The size parameter should be set to the expected (maximum) size +for each frame of data. + +Each buffer (in the form of a struct videobuf_buffer pointer) will be +passed to buf_prepare(), which should set the buffer's size, width, height, +and field fields properly. If the buffer's state field is +VIDEOBUF_NEEDS_INIT, the driver should pass it to: + + int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, + struct v4l2_framebuffer *fbuf); + +Among other things, this call will usually allocate memory for the buffer. +Finally, the buf_prepare() function should set the buffer's state to +VIDEOBUF_PREPARED. + +When a buffer is queued for I/O, it is passed to buf_queue(), which should +put it onto the driver's list of available buffers and set its state to +VIDEOBUF_QUEUED. Note that this function is called with the queue spinlock +held; if it tries to acquire it as well things will come to a screeching +halt. Yes, this is the voice of experience. Note also that videobuf may +wait on the first buffer in the queue; placing other buffers in front of it +could again gum up the works. So use list_add_tail() to enqueue buffers. + +Finally, buf_release() is called when a buffer is no longer intended to be +used. The driver should ensure that there is no I/O active on the buffer, +then pass it to the appropriate free routine(s): + + /* Scatter/gather drivers */ + int videobuf_dma_unmap(struct videobuf_queue *q, + struct videobuf_dmabuf *dma); + int videobuf_dma_free(struct videobuf_dmabuf *dma); + + /* vmalloc drivers */ + void videobuf_vmalloc_free (struct videobuf_buffer *buf); + + /* Contiguous drivers */ + void videobuf_dma_contig_free(struct videobuf_queue *q, + struct videobuf_buffer *buf); + +One way to ensure that a buffer is no longer under I/O is to pass it to: + + int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); + +Here, vb is the buffer, non_blocking indicates whether non-blocking I/O +should be used (it should be zero in the buf_release() case), and intr +controls whether an interruptible wait is used. + +File operations + +At this point, much of the work is done; much of the rest is slipping +videobuf calls into the implementation of the other driver callbacks. The +first step is in the open() function, which must initialize the +videobuf queue. The function to use depends on the type of buffer used: + + void videobuf_queue_sg_init(struct videobuf_queue *q, + struct videobuf_queue_ops *ops, + struct device *dev, + spinlock_t *irqlock, + enum v4l2_buf_type type, + enum v4l2_field field, + unsigned int msize, + void *priv); + + void videobuf_queue_vmalloc_init(struct videobuf_queue *q, + struct videobuf_queue_ops *ops, + struct device *dev, + spinlock_t *irqlock, + enum v4l2_buf_type type, + enum v4l2_field field, + unsigned int msize, + void *priv); + + void videobuf_queue_dma_contig_init(struct videobuf_queue *q, + struct videobuf_queue_ops *ops, + struct device *dev, + spinlock_t *irqlock, + enum v4l2_buf_type type, + enum v4l2_field field, + unsigned int msize, + void *priv); + +In each case, the parameters are the same: q is the queue structure for the +device, ops is the set of callbacks as described above, dev is the device +structure for this video device, irqlock is an interrupt-safe spinlock to +protect access to the data structures, type is the buffer type used by the +device (cameras will use V4L2_BUF_TYPE_VIDEO_CAPTURE, for example), field +describes which field is being captured (often V4L2_FIELD_NONE for +progressive devices), msize is the size of any containing structure used +around struct videobuf_buffer, and priv is a private data pointer which +shows up in the priv_data field of struct videobuf_queue. Note that these +are void functions which, evidently, are immune to failure. + +V4L2 capture drivers can be written to support either of two APIs: the +read() system call and the rather more complicated streaming mechanism. As +a general rule, it is necessary to support both to ensure that all +applications have a chance of working with the device. Videobuf makes it +easy to do that with the same code. To implement read(), the driver need +only make a call to one of: + + ssize_t videobuf_read_one(struct videobuf_queue *q, + char __user *data, size_t count, + loff_t *ppos, int nonblocking); + + ssize_t videobuf_read_stream(struct videobuf_queue *q, + char __user *data, size_t count, + loff_t *ppos, int vbihack, int nonblocking); + +Either one of these functions will read frame data into data, returning the +amount actually read; the difference is that videobuf_read_one() will only +read a single frame, while videobuf_read_stream() will read multiple frames +if they are needed to satisfy the count requested by the application. A +typical driver read() implementation will start the capture engine, call +one of the above functions, then stop the engine before returning (though a +smarter implementation might leave the engine running for a little while in +anticipation of another read() call happening in the near future). + +The poll() function can usually be implemented with a direct call to: + + unsigned int videobuf_poll_stream(struct file *file, + struct videobuf_queue *q, + poll_table *wait); + +Note that the actual wait queue eventually used will be the one associated +with the first available buffer. + +When streaming I/O is done to kernel-space buffers, the driver must support +the mmap() system call to enable user space to access the data. In many +V4L2 drivers, the often-complex mmap() implementation simplifies to a +single call to: + + int videobuf_mmap_mapper(struct videobuf_queue *q, + struct vm_area_struct *vma); + +Everything else is handled by the videobuf code. + +The release() function requires two separate videobuf calls: + + void videobuf_stop(struct videobuf_queue *q); + int videobuf_mmap_free(struct videobuf_queue *q); + +The call to videobuf_stop() terminates any I/O in progress - though it is +still up to the driver to stop the capture engine. The call to +videobuf_mmap_free() will ensure that all buffers have been unmapped; if +so, they will all be passed to the buf_release() callback. If buffers +remain mapped, videobuf_mmap_free() returns an error code instead. The +purpose is clearly to cause the closing of the file descriptor to fail if +buffers are still mapped, but every driver in the 2.6.32 kernel cheerfully +ignores its return value. + +ioctl() operations + +The V4L2 API includes a very long list of driver callbacks to respond to +the many ioctl() commands made available to user space. A number of these +- those associated with streaming I/O - turn almost directly into videobuf +calls. The relevant helper functions are: + + int videobuf_reqbufs(struct videobuf_queue *q, + struct v4l2_requestbuffers *req); + int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b); + int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b); + int videobuf_dqbuf(struct videobuf_queue *q, struct v4l2_buffer *b, + int nonblocking); + int videobuf_streamon(struct videobuf_queue *q); + int videobuf_streamoff(struct videobuf_queue *q); + int videobuf_cgmbuf(struct videobuf_queue *q, struct video_mbuf *mbuf, + int count); + +So, for example, a VIDIOC_REQBUFS call turns into a call to the driver's +vidioc_reqbufs() callback which, in turn, usually only needs to locate the +proper struct videobuf_queue pointer and pass it to videobuf_reqbufs(). +These support functions can replace a great deal of buffer management +boilerplate in a lot of V4L2 drivers. + +The vidioc_streamon() and vidioc_streamoff() functions will be a bit more +complex, of course, since they will also need to deal with starting and +stopping the capture engine. videobuf_cgmbuf(), called from the driver's +vidiocgmbuf() function, only exists if the V4L1 compatibility module has +been selected with CONFIG_VIDEO_V4L1_COMPAT, so its use must be surrounded +with #ifdef directives. + +Buffer allocation + +Thus far, we have talked about buffers, but have not looked at how they are +allocated. The scatter/gather case is the most complex on this front. For +allocation, the driver can leave buffer allocation entirely up to the +videobuf layer; in this case, buffers will be allocated as anonymous +user-space pages and will be very scattered indeed. If the application is +using user-space buffers, no allocation is needed; the videobuf layer will +take care of calling get_user_pages() and filling in the scatterlist array. + +If the driver needs to do its own memory allocation, it should be done in +the vidioc_reqbufs() function, *after* calling videobuf_reqbufs(). The +first step is a call to: + + struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); + +The returned videobuf_dmabuf structure (defined in +<media/videobuf-dma-sg.h>) includes a couple of relevant fields: + + struct scatterlist *sglist; + int sglen; + +The driver must allocate an appropriately-sized scatterlist array and +populate it with pointers to the pieces of the allocated buffer; sglen +should be set to the length of the array. + +Drivers using the vmalloc() method need not (and cannot) concern themselves +with buffer allocation at all; videobuf will handle those details. The +same is normally true of contiguous-DMA drivers as well; videobuf will +allocate the buffers (with dma_alloc_coherent()) when it sees fit. That +means that these drivers may be trying to do high-order allocations at any +time, an operation which is not always guaranteed to work. Some drivers +play tricks by allocating DMA space at system boot time; videobuf does not +currently play well with those drivers. + +As of 2.6.31, contiguous-DMA drivers can work with a user-supplied buffer, +as long as that buffer is physically contiguous. Normal user-space +allocations will not meet that criterion, but buffers obtained from other +kernel drivers, or those contained within huge pages, will work with these +drivers. + +Filling the buffers + +The final part of a videobuf implementation has no direct callback - it's +the portion of the code which actually puts frame data into the buffers, +usually in response to interrupts from the device. For all types of +drivers, this process works approximately as follows: + + - Obtain the next available buffer and make sure that somebody is actually + waiting for it. + + - Get a pointer to the memory and put video data there. + + - Mark the buffer as done and wake up the process waiting for it. + +Step (1) above is done by looking at the driver-managed list_head structure +- the one which is filled in the buf_queue() callback. Because starting +the engine and enqueueing buffers are done in separate steps, it's possible +for the engine to be running without any buffers available - in the +vmalloc() case especially. So the driver should be prepared for the list +to be empty. It is equally possible that nobody is yet interested in the +buffer; the driver should not remove it from the list or fill it until a +process is waiting on it. That test can be done by examining the buffer's +done field (a wait_queue_head_t structure) with waitqueue_active(). + +A buffer's state should be set to VIDEOBUF_ACTIVE before being mapped for +DMA; that ensures that the videobuf layer will not try to do anything with +it while the device is transferring data. + +For scatter/gather drivers, the needed memory pointers will be found in the +scatterlist structure described above. Drivers using the vmalloc() method +can get a memory pointer with: + + void *videobuf_to_vmalloc(struct videobuf_buffer *buf); + +For contiguous DMA drivers, the function to use is: + + dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf); + +The contiguous DMA API goes out of its way to hide the kernel-space address +of the DMA buffer from drivers. + +The final step is to set the size field of the relevant videobuf_buffer +structure to the actual size of the captured image, set state to +VIDEOBUF_DONE, then call wake_up() on the done queue. At this point, the +buffer is owned by the videobuf layer and the driver should not touch it +again. + +Developers who are interested in more information can go into the relevant +header files; there are a few low-level functions declared there which have +not been talked about here. Also worthwhile is the vivi driver +(drivers/media/video/vivi.c), which is maintained as an example of how V4L2 +drivers should be written. Vivi only uses the vmalloc() API, but it's good +enough to get started with. Note also that all of these calls are exported +GPL-only, so they will not be available to non-GPL kernel modules. diff --git a/Documentation/video4linux/w9966.txt b/Documentation/video4linux/w9966.txt index 78a651254b8..855024525fd 100644 --- a/Documentation/video4linux/w9966.txt +++ b/Documentation/video4linux/w9966.txt @@ -24,7 +24,7 @@ where every two pixels take 4 bytes. In SDL (www.libsdl.org) this format is called VIDEO_PALETTE_YUV422 (16 bpp). A minimal test application (with source) is available from: - http://hem.fyristorg.com/mogul/w9966.html + http://www.slackwaresupport.com/howtos/Webcam-HOWTO The slow framerate is due to missing DMA ECP read support in the parport drivers. I might add working EPP support later. |