V4L/DVB (8157): gspca: all subdrivers

- remaning subdrivers added
- remove the decoding helper and some specific frame decodings

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Jean-Francois Moine 2008-06-30 15:50:11 -03:00 коммит произвёл Mauro Carvalho Chehab
Родитель d43fa32fec
Коммит 6a7eba24e4
27 изменённых файлов: 21990 добавлений и 1010 удалений

Просмотреть файл

@ -1,4 +1,4 @@
Here the list of the known working cameras with gspca.
List of the webcams know by gspca.
The modules are:
gspca_main main driver
@ -6,203 +6,50 @@ The modules are:
xxxx vend:prod
----
conex 0572:0041 Creative Notebook cx11646
etoms 102c:6151 Qcam Sangha CIF
etoms 102c:6251 Qcam xxxxxx VGA
mars 093a:050f Mars-Semi Pc-Camera
ov519 041e:4052 Creative Live! VISTA IM
ov519 041e:405f Creative Live! VISTA VF0330
ov519 041e:4060 Creative Live! VISTA VF0350
ov519 041e:4061 Creative Live! VISTA VF0400
ov519 041e:4064 Creative Live! VISTA VF0420
ov519 041e:4068 Creative Live! VISTA VF0470
ov519 045e:028c Micro$oft xbox cam
ov519 054c:0154 Sonny toy4
ov519 054c:0155 Sonny toy5
ov519 05a9:0519 OmniVision
ov519 05a9:4519 OmniVision
ov519 05a9:8519 OmniVision
ov519 05a9:0530 OmniVision
pac207 041e:4028 Creative Webcam Vista Plus
pac207 093a:2460 PAC207 Qtec Webcam 100
pac207 093a:2463 Philips spc200nc pac207
pac207 093a:2464 Labtec Webcam 1200
pac207 093a:2468 PAC207
pac207 093a:2470 Genius GF112
pac207 093a:2471 PAC207 Genius VideoCam ge111
pac207 093a:2472 PAC207 Genius VideoCam ge110
pac7311 093a:2600 PAC7311 Typhoon
pac7311 093a:2601 PAC7311 Phillips SPC610NC
pac7311 093a:2603 PAC7312
pac7311 093a:2608 PAC7311 Trust WB-3300p
pac7311 093a:260e PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
pac7311 093a:260f PAC7311 SnakeCam
sonixb 0c45:6001 Genius VideoCAM NB
sonixb 0c45:6005 Sweex Tas5110
sonixb 0c45:6007 Sonix sn9c101 + Tas5110D
sonixb 0c45:6009 spcaCam@120
sonixb 0c45:600d spcaCam@120
sonixb 0c45:6011 MAX Webcam (Microdia - OV6650 - SN9C101G)
sonixb 0c45:6019 Generic Sonix OV7630
sonixb 0c45:6024 Generic Sonix Tas5130c
sonixb 0c45:6025 Xcam Shanga
sonixb 0c45:6028 Sonix Btc Pc380
sonixb 0c45:6029 spcaCam@150
sonixb 0c45:602c Generic Sonix OV7630
sonixb 0c45:602d LIC-200 LG
sonixb 0c45:602e Genius VideoCam Messenger
sonixj 0458:7025 Genius Eye 311Q
sonixj 045e:00f5 MicroSoft VX3000
sonixj 045e:00f7 MicroSoft VX1000
sonixj 0471:0327 Philips SPC 600 NC
sonixj 0471:0328 Philips SPC 700 NC
sonixj 0471:0330 Philips SPC 710NC
sonixj 0c45:6040 Speed NVC 350K
sonixj 0c45:607c Sonix sn9c102p Hv7131R
sonixj 0c45:60c0 Sangha Sn535
sonixj 0c45:60ec SN9C105+MO4000
sonixj 0c45:60fb Surfer NoName
sonixj 0c45:60fc LG-LIC300
sonixj 0c45:612a Avant Camera
sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
sonixj 0c45:6130 Sonix Pccam
sonixj 0c45:6138 Sn9c120 Mo4000
sonixj 0c45:613b Surfer SN-206
sonixj 0c45:613c Sonix Pccam168
spca500 040a:0300 Kodak EZ200
spca500 041e:400a Creative PC-CAM 300
spca500 046d:0890 Logitech QuickCam traveler
spca500 046d:0900 Logitech Inc. ClickSmart 310
spca500 046d:0901 Logitech Inc. ClickSmart 510
spca500 04a5:300c Benq DC1016
spca500 04fc:7333 PalmPixDC85
spca500 055f:c200 Mustek Gsmart 300
spca500 055f:c220 Gsmart Mini
spca500 06bd:0404 Agfa CL20
spca500 06be:0800 Optimedia
spca500 084d:0003 D-Link DSC-350
spca500 08ca:0103 Aiptek PocketDV
spca500 2899:012c Toptro Industrial
spca500 8086:0630 Intel Pocket PC Camera
spca501 040a:0002 Kodak DVC-325
spca501 0497:c001 Smile International
spca501 0506:00df 3Com HomeConnect Lite
spca501 0733:0401 Intel Create and Share
spca501 0733:0402 ViewQuest M318B
spca501 1776:501c Arowana 300K CMOS Camera
spca501 0000:0000 MystFromOri Unknow Camera
spca505 041e:401d Creative Webcam NX ULTRA
spca505 0733:0430 Intel PC Camera Pro
spca506 06e1:a190 ADS Instant VCD
spca506 0734:043b 3DeMon USB Capture aka
spca506 99fa:8988 Grandtec V.cap
spca506 99fa:8988 Grandtec V.cap
spca508 041e:4018 Creative Webcam Vista (PD1100)
spca508 0461:0815 Micro Innovation IC200
spca508 0733:0110 ViewQuest VQ110
spca508 0af9:0010 Hama USB Sightcam 100
spca508 0af9:0011 Hama USB Sightcam 100
spca508 8086:0110 Intel Easy PC Camera
spca561 041e:401a Creative Webcam Vista (PD1100)
spca561 041e:403b Creative Webcam Vista (VF0010)
spca561 0458:7004 Genius VideoCAM Express V2
spca561 046d:0928 Logitech QC Express Etch2
spca561 046d:0929 Labtec Webcam Elch2
spca561 046d:092a Logitech QC for Notebook
spca561 046d:092b Labtec Webcam Plus
spca561 046d:092c Logitech QC chat Elch2
spca561 046d:092d Logitech QC Elch2
spca561 046d:092e Logitech QC Elch2
spca561 046d:092f Logitech QC Elch2
spca561 04fc:0561 Flexcam 100
spca561 060b:a001 Maxell Compact Pc PM3
spca561 10fd:7e50 FlyCam Usb 100
spca561 abcd:cdee Petcam
stk014 05e1:0893 Syntek DV4000
spca501 040a:0002 Kodak DVC-325
spca500 040a:0300 Kodak EZ200
zc3xx 041e:041e Creative WebCam Live!
spca500 041e:400a Creative PC-CAM 300
sunplus 041e:400b Creative PC-CAM 600
sunplus 041e:4012 PC-Cam350
sunplus 041e:4013 Creative Pccam750
sunplus 0458:7006 Genius Dsc 1.3 Smart
sunplus 046d:0905 Logitech ClickSmart 820
sunplus 046d:0960 Logitech ClickSmart 420
sunplus 0471:0322 Philips DMVC1300K
sunplus 04a5:3003 Benq DC 1300
sunplus 04a5:3008 Benq DC 1500
sunplus 04a5:300a Benq DC3410
sunplus 04f1:1001 JVC GC A50
sunplus 04fc:500c Sunplus CA500C
sunplus 04fc:504a Aiptek Mini PenCam 1.3
sunplus 04fc:504b Maxell MaxPocket LE 1.3
sunplus 04fc:5330 Digitrex 2110
sunplus 04fc:5360 Sunplus Generic
sunplus 04fc:ffff Pure DigitalDakota
sunplus 052b:1513 Megapix V4
sunplus 0546:3155 Polaroid PDC3070
sunplus 0546:3191 Polaroid Ion 80
sunplus 0546:3273 Polaroid PDC2030
sunplus 055f:c211 Kowa Bs888e Microcamera
sunplus 055f:c230 Mustek Digicam 330K
sunplus 055f:c232 Mustek MDC3500
sunplus 055f:c360 Mustek DV4000 Mpeg4
sunplus 055f:c420 Mustek gSmart Mini 2
sunplus 055f:c430 Mustek Gsmart LCD 2
sunplus 055f:c440 Mustek DV 3000
sunplus 055f:c520 Mustek gSmart Mini 3
sunplus 055f:c530 Mustek Gsmart LCD 3
sunplus 055f:c540 Gsmart D30
sunplus 055f:c630 Mustek MDC4000
sunplus 055f:c650 Mustek MDC5500Z
sunplus 05da:1018 Digital Dream Enigma 1.3
sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom
sunplus 0733:1311 Digital Dream Epsilon 1.3
sunplus 0733:1314 Mercury 2.1MEG Deluxe Classic Cam
sunplus 0733:2211 Jenoptik jdc 21 LCD
sunplus 0733:2221 Mercury Digital Pro 3.1p
sunplus 0733:3261 Concord 3045 spca536a
sunplus 0733:3281 Cyberpix S550V
sunplus 08ca:0104 Aiptek PocketDVII 1.3
sunplus 08ca:0106 Aiptek Pocket DV3100+
sunplus 08ca:2008 Aiptek Mini PenCam 2 M
sunplus 08ca:2010 Aiptek PocketCam 3M
sunplus 08ca:2016 Aiptek PocketCam 2 Mega
sunplus 08ca:2018 Aiptek Pencam SD 2M
sunplus 08ca:2020 Aiptek Slim 3000F
sunplus 08ca:2022 Aiptek Slim 3200
sunplus 08ca:2024 Aiptek DV3500 Mpeg4
sunplus 08ca:2028 Aiptek PocketCam4M
sunplus 08ca:2040 Aiptek PocketDV4100M
sunplus 08ca:2042 Aiptek PocketDV5100
sunplus 08ca:2060 Aiptek PocketDV5300
sunplus 0d64:0303 Sunplus FashionCam DXG
tv8532 046d:0920 QC Express
tv8532 046d:0921 Labtec Webcam
tv8532 0545:808b Veo Stingray
tv8532 0545:8333 Veo Stingray
tv8532 0923:010f ICM532 cams
vc032x 046d:0892 Logitech Orbicam
vc032x 046d:0896 Logitech Orbicam
vc032x 0ac8:0321 Vimicro generic vc0321
vc032x 0ac8:0323 Vimicro Vc0323
vc032x 0ac8:0328 A4Tech PK-130MG
vc032x 0ac8:c001 Sony embedded vimicro
vc032x 0ac8:c002 Sony embedded vimicro
vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
zc3xx 041e:041e Creative WebCam Live!
zc3xx 041e:4017 Creative Webcam Mobile PD1090
spca508 041e:4018 Creative Webcam Vista (PD1100)
spca561 041e:401a Creative Webcam Vista (PD1100)
zc3xx 041e:401c Creative NX
spca505 041e:401d Creative Webcam NX ULTRA
zc3xx 041e:401e Creative Nx Pro
zc3xx 041e:401f Creative Webcam Notebook PD1171
pac207 041e:4028 Creative Webcam Vista Plus
zc3xx 041e:4029 Creative WebCam Vista Pro
zc3xx 041e:4034 Creative Instant P0620
zc3xx 041e:4035 Creative Instant P0620D
zc3xx 041e:4036 Creative Live !
zc3xx 041e:403a Creative Nx Pro 2
spca561 041e:403b Creative Webcam Vista (VF0010)
zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250)
ov519 041e:4052 Creative Live! VISTA IM
zc3xx 041e:4053 Creative Live!Cam Video IM
ov519 041e:405f Creative Live! VISTA VF0330
ov519 041e:4060 Creative Live! VISTA VF0350
ov519 041e:4061 Creative Live! VISTA VF0400
ov519 041e:4064 Creative Live! VISTA VF0420
ov519 041e:4068 Creative Live! VISTA VF0470
spca561 0458:7004 Genius VideoCAM Express V2
sunplus 0458:7006 Genius Dsc 1.3 Smart
zc3xx 0458:7007 Genius VideoCam V2
zc3xx 0458:700c Genius VideoCam V3
zc3xx 0458:700f Genius VideoCam Web V2
sonixj 0458:7025 Genius Eye 311Q
sonixj 045e:00f5 MicroSoft VX3000
sonixj 045e:00f7 MicroSoft VX1000
ov519 045e:028c Micro$oft xbox cam
spca508 0461:0815 Micro Innovation IC200
zc3xx 0461:0a00 MicroInnovation WebCam320
spca500 046d:0890 Logitech QuickCam traveler
vc032x 046d:0892 Logitech Orbicam
vc032x 046d:0896 Logitech Orbicam
zc3xx 046d:08a0 Logitech QC IM
zc3xx 046d:08a1 Logitech QC IM 0x08A1 +sound
zc3xx 046d:08a2 Labtec Webcam Pro
@ -221,18 +68,173 @@ zc3xx 046d:08d9 Logitech QuickCam IM/Connect
zc3xx 046d:08d8 Logitech Notebook Deluxe
zc3xx 046d:08da Logitech QuickCam Messenger
zc3xx 046d:08dd Logitech QuickCam for Notebooks
spca500 046d:0900 Logitech Inc. ClickSmart 310
spca500 046d:0901 Logitech Inc. ClickSmart 510
sunplus 046d:0905 Logitech ClickSmart 820
tv8532 046d:0920 QC Express
tv8532 046d:0921 Labtec Webcam
spca561 046d:0928 Logitech QC Express Etch2
spca561 046d:0929 Labtec Webcam Elch2
spca561 046d:092a Logitech QC for Notebook
spca561 046d:092b Labtec Webcam Plus
spca561 046d:092c Logitech QC chat Elch2
spca561 046d:092d Logitech QC Elch2
spca561 046d:092e Logitech QC Elch2
spca561 046d:092f Logitech QC Elch2
sunplus 046d:0960 Logitech ClickSmart 420
sunplus 0471:0322 Philips DMVC1300K
zc3xx 0471:0325 Philips SPC 200 NC
zc3xx 0471:0326 Philips SPC 300 NC
sonixj 0471:0327 Philips SPC 600 NC
sonixj 0471:0328 Philips SPC 700 NC
zc3xx 0471:032d Philips spc210nc
zc3xx 0471:032e Philips spc315nc
sonixj 0471:0330 Philips SPC 710NC
spca501 0497:c001 Smile International
sunplus 04a5:3003 Benq DC 1300
sunplus 04a5:3008 Benq DC 1500
sunplus 04a5:300a Benq DC3410
spca500 04a5:300c Benq DC1016
sunplus 04f1:1001 JVC GC A50
spca561 04fc:0561 Flexcam 100
sunplus 04fc:500c Sunplus CA500C
sunplus 04fc:504a Aiptek Mini PenCam 1.3
sunplus 04fc:504b Maxell MaxPocket LE 1.3
sunplus 04fc:5330 Digitrex 2110
sunplus 04fc:5360 Sunplus Generic
spca500 04fc:7333 PalmPixDC85
sunplus 04fc:ffff Pure DigitalDakota
spca501 0506:00df 3Com HomeConnect Lite
sunplus 052b:1513 Megapix V4
tv8532 0545:808b Veo Stingray
tv8532 0545:8333 Veo Stingray
sunplus 0546:3155 Polaroid PDC3070
sunplus 0546:3191 Polaroid Ion 80
sunplus 0546:3273 Polaroid PDC2030
ov519 054c:0154 Sonny toy4
ov519 054c:0155 Sonny toy5
zc3xx 055f:c005 Mustek Wcam300A
spca500 055f:c200 Mustek Gsmart 300
sunplus 055f:c211 Kowa Bs888e Microcamera
spca500 055f:c220 Gsmart Mini
sunplus 055f:c230 Mustek Digicam 330K
sunplus 055f:c232 Mustek MDC3500
sunplus 055f:c360 Mustek DV4000 Mpeg4
sunplus 055f:c420 Mustek gSmart Mini 2
sunplus 055f:c430 Mustek Gsmart LCD 2
sunplus 055f:c440 Mustek DV 3000
sunplus 055f:c520 Mustek gSmart Mini 3
sunplus 055f:c530 Mustek Gsmart LCD 3
sunplus 055f:c540 Gsmart D30
sunplus 055f:c630 Mustek MDC4000
sunplus 055f:c650 Mustek MDC5500Z
zc3xx 055f:d003 Mustek WCam300A
zc3xx 055f:d004 Mustek WCam300 AN
conex 0572:0041 Creative Notebook cx11646
ov519 05a9:0519 OmniVision
ov519 05a9:0530 OmniVision
ov519 05a9:4519 OmniVision
ov519 05a9:8519 OmniVision
sunplus 05da:1018 Digital Dream Enigma 1.3
stk014 05e1:0893 Syntek DV4000
spca561 060b:a001 Maxell Compact Pc PM3
zc3xx 0698:2003 CTX M730V built in
spca500 06bd:0404 Agfa CL20
spca500 06be:0800 Optimedia
sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom
spca506 06e1:a190 ADS Instant VCD
spca508 0733:0110 ViewQuest VQ110
spca501 0733:0401 Intel Create and Share
spca501 0733:0402 ViewQuest M318B
spca505 0733:0430 Intel PC Camera Pro
sunplus 0733:1311 Digital Dream Epsilon 1.3
sunplus 0733:1314 Mercury 2.1MEG Deluxe Classic Cam
sunplus 0733:2211 Jenoptik jdc 21 LCD
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
spca500 084d:0003 D-Link DSC-350
spca500 08ca:0103 Aiptek PocketDV
sunplus 08ca:0104 Aiptek PocketDVII 1.3
sunplus 08ca:0106 Aiptek Pocket DV3100+
sunplus 08ca:2008 Aiptek Mini PenCam 2 M
sunplus 08ca:2010 Aiptek PocketCam 3M
sunplus 08ca:2016 Aiptek PocketCam 2 Mega
sunplus 08ca:2018 Aiptek Pencam SD 2M
sunplus 08ca:2020 Aiptek Slim 3000F
sunplus 08ca:2022 Aiptek Slim 3200
sunplus 08ca:2024 Aiptek DV3500 Mpeg4
sunplus 08ca:2028 Aiptek PocketCam4M
sunplus 08ca:2040 Aiptek PocketDV4100M
sunplus 08ca:2042 Aiptek PocketDV5100
sunplus 08ca:2060 Aiptek PocketDV5300
tv8532 0923:010f ICM532 cams
mars 093a:050f Mars-Semi Pc-Camera
pac207 093a:2460 PAC207 Qtec Webcam 100
pac207 093a:2463 Philips spc200nc pac207
pac207 093a:2464 Labtec Webcam 1200
pac207 093a:2468 PAC207
pac207 093a:2470 Genius GF112
pac207 093a:2471 PAC207 Genius VideoCam ge111
pac207 093a:2472 PAC207 Genius VideoCam ge110
pac7311 093a:2600 PAC7311 Typhoon
pac7311 093a:2601 PAC7311 Phillips SPC610NC
pac7311 093a:2603 PAC7312
pac7311 093a:2608 PAC7311 Trust WB-3300p
pac7311 093a:260e PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
pac7311 093a:260f PAC7311 SnakeCam
pac7311 093a:2621 PAC731x
zc3xx 0ac8:0302 Z-star Vimicro zc0302
vc032x 0ac8:0321 Vimicro generic vc0321
vc032x 0ac8:0323 Vimicro Vc0323
vc032x 0ac8:0328 A4Tech PK-130MG
zc3xx 0ac8:301b Z-Star zc301b
zc3xx 0ac8:303b Vimicro 0x303b
zc3xx 0ac8:305b Z-star Vimicro zc0305b
zc3xx 0ac8:307b Ldlc VC302+Ov7620
vc032x 0ac8:c001 Sony embedded vimicro
vc032x 0ac8:c002 Sony embedded vimicro
spca508 0af9:0010 Hama USB Sightcam 100
spca508 0af9:0011 Hama USB Sightcam 100
sonixb 0c45:6001 Genius VideoCAM NB
sonixb 0c45:6005 Sweex Tas5110
sonixb 0c45:6007 Sonix sn9c101 + Tas5110D
sonixb 0c45:6009 spcaCam@120
sonixb 0c45:600d spcaCam@120
sonixb 0c45:6011 MAX Webcam (Microdia - OV6650 - SN9C101G)
sonixb 0c45:6019 Generic Sonix OV7630
sonixb 0c45:6024 Generic Sonix Tas5130c
sonixb 0c45:6025 Xcam Shanga
sonixb 0c45:6028 Sonix Btc Pc380
sonixb 0c45:6029 spcaCam@150
sonixb 0c45:602c Generic Sonix OV7630
sonixb 0c45:602d LIC-200 LG
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:60ec SN9C105+MO4000
sonixj 0c45:60fb Surfer NoName
sonixj 0c45:60fc LG-LIC300
sonixj 0c45:612a Avant Camera
sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
sonixj 0c45:6130 Sonix Pccam
sonixj 0c45:6138 Sn9c120 Mo4000
sonixj 0c45:613b Surfer SN-206
sonixj 0c45:613c Sonix Pccam168
sunplus 0d64:0303 Sunplus FashionCam DXG
etoms 102c:6151 Qcam Sangha CIF
etoms 102c:6251 Qcam xxxxxx VGA
zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128
spca561 10fd:7e50 FlyCam Usb 100
zc3xx 10fd:8050 Typhoon Webshot II USB 300k
spca501 1776:501c Arowana 300K CMOS Camera
t613 17a1:0128 T613/TAS5130A
vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
pac207 2001:f115 D-Link DSB-C120
spca500 2899:012c Toptro Industrial
spca508 8086:0110 Intel Easy PC Camera
spca500 8086:0630 Intel Pocket PC Camera
spca506 99fa:8988 Grandtec V.cap
spca561 abcd:cdee Petcam

Просмотреть файл

@ -117,6 +117,7 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102/
obj-$(CONFIG_USB_ET61X251) += et61x251/
obj-$(CONFIG_USB_PWC) += pwc/
obj-$(CONFIG_USB_ZC0301) += zc0301/
obj-$(CONFIG_USB_GSPCA) += gspca/
obj-$(CONFIG_USB_IBMCAM) += usbvideo/
obj-$(CONFIG_USB_KONICAWC) += usbvideo/

Просмотреть файл

@ -2,7 +2,7 @@ config USB_GSPCA
tristate "USB GSPCA driver"
depends on VIDEO_V4L2
---help---
Say Y here if you want support for various USB cameras.
Say Y here if you want support for various USB webcams.
See <file:Documentation/video4linux/gspca.txt> for more info.

Просмотреть файл

@ -1,7 +1,29 @@
obj-$(CONFIG_GSPCA) += gspca_main.o \
gspca_pac207.o gspca_stk014.o gspca_zc3xx.o
obj-$(CONFIG_USB_GSPCA) += gspca_main.o \
gspca_conex.o gspca_etoms.o gspca_mars.o \
gspca_ov519.o gspca_pac207.o gspca_pac7311.o \
gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \
gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \
gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \
gspca_vc032x.o gspca_zc3xx.o
gspca_main-objs := gspca.o
gspca_conex-objs := conex.o
gspca_etoms-objs := etoms.o
gspca_mars-objs := mars.o
gspca_ov519-objs := ov519.o
gspca_pac207-objs := pac207.o
gspca_pac7311-objs := pac7311.o
gspca_sonixb-objs := sonixb.o
gspca_sonixj-objs := sonixj.o
gspca_spca500-objs := spca500.o
gspca_spca501-objs := spca501.o
gspca_spca505-objs := spca505.o
gspca_spca506-objs := spca506.o
gspca_spca508-objs := spca508.o
gspca_spca561-objs := spca561.o
gspca_stk014-objs := stk014.o
gspca_sunplus-objs := sunplus.o
gspca_t613-objs := t613.o
gspca_tv8532-objs := tv8532.o
gspca_vc032x-objs := vc032x.o
gspca_zc3xx-objs := zc3xx.o

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -35,24 +35,24 @@
#include "gspca.h"
/* option */
#define GSPCA_HLP 0
#undef CONFIG_VIDEO_V4L1_COMPAT
/* global values */
#define DEF_NURBS 2 /* default number of URBs (mmap) */
#define USR_NURBS 5 /* default number of URBs (userptr) */
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 15)
static const char version[] = "0.2.15";
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
static int video_nr = -1;
static int comp_fac = 30; /* Buffer size ratio when compressed in % */
#ifdef GSPCA_DEBUG
#ifdef VIDEO_ADV_DEBUG
int gspca_debug = D_ERR | D_PROBE;
EXPORT_SYMBOL(gspca_debug);
@ -81,224 +81,7 @@ static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
#define GSPCA_MEMORY_READ 7
#ifndef GSPCA_HLP
#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
#else
#define GSPCA_BUF_FLAG_DECODE 0x1000 /* internal buffer flag */
#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE \
| GSPCA_BUF_FLAG_DECODE)
static int autostart = 4;
module_param(autostart, int, 0644);
MODULE_PARM_DESC(autostart,
"Automatically start the helper process");
/* try to start the helper process */
static void start_hlp(void)
{
int ret;
static char *argv[] = {"gspca_hlp", NULL};
static char *env[] = {NULL};
if (autostart <= 0) {
if (autostart < 0)
PDEBUG(D_ERR|D_PROBE, "Too many helper restart");
return;
}
autostart--;
if (autostart == 0)
autostart = -1;
ret = call_usermodehelper("/sbin/gspca_hlp", argv, env,
UMH_WAIT_EXEC);
if (ret != 0)
PDEBUG(D_ERR|D_PROBE,
"/sbin/gspca_hlp start failed %d", ret);
}
/* /dev/gspca_hlp stuff */
#include <linux/miscdevice.h>
#include "gspca_hlp.h"
/* !! possible decodings defined in decoder.c */
static __u32 bayer_to_tb[] = {
V4L2_PIX_FMT_SBGGR8,
V4L2_PIX_FMT_YUYV,
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_RGB24,
V4L2_PIX_FMT_BGR24,
V4L2_PIX_FMT_RGB565,
};
static __u32 jpeg_to_tb[] = {
V4L2_PIX_FMT_JPEG,
V4L2_PIX_FMT_YUYV,
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_RGB24,
V4L2_PIX_FMT_BGR24,
V4L2_PIX_FMT_RGB565,
};
/* /dev/gspca_hlp device */
struct hlp_dev {
struct gspca_dev *gspca_dev; /* associated device */
struct gspca_frame *frame; /* frame being decoded */
__u32 pixfmt; /* webcam pixel format */
atomic_t nevent; /* nb of frames ready to decode */
wait_queue_head_t wq; /* wait queue */
char fr_d; /* next frame to decode */
} *hlp;
static int hlp_open(struct inode *inode, struct file *file)
{
struct hlp_dev *hlp_dev;
PDEBUG(D_CONF, "hlp open");
if (hlp != 0)
return -EBUSY;
hlp_dev = kzalloc(sizeof *hlp_dev, GFP_KERNEL);
if (hlp_dev == NULL) {
err("couldn't kzalloc hlp struct");
return -EIO;
}
init_waitqueue_head(&hlp_dev->wq);
file->private_data = hlp_dev;
hlp = hlp_dev;
return 0;
}
static int hlp_close(struct inode *inode, struct file *file)
{
struct gspca_dev *gspca_dev;
int mode;
PDEBUG(D_CONF, "hlp close");
file->private_data = NULL;
/* stop decoding */
gspca_dev = hlp->gspca_dev;
if (gspca_dev != 0) {
mode = gspca_dev->curr_mode;
gspca_dev->pixfmt = gspca_dev->cam.cam_mode[mode].pixfmt;
}
/* destroy the helper structure */
kfree(hlp);
hlp = 0;
/* try to restart the helper process */
start_hlp();
return 0;
}
static ssize_t hlp_read(struct file *file, char __user *buf,
size_t cnt, loff_t *ppos)
{
struct hlp_dev *hlp_dev = file->private_data;
struct gspca_dev *gspca_dev;
struct gspca_frame *frame;
struct gspca_hlp_read_hd head;
int i, j, len, ret;
PDEBUG(D_FRAM, "hlp read (%d)", cnt);
/* check / wait till a frame is ready */
for (;;) {
gspca_dev = hlp_dev->gspca_dev;
if (gspca_dev != 0 && gspca_dev->streaming) {
i = hlp_dev->fr_d; /* frame to decode */
j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j];
if (frame->v4l2_buf.flags & GSPCA_BUF_FLAG_DECODE)
break;
}
ret = wait_event_interruptible(hlp_dev->wq,
atomic_read(&hlp_dev->nevent) > 0);
if (ret < 0) { /* helper process is killed */
autostart = 0; /* don't restart it */
return ret;
}
}
atomic_dec(&hlp_dev->nevent);
hlp_dev->fr_d = (i + 1) % gspca_dev->nframes;
PDEBUG(D_FRAM, "hlp read q:%d i:%d d:%d o:%d",
gspca_dev->fr_q,
gspca_dev->fr_i,
hlp_dev->fr_d,
gspca_dev->fr_o);
hlp_dev->frame = frame; /* memorize the current frame */
len = frame->v4l2_buf.bytesused;
if (cnt < sizeof head - sizeof head.data + len)
/*fixme: special errno?*/
return -EINVAL;
head.pixfmt_out = gspca_dev->pixfmt;
head.pixfmt_in = hlp_dev->pixfmt;
head.width = gspca_dev->width;
head.height = gspca_dev->height;
copy_to_user(buf, &head, sizeof head);
copy_to_user(buf + sizeof head - sizeof head.data,
frame->data, len);
return sizeof head - sizeof head.data + len;
}
static ssize_t hlp_write(struct file *file,
const char __user *buf,
size_t cnt, loff_t *ppos)
{
struct hlp_dev *hlp_dev = file->private_data;
struct gspca_dev *gspca_dev;
struct gspca_frame *frame;
PDEBUG(D_FRAM, "hlp write (%d)", cnt);
gspca_dev = hlp_dev->gspca_dev;
if (gspca_dev == 0)
return cnt;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
if (!gspca_dev->streaming)
goto out;
frame = hlp_dev->frame;
hlp_dev->frame = 0;
if (frame == 0)
goto out;
if (cnt > frame->v4l2_buf.length) {
PDEBUG(D_ERR|D_FRAM, "bad frame size %d - %d",
cnt, frame->v4l2_buf.length);
cnt = -EINVAL;
goto out;
}
copy_from_user(frame->data, buf, cnt);
frame->v4l2_buf.bytesused = cnt;
frame->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_QUEUED
| GSPCA_BUF_FLAG_DECODE);
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
mutex_unlock(&gspca_dev->queue_lock);
atomic_inc(&gspca_dev->nevent);
wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
PDEBUG(D_FRAM, "hlp write q:%d i:%d d:%d o:%d",
gspca_dev->fr_q,
gspca_dev->fr_i,
hlp_dev->fr_d,
gspca_dev->fr_o);
return cnt;
out:
mutex_unlock(&gspca_dev->queue_lock);
return cnt;
}
static struct file_operations hlp_fops = {
.owner = THIS_MODULE,
.open = hlp_open,
.release = hlp_close,
.read = hlp_read,
.write = hlp_write,
.llseek = no_llseek
};
static struct miscdevice hlp_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "gspca_hlp",
.fops = &hlp_fops,
};
#endif
/*
* VMA operations.
@ -331,10 +114,14 @@ static void fill_frame(struct gspca_dev *gspca_dev,
struct urb *urb)
{
struct gspca_frame *frame;
unsigned char *data; /* address of data in the iso message */
__u8 *data; /* address of data in the iso message */
int i, j, len, st;
cam_pkt_op pkt_scan;
if (urb->status != 0) {
PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
return; /* disconnection ? */
}
pkt_scan = gspca_dev->sd_desc->pkt_scan;
for (i = 0; i < urb->number_of_packets; i++) {
@ -350,20 +137,21 @@ static void fill_frame(struct gspca_dev *gspca_dev,
/* check the packet status and length */
len = urb->iso_frame_desc[i].actual_length;
if (len == 0)
continue;
st = urb->iso_frame_desc[i].status;
if (st) {
PDEBUG(D_ERR, "ISOC data error: [%d] len=%d, status=%d",
PDEBUG(D_ERR,
"ISOC data error: [%d] len=%d, status=%d",
i, len, st);
gspca_dev->last_packet_type = DISCARD_PACKET;
continue;
}
if (len == 0)
continue;
/* let the packet be analyzed by the subdriver */
PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
i, urb->iso_frame_desc[i].offset, len);
data = (unsigned char *) urb->transfer_buffer
data = (__u8 *) urb->transfer_buffer
+ urb->iso_frame_desc[i].offset;
pkt_scan(gspca_dev, frame, data, len);
}
@ -390,7 +178,8 @@ static void fill_frame(struct gspca_dev *gspca_dev,
* buffers are in user space (userptr). The frame detection
* and copy is done by the application.
*/
static void isoc_irq_mmap(struct urb *urb)
static void isoc_irq_mmap(struct urb *urb
)
{
struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
@ -400,7 +189,8 @@ static void isoc_irq_mmap(struct urb *urb)
fill_frame(gspca_dev, urb);
}
static void isoc_irq_user(struct urb *urb)
static void isoc_irq_user(struct urb *urb
)
{
struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
int i;
@ -459,7 +249,7 @@ static void isoc_transfer(struct gspca_dev *gspca_dev)
struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
int packet_type,
struct gspca_frame *frame,
unsigned char *data,
__u8 *data,
int len)
{
int i, j;
@ -503,23 +293,10 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
/* if last packet, wake the application and advance in the queue */
if (packet_type == LAST_PACKET) {
frame->v4l2_buf.bytesused = frame->data_end - frame->data;
#ifndef GSPCA_HLP
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
atomic_inc(&gspca_dev->nevent);
wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
#else /*GSPCA_HLP*/
if (hlp != 0 && hlp->gspca_dev == gspca_dev) {
frame->v4l2_buf.flags |= GSPCA_BUF_FLAG_DECODE;
atomic_inc(&hlp->nevent);
wake_up_interruptible(&hlp->wq);
} else {
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
atomic_inc(&gspca_dev->nevent);
wake_up_interruptible(&gspca_dev->wq); /* new frame */
}
#endif /*GSPCA_HLP*/
i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
gspca_dev->fr_i = i;
PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
@ -581,13 +358,13 @@ static void rvfree(void *mem, unsigned long size)
static __u32 get_v4l2_depth(__u32 pixfmt)
{
switch (pixfmt) {
case V4L2_PIX_FMT_BGR32:
/* case V4L2_PIX_FMT_BGR32:
case V4L2_PIX_FMT_RGB32:
return 32;
return 32; */
case V4L2_PIX_FMT_RGB24: /* 'RGB3' */
case V4L2_PIX_FMT_BGR24:
return 24;
case V4L2_PIX_FMT_RGB565: /* 'RGBP' */
/* case V4L2_PIX_FMT_RGB565: * 'RGBP' */
case V4L2_PIX_FMT_YUYV: /* 'YUYV' packed 4.2.2 */
case V4L2_PIX_FMT_YYUV: /* 'YYUV' */
return 16;
@ -596,6 +373,9 @@ static __u32 get_v4l2_depth(__u32 pixfmt)
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_JPEG:
case V4L2_PIX_FMT_SBGGR8: /* 'BA81' Bayer */
case V4L2_PIX_FMT_SN9C10X: /* 'S910' SN9C10x compression */
case V4L2_PIX_FMT_SPCA501: /* 'S501' YUYV per line */
case V4L2_PIX_FMT_SPCA561: /* 'S561' compressed BGGR bayer */
return 8;
}
PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c",
@ -603,7 +383,7 @@ static __u32 get_v4l2_depth(__u32 pixfmt)
(pixfmt >> 8) & 0xff,
(pixfmt >> 16) & 0xff,
pixfmt >> 24);
return -EINVAL;
return 24;
}
static int gspca_get_buff_size(struct gspca_dev *gspca_dev)
@ -632,7 +412,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
count = GSPCA_MAX_FRAMES;
/* if compressed (JPEG), reduce the buffer size */
if (gspca_is_compressed(gspca_dev->pixfmt))
frsz = (frsz * comp_fac) / 100 + 600; /* plus JPEG header */
frsz = (frsz * comp_fac) / 100 + 600; /* (+ JPEG header sz) */
frsz = PAGE_ALIGN(frsz);
PDEBUG(D_STREAM, "new fr_sz: %d", frsz);
gspca_dev->frsz = frsz;
@ -660,17 +440,6 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
}
}
gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
#ifdef GSPCA_HLP
{
struct hlp_dev *hlp_dev;
hlp_dev = hlp;
if (hlp != 0 && hlp_dev->gspca_dev == gspca_dev) {
hlp_dev->fr_d = 0;
atomic_set(&hlp_dev->nevent, 0);
}
}
#endif /*GSPCA_HLP*/
gspca_dev->last_packet_type = DISCARD_PACKET;
gspca_dev->sequence = 0;
atomic_set(&gspca_dev->nevent, 0);
@ -752,13 +521,14 @@ struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
int i, ret;
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
ep = NULL;
i = gspca_dev->alt; /* previous alt setting */
while (--i > 0) { /* alt 0 is unusable */
ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
if (ep)
break;
}
if (i <= 0) {
if (ep == NULL) {
err("no ISOC endpoint found");
return NULL;
}
@ -796,11 +566,14 @@ static int create_urbs(struct gspca_dev *gspca_dev,
"isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
/*fixme:change for userptr*/
/*fixme:don't submit all URBs when userptr*/
gspca_dev->nurbs = nurbs = DEF_NURBS;
if (gspca_dev->memory == V4L2_MEMORY_MMAP)
if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
usb_complete = isoc_irq_mmap;
else
nurbs = DEF_NURBS;
} else {
usb_complete = isoc_irq_user;
nurbs = USR_NURBS;
}
gspca_dev->nurbs = nurbs;
for (n = 0; n < nurbs; n++) {
urb = usb_alloc_urb(npkt, GFP_KERNEL);
if (!urb) {
@ -904,16 +677,6 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
gspca_dev->streaming = 0;
atomic_set(&gspca_dev->nevent, 0);
#ifdef GSPCA_HLP
{
struct hlp_dev *hlp_dev;
hlp_dev = hlp;
if (hlp_dev != 0
&& hlp_dev->gspca_dev == gspca_dev)
atomic_set(&hlp_dev->nevent, 0);
}
#endif
if (gspca_dev->present) {
gspca_dev->sd_desc->stopN(gspca_dev);
destroy_urbs(gspca_dev);
@ -979,15 +742,11 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *fmtdesc)
{
struct gspca_dev *gspca_dev = priv;
int i;
#ifndef GSPCA_HLP
int j, index;
int i, j, index;
__u32 fmt_tb[8];
#endif
PDEBUG(D_CONF, "enum fmt cap");
#ifndef GSPCA_HLP
/* give an index to each format */
index = 0;
j = 0;
@ -1013,36 +772,6 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
fmtdesc->pixelformat = fmt_tb[index];
if (gspca_is_compressed(fmt_tb[index]))
fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
#else /*GSPCA_HLP*/
/* !! code tied to the decoding functions in decoder.c */
i = gspca_dev->cam.nmodes - 1;
if (fmtdesc->index == 0) { /* (assume one format per subdriver) */
fmtdesc->pixelformat = gspca_dev->cam.cam_mode[i].pixfmt;
if (gspca_is_compressed(fmtdesc->pixelformat))
fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
} else {
if (hlp == 0
|| (hlp->gspca_dev != 0
&& hlp->gspca_dev != gspca_dev))
return -EINVAL;
switch (gspca_dev->cam.cam_mode[i].pixfmt) {
case V4L2_PIX_FMT_JPEG:
if (fmtdesc->index >= sizeof jpeg_to_tb
/ sizeof jpeg_to_tb[0])
return -EINVAL;
fmtdesc->pixelformat = jpeg_to_tb[fmtdesc->index];
break;
case V4L2_PIX_FMT_SBGGR8:
if (fmtdesc->index >= sizeof bayer_to_tb
/ sizeof bayer_to_tb[0])
return -EINVAL;
fmtdesc->pixelformat = bayer_to_tb[fmtdesc->index];
break;
default:
return -EINVAL;
}
}
#endif /*GSPCA_HLP*/
fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
@ -1057,25 +786,12 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
{
struct gspca_dev *gspca_dev = priv;
#ifdef GSPCA_HLP
int i;
/* if the pixel format is not the one of the device and
* if the helper is inactive or busy, restore */
i = gspca_dev->curr_mode;
if (gspca_dev->pixfmt != gspca_dev->cam.cam_mode[i].pixfmt) {
struct hlp_dev *hlp_dev;
hlp_dev = hlp;
if (hlp_dev == 0 || hlp_dev->gspca_dev != gspca_dev)
gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt;
}
#endif /*GSPCA_HLP*/
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
fmt->fmt.pix.width = gspca_dev->width;
fmt->fmt.pix.height = gspca_dev->height;
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
#ifdef GSPCA_DEBUG
#ifdef VIDEO_ADV_DEBUG
if (gspca_debug & D_CONF) {
PDEBUG_MODE("get fmt cap",
fmt->fmt.pix.pixelformat,
@ -1099,13 +815,15 @@ static int try_fmt_cap(struct gspca_dev *gspca_dev,
{
int w, h, mode, mode2, frsz;
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
w = fmt->fmt.pix.width;
h = fmt->fmt.pix.height;
/* (luvcview problem) */
if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
#ifdef GSPCA_DEBUG
#ifdef VIDEO_ADV_DEBUG
if (gspca_debug & D_CONF)
PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
#endif
@ -1121,44 +839,11 @@ static int try_fmt_cap(struct gspca_dev *gspca_dev,
if (mode2 >= 0) {
mode = mode2;
} else {
__u32 pixfmt;
pixfmt = gspca_dev->cam.cam_mode[mode].pixfmt;
#ifndef GSPCA_HLP
/* no chance, return this mode */
fmt->fmt.pix.pixelformat = pixfmt;
#else /*GSPCA_HLP*/
if (hlp != 0
&& (hlp->gspca_dev == 0
|| hlp->gspca_dev == gspca_dev)
/* decoding works for JPEG and Bayer only */
&& (pixfmt == V4L2_PIX_FMT_JPEG
|| pixfmt == V4L2_PIX_FMT_SBGGR8)) {
switch (fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUYV: /* 'YUYV' */
case V4L2_PIX_FMT_BGR24: /* 'BGR3' */
case V4L2_PIX_FMT_RGB24: /* 'RGB3' */
case V4L2_PIX_FMT_YUV420: /* 'YU12' */
case V4L2_PIX_FMT_RGB565: /* 'RGBP' */
break;
default: {
/* return any of the supported fmt's */
__u8 u;
u = get_jiffies_64();
u %= sizeof bayer_to_tb
/ sizeof bayer_to_tb[0] - 1;
fmt->fmt.pix.pixelformat =
bayer_to_tb[u + 1];
break;
}
}
} else {
fmt->fmt.pix.pixelformat = pixfmt;
}
#endif /*GSPCA_HLP*/
#ifdef GSPCA_DEBUG
fmt->fmt.pix.pixelformat =
gspca_dev->cam.cam_mode[mode].pixfmt;
#ifdef VIDEO_ADV_DEBUG
if (gspca_debug & D_CONF) {
PDEBUG_MODE("new format",
fmt->fmt.pix.pixelformat,
@ -1198,7 +883,17 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv;
int ret;
#ifdef GSPCA_DEBUG
#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* if v4l1 got JPEG */
if (fmt->fmt.pix.pixelformat == 0
&& gspca_dev->streaming) {
fmt->fmt.pix.width = gspca_dev->width;
fmt->fmt.pix.height = gspca_dev->height;
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
return 0;
}
#endif
#ifdef VIDEO_ADV_DEBUG
if (gspca_debug & D_CONF) {
PDEBUG_MODE("set fmt cap",
fmt->fmt.pix.pixelformat,
@ -1218,14 +913,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
goto out;
}
#ifndef GSPCA_HLP
if (ret == gspca_dev->curr_mode)
goto out; /* same mode */
#else /*GSPCA_HLP*/
if (ret == gspca_dev->curr_mode
&& gspca_dev->pixfmt == fmt->fmt.pix.pixelformat)
goto out; /* same mode */
#endif /*GSPCA_HLP*/
if (gspca_dev->streaming) {
ret = -EBUSY;
@ -1236,26 +925,6 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
gspca_dev->curr_mode = ret;
#ifdef GSPCA_HLP
/* if frame decoding is required */
if (gspca_dev->pixfmt != gspca_dev->cam.cam_mode[ret].pixfmt) {
struct hlp_dev *hlp_dev;
hlp_dev = hlp;
if (hlp_dev == 0
|| (hlp_dev->gspca_dev != 0
&& hlp_dev->gspca_dev != gspca_dev)) { /* helper busy */
fmt->fmt.pix.pixelformat =
gspca_dev->pixfmt =
gspca_dev->cam.cam_mode[ret].pixfmt;
} else { /* helper active */
hlp_dev->gspca_dev = gspca_dev;
hlp_dev->pixfmt = gspca_dev->cam.cam_mode[ret].pixfmt;
hlp_dev->fr_d = gspca_dev->fr_i;
}
} else if (hlp != 0 && hlp->gspca_dev == gspca_dev)
hlp->gspca_dev = 0;
#endif /*GSPCA_HLP*/
ret = 0;
out:
mutex_unlock(&gspca_dev->queue_lock);
@ -1294,7 +963,7 @@ static int dev_open(struct inode *inode, struct file *file)
}
gspca_dev->users++;
file->private_data = gspca_dev;
#ifdef GSPCA_DEBUG
#ifdef VIDEO_ADV_DEBUG
/* activate the v4l2 debug */
if (gspca_debug & D_V4L2)
gspca_dev->vdev.debug |= 3;
@ -1329,22 +998,6 @@ static int dev_close(struct inode *inode, struct file *file)
frame_free(gspca_dev);
gspca_dev->capt_file = 0;
gspca_dev->memory = GSPCA_MEMORY_NO;
#ifdef GSPCA_HLP
{
struct hlp_dev *hlp_dev;
int mode;
hlp_dev = hlp;
if (hlp_dev != 0
&& hlp_dev->gspca_dev == gspca_dev) {
hlp_dev->gspca_dev = 0;
hlp_dev->frame = 0;
mode = gspca_dev->curr_mode;
gspca_dev->pixfmt =
gspca_dev->cam.cam_mode[mode].pixfmt;
}
}
#endif /*GSPCA_HLP*/
}
file->private_data = NULL;
mutex_unlock(&gspca_dev->queue_lock);
@ -1370,23 +1023,38 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *q_ctrl)
{
struct gspca_dev *gspca_dev = priv;
int i;
u32 id;
PDEBUG(D_CONF, "queryctrl");
id = q_ctrl->id;
if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
id &= V4L2_CTRL_ID_MASK;
id++;
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
memcpy(q_ctrl,
&gspca_dev->sd_desc->ctrls[i].qctrl,
sizeof *q_ctrl);
return 0;
}
}
return -EINVAL;
}
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
if (q_ctrl->id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
memcpy(q_ctrl,
&gspca_dev->sd_desc->ctrls[i].qctrl,
sizeof *q_ctrl);
return 0;
}
}
if (q_ctrl->id >= V4L2_CID_BASE
&& q_ctrl->id <= V4L2_CID_LASTP1) {
if (id >= V4L2_CID_BASE
&& id <= V4L2_CID_LASTP1) {
q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
return 0;
}
@ -1489,13 +1157,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
return -EINVAL;
switch (rb->memory) {
case V4L2_MEMORY_MMAP:
break;
case V4L2_MEMORY_USERPTR:
#ifdef GSPCA_HLP
if (hlp == 0 || hlp->gspca_dev != gspca_dev)
break;
#endif
return -EINVAL;
break;
default:
return -EINVAL;
}
@ -1578,7 +1241,7 @@ static int vidioc_streamon(struct file *file, void *priv,
if (ret < 0)
goto out;
}
#ifdef GSPCA_DEBUG
#ifdef VIDEO_ADV_DEBUG
if (gspca_debug & D_STREAM) {
PDEBUG_MODE("stream on OK",
gspca_dev->pixfmt,
@ -1657,7 +1320,7 @@ static int vidioc_g_parm(struct file *filp, void *priv,
{
struct gspca_dev *gspca_dev = priv;
memset(parm, 0, sizeof parm);
memset(parm, 0, sizeof *parm);
parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm->parm.capture.readbuffers = gspca_dev->nbufread;
return 0;
@ -1677,6 +1340,12 @@ static int vidioc_s_parm(struct file *filp, void *priv,
return 0;
}
static int vidioc_s_std(struct file *filp, void *priv,
v4l2_std_id *parm)
{
return 0;
}
#ifdef CONFIG_VIDEO_V4L1_COMPAT
static int vidiocgmbuf(struct file *file, void *priv,
struct video_mbuf *mbuf)
@ -1686,29 +1355,32 @@ static int vidiocgmbuf(struct file *file, void *priv,
PDEBUG(D_STREAM, "cgmbuf");
if (gspca_dev->nframes == 0) {
struct v4l2_requestbuffers rb;
int ret;
__u32 pixfmt;
short width, height;
/* as the final format is not yet defined, allocate
buffers with the max size */
pixfmt = gspca_dev->pixfmt;
width = gspca_dev->width;
height = gspca_dev->height;
gspca_dev->pixfmt = V4L2_PIX_FMT_BGR32;
gspca_dev->width = 640;
gspca_dev->height = 480;
memset(&rb, 0, sizeof rb);
rb.count = 4;
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
rb.memory = V4L2_MEMORY_MMAP;
ret = vidioc_reqbufs(file, priv, &rb);
gspca_dev->pixfmt = pixfmt;
gspca_dev->width = width;
gspca_dev->height = height;
if (ret != 0)
return ret;
{
struct v4l2_format fmt;
memset(&fmt, 0, sizeof fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
i = gspca_dev->cam.nmodes - 1; /* highest mode */
fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
ret = vidioc_s_fmt_cap(file, priv, &fmt);
if (ret != 0)
return ret;
}
{
struct v4l2_requestbuffers rb;
memset(&rb, 0, sizeof rb);
rb.count = 4;
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
rb.memory = V4L2_MEMORY_MMAP;
ret = vidioc_reqbufs(file, priv, &rb);
if (ret != 0)
return ret;
}
}
mbuf->frames = gspca_dev->nframes;
mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
@ -1951,7 +1623,7 @@ static int vidioc_qbuf(struct file *file, void *priv,
if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
frame->data = frame->data_end =
(unsigned char *) v4l2_buf->m.userptr;
(__u8 *) v4l2_buf->m.userptr;
frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
frame->v4l2_buf.length = v4l2_buf->length;
}
@ -2154,6 +1826,9 @@ static struct file_operations dev_fops = {
.read = dev_read,
.mmap = dev_mmap,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
#endif
.llseek = no_llseek,
.poll = dev_poll,
};
@ -2186,6 +1861,7 @@ static struct video_device gspca_template = {
.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
.vidioc_g_parm = vidioc_g_parm,
.vidioc_s_parm = vidioc_s_parm,
.vidioc_s_std = vidioc_s_std,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
@ -2207,12 +1883,8 @@ int gspca_dev_probe(struct usb_interface *intf,
struct gspca_dev *gspca_dev;
struct usb_device *dev = interface_to_usbdev(intf);
int ret;
__u16 vendor;
__u16 product;
vendor = id->idVendor;
product = id->idProduct;
PDEBUG(D_PROBE, "probing %04x:%04x", vendor, product);
PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
/* we don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1)
@ -2309,35 +1981,24 @@ EXPORT_SYMBOL(gspca_disconnect);
/* -- module insert / remove -- */
static int __init gspca_init(void)
{
#ifdef GSPCA_HLP
int ret;
/* create /dev/gspca_hlp */
ret = misc_register(&hlp_device);
if (ret < 0)
err("misc_register err %d", ret);
start_hlp(); /* try to start the helper process */
#endif
info("main v%s registered", version);
return 0;
}
static void __exit gspca_exit(void)
{
#ifdef GSPCA_HLP
misc_deregister(&hlp_device);
#endif
info("main deregistered");
}
module_init(gspca_init);
module_exit(gspca_exit);
#ifdef VIDEO_ADV_DEBUG
module_param_named(debug, gspca_debug, int, 0644);
MODULE_PARM_DESC(debug,
"Debug (bit) 0x01:error 0x02:probe 0x04:config"
" 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
" 0x0100: v4l2");
#endif
module_param(comp_fac, int, 0644);
MODULE_PARM_DESC(comp_fac,
"Buffer size ratio when compressed in percent");

Просмотреть файл

@ -9,7 +9,26 @@
#include <media/v4l2-common.h>
#include <linux/mutex.h>
#ifdef GSPCA_DEBUG
/* values in 2.6.27 */
#ifndef V4L2_PIX_FMT_SPCA501
#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S', '5', '0', '1')
#endif
#ifndef V4L2_PIX_FMT_SPCA561
#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1')
#endif
/* values in 2.6.26 */
#ifndef V4L2_CID_POWER_LINE_FREQUENCY
#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24)
#endif
#ifndef V4L2_CID_WHITE_BALANCE_TEMPERATURE
#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE + 26)
#endif
#ifndef V4L2_CID_SHARPNESS
#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27)
#endif
#ifdef VIDEO_ADV_DEBUG
/* GSPCA our debug messages */
extern int gspca_debug;
#define PDEBUG(level, fmt, args...) \
@ -47,7 +66,7 @@ extern int gspca_debug;
#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
/* ISOC transfers */
#define MAX_NURBS 32 /* max number of URBs (read & userptr) */
#define MAX_NURBS 16 /* max number of URBs */
#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */
#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */
@ -79,7 +98,7 @@ typedef int (*cam_qmnu_op) (struct gspca_dev *,
struct v4l2_querymenu *);
typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
struct gspca_frame *frame,
unsigned char *data,
__u8 *data,
int len);
struct ctrl {
@ -116,8 +135,8 @@ struct sd_desc {
#define LAST_PACKET 3
struct gspca_frame {
unsigned char *data; /* frame buffer */
unsigned char *data_end; /* end of frame while filling */
__u8 *data; /* frame buffer */
__u8 *data_end; /* end of frame while filling */
int vma_use_count;
struct v4l2_buffer v4l2_buf;
};
@ -135,7 +154,7 @@ struct gspca_dev {
__u8 *frbuf; /* buffer for nframes */
struct gspca_frame frame[GSPCA_MAX_FRAMES];
unsigned int frsz; /* frame size */
__u32 frsz; /* frame size */
char nframes; /* number of frames */
char fr_i; /* frame being filled */
char fr_q; /* next frame to queue */
@ -145,10 +164,10 @@ struct gspca_dev {
__u8 iface; /* USB interface number */
__u8 alt; /* USB alternate setting */
unsigned char curr_mode; /* current camera mode */
__u8 curr_mode; /* current camera mode */
__u32 pixfmt; /* current mode parameters */
short width;
short height;
__u16 width;
__u16 height;
atomic_t nevent; /* number of frames done */
wait_queue_head_t wq; /* wait queue */
@ -176,6 +195,6 @@ void gspca_disconnect(struct usb_interface *intf);
struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
int packet_type,
struct gspca_frame *frame,
unsigned char *data,
__u8 *data,
int len);
#endif /* GSPCAV2_H */

Просмотреть файл

@ -0,0 +1,455 @@
/*
* Mars-Semi MR97311A library
* Copyright (C) 2005 <bradlch@hotmail.com>
*
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define MODULE_NAME "mars"
#include "gspca.h"
#include "jpeg.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
MODULE_LICENSE("GPL");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
char qindex;
};
/* V4L2 controls supported by the driver */
static struct ctrl sd_ctrls[] = {
};
static struct cam_mode vga_mode[] = {
{V4L2_PIX_FMT_JPEG, 320, 240, 2},
{V4L2_PIX_FMT_JPEG, 640, 480, 1},
};
/* MI Register table //elvis */
enum {
REG_HW_MI_0,
REG_HW_MI_1,
REG_HW_MI_2,
REG_HW_MI_3,
REG_HW_MI_4,
REG_HW_MI_5,
REG_HW_MI_6,
REG_HW_MI_7,
REG_HW_MI_9 = 0x09,
REG_HW_MI_B = 0x0B,
REG_HW_MI_C,
REG_HW_MI_D,
REG_HW_MI_1E = 0x1E,
REG_HW_MI_20 = 0x20,
REG_HW_MI_2B = 0x2B,
REG_HW_MI_2C,
REG_HW_MI_2D,
REG_HW_MI_2E,
REG_HW_MI_35 = 0x35,
REG_HW_MI_5F = 0x5f,
REG_HW_MI_60,
REG_HW_MI_61,
REG_HW_MI_62,
REG_HW_MI_63,
REG_HW_MI_64,
REG_HW_MI_F1 = 0xf1,
ATTR_TOTAL_MI_REG = 242
};
static int pcam_reg_write(struct usb_device *dev,
__u16 index, unsigned char *value, int length)
{
int rc;
rc = usb_control_msg(dev,
usb_sndbulkpipe(dev, 4),
0x12,
/* ?? 0xc8 = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_??? !? */
0xc8,
0, /* value */
index, value, length, 500);
PDEBUG(D_USBO, "reg write: 0x%02X , result = 0x%x", index, rc);
if (rc < 0)
PDEBUG(D_ERR, "reg write: error %d", rc);
return rc;
}
static void MISensor_BulkWrite(struct usb_device *dev, unsigned short *pch,
char Address)
{
int result;
unsigned char data[6];
data[0] = 0x1f;
data[1] = 0;
data[2] = Address;
data[3] = *pch >> 8; /* high byte */
data[4] = *pch; /* low byte */
data[5] = 0;
result = usb_control_msg(dev,
usb_sndbulkpipe(dev, 4),
0x12,
/* ?? 0xc8 = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_??? !? */
0xc8,
0, /* value */
Address, /* index */
data, 5, 500);
PDEBUG(D_USBO, "bulk write 0x%02x = 0x%04x", Address, *pch);
if (result < 0)
PDEBUG(D_ERR, "reg write: error %d", result);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
cam = &gspca_dev->cam;
cam->dev_name = (char *) id->driver_info;
cam->epaddr = 0x01;
cam->cam_mode = vga_mode;
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
sd->qindex = 1; /* set the quantization table */
return 0;
}
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
return 0;
}
static void sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
int err_code;
__u8 data[12];
__u16 MI_buf[242];
int h_size, v_size;
int intpipe;
/* struct usb_device *dev = pcam->dev; */
memset(data, 0, sizeof data);
memset(MI_buf, 0, sizeof MI_buf);
PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
if (usb_set_interface(dev, gspca_dev->iface, 8) < 0) {
PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
return;
}
data[0] = 0x01; /* address */
data[1] = 0x01;
err_code = pcam_reg_write(dev, data[0], data, 0x02);
if (err_code < 0)
return;
/*
Initialize the MR97113 chip register
*/
data[0] = 0x00; /* address */
data[1] = 0x0c | 0x01; /* reg 0 */
data[2] = 0x01; /* reg 1 */
h_size = gspca_dev->width;
v_size = gspca_dev->height;
data[3] = h_size / 8; /* h_size , reg 2 */
data[4] = v_size / 8; /* v_size , reg 3 */
data[5] = 0x30; /* reg 4, MI, PAS5101 :
* 0x30 for 24mhz , 0x28 for 12mhz */
data[6] = 4; /* reg 5, H start */
data[7] = 0xc0; /* reg 6, gamma 1.5 */
data[8] = 3; /* reg 7, V start */
/* if(h_size == 320 ) */
/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
/* else */
data[9] = 0x52; /* reg 8, 24MHz, no scale down */
data[10] = 0x5d; /* reg 9, I2C device address
* [for PAS5101 (0x40)] [for MI (0x5d)] */
err_code = pcam_reg_write(dev, data[0], data, 0x0b);
if (err_code < 0)
return;
data[0] = 0x23; /* address */
data[1] = 0x09; /* reg 35, append frame header */
err_code = pcam_reg_write(dev, data[0], data, 0x02);
if (err_code < 0) {
PDEBUG(D_ERR, "Register write failed");
return;
}
data[0] = 0x3C; /* address */
/* if (pcam->width == 1280) */
/* data[1] = 200; * reg 60, pc-cam frame size
* (unit: 4KB) 800KB */
/* else */
data[1] = 50; /* 50 reg 60, pc-cam frame size
* (unit: 4KB) 200KB */
err_code = pcam_reg_write(dev, data[0], data, 0x02);
if (err_code < 0)
return;
if (0) { /* fixed dark-gain */
data[1] = 0; /* reg 94, Y Gain (1.75) */
data[2] = 0; /* reg 95, UV Gain (1.75) */
data[3] = 0x3f; /* reg 96, Y Gain/UV Gain/disable auto dark-gain */
data[4] = 0; /* reg 97, set fixed dark level */
data[5] = 0; /* reg 98, don't care */
} else { /* auto dark-gain */
data[1] = 0; /* reg 94, Y Gain (auto) */
data[2] = 0; /* reg 95, UV Gain (1.75) */
data[3] = 0x78; /* reg 96, Y Gain/UV Gain/disable auto dark-gain */
switch (gspca_dev->width) {
/* case 1280: */
/* data[4] = 154;
* reg 97, %3 shadow point (unit: 256 pixel) */
/* data[5] = 51;
* reg 98, %1 highlight point
* (uint: 256 pixel) */
/* break; */
default:
/* case 640: */
data[4] = 36; /* reg 97, %3 shadow point
* (unit: 256 pixel) */
data[5] = 12; /* reg 98, %1 highlight point
* (uint: 256 pixel) */
break;
case 320:
data[4] = 9; /* reg 97, %3 shadow point
* (unit: 256 pixel) */
data[5] = 3; /* reg 98, %1 highlight point
* (uint: 256 pixel) */
break;
}
}
/* auto dark-gain */
data[0] = 0x5e; /* address */
err_code = pcam_reg_write(dev, data[0], data, 0x06);
if (err_code < 0)
return;
data[0] = 0x67;
data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */
err_code = pcam_reg_write(dev, data[0], data, 0x02);
if (err_code < 0)
return;
/*
* initialize the value of MI sensor...
*/
MI_buf[REG_HW_MI_1] = 0x000a;
MI_buf[REG_HW_MI_2] = 0x000c;
MI_buf[REG_HW_MI_3] = 0x0405;
MI_buf[REG_HW_MI_4] = 0x0507;
/* mi_Attr_Reg_[REG_HW_MI_5] = 0x01ff;//13 */
MI_buf[REG_HW_MI_5] = 0x0013; /* 13 */
MI_buf[REG_HW_MI_6] = 0x001f; /* vertical blanking */
/* mi_Attr_Reg_[REG_HW_MI_6] = 0x0400; // vertical blanking */
MI_buf[REG_HW_MI_7] = 0x0002;
/* mi_Attr_Reg_[REG_HW_MI_9] = 0x015f; */
/* mi_Attr_Reg_[REG_HW_MI_9] = 0x030f; */
MI_buf[REG_HW_MI_9] = 0x0374;
MI_buf[REG_HW_MI_B] = 0x0000;
MI_buf[REG_HW_MI_C] = 0x0000;
MI_buf[REG_HW_MI_D] = 0x0000;
MI_buf[REG_HW_MI_1E] = 0x8000;
/* mi_Attr_Reg_[REG_HW_MI_20] = 0x1104; */
MI_buf[REG_HW_MI_20] = 0x1104; /* 0x111c; */
MI_buf[REG_HW_MI_2B] = 0x0008;
/* mi_Attr_Reg_[REG_HW_MI_2C] = 0x000f; */
MI_buf[REG_HW_MI_2C] = 0x001f; /* lita suggest */
MI_buf[REG_HW_MI_2D] = 0x0008;
MI_buf[REG_HW_MI_2E] = 0x0008;
MI_buf[REG_HW_MI_35] = 0x0051;
MI_buf[REG_HW_MI_5F] = 0x0904; /* fail to write */
MI_buf[REG_HW_MI_60] = 0x0000;
MI_buf[REG_HW_MI_61] = 0x0000;
MI_buf[REG_HW_MI_62] = 0x0498;
MI_buf[REG_HW_MI_63] = 0x0000;
MI_buf[REG_HW_MI_64] = 0x0000;
MI_buf[REG_HW_MI_F1] = 0x0001;
/* changing while setting up the different value of dx/dy */
if (gspca_dev->width != 1280) {
MI_buf[0x01] = 0x010a;
MI_buf[0x02] = 0x014c;
MI_buf[0x03] = 0x01e5;
MI_buf[0x04] = 0x0287;
}
MI_buf[0x20] = 0x1104;
MISensor_BulkWrite(dev, MI_buf + 1, 1);
MISensor_BulkWrite(dev, MI_buf + 2, 2);
MISensor_BulkWrite(dev, MI_buf + 3, 3);
MISensor_BulkWrite(dev, MI_buf + 4, 4);
MISensor_BulkWrite(dev, MI_buf + 5, 5);
MISensor_BulkWrite(dev, MI_buf + 6, 6);
MISensor_BulkWrite(dev, MI_buf + 7, 7);
MISensor_BulkWrite(dev, MI_buf + 9, 9);
MISensor_BulkWrite(dev, MI_buf + 0x0b, 0x0b);
MISensor_BulkWrite(dev, MI_buf + 0x0c, 0x0c);
MISensor_BulkWrite(dev, MI_buf + 0x0d, 0x0d);
MISensor_BulkWrite(dev, MI_buf + 0x1e, 0x1e);
MISensor_BulkWrite(dev, MI_buf + 0x20, 0x20);
MISensor_BulkWrite(dev, MI_buf + 0x2b, 0x2b);
MISensor_BulkWrite(dev, MI_buf + 0x2c, 0x2c);
MISensor_BulkWrite(dev, MI_buf + 0x2d, 0x2d);
MISensor_BulkWrite(dev, MI_buf + 0x2e, 0x2e);
MISensor_BulkWrite(dev, MI_buf + 0x35, 0x35);
MISensor_BulkWrite(dev, MI_buf + 0x5f, 0x5f);
MISensor_BulkWrite(dev, MI_buf + 0x60, 0x60);
MISensor_BulkWrite(dev, MI_buf + 0x61, 0x61);
MISensor_BulkWrite(dev, MI_buf + 0x62, 0x62);
MISensor_BulkWrite(dev, MI_buf + 0x63, 0x63);
MISensor_BulkWrite(dev, MI_buf + 0x64, 0x64);
MISensor_BulkWrite(dev, MI_buf + 0xf1, 0xf1);
intpipe = usb_sndintpipe(dev, 0);
err_code = usb_clear_halt(dev, intpipe);
data[0] = 0x00;
data[1] = 0x4d; /* ISOC transfering enable... */
pcam_reg_write(dev, data[0], data, 0x02);
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
int result;
__u8 data[2];
data[0] = 1;
data[1] = 0;
result = pcam_reg_write(gspca_dev->dev, data[0], data, 2);
if (result < 0)
PDEBUG(D_ERR, "Camera Stop failed");
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
}
static void sd_close(struct gspca_dev *gspca_dev)
{
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
unsigned char *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
int p;
if (len < 6) {
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
return;
}
for (p = 0; p < len - 6; p++) {
if (data[0 + p] == 0xff
&& data[1 + p] == 0xff
&& data[2 + p] == 0x00
&& data[3 + p] == 0xff
&& data[4 + p] == 0x96) {
if (data[5 + p] == 0x64
|| data[5 + p] == 0x65
|| data[5 + p] == 0x66
|| data[5 + p] == 0x67) {
PDEBUG(D_PACK, "sof offset: %d leng: %d",
p, len);
frame = gspca_frame_add(gspca_dev, LAST_PACKET,
frame, data, 0);
/* put the JPEG header */
jpeg_put_header(gspca_dev, frame,
sd->qindex, 0x21);
data += 16;
len -= 16;
break;
}
}
}
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.open = sd_open,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
#define DVNM(name) .driver_info = (kernel_ulong_t) name
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x050f), DVNM("Mars-Semi Pc-Camera")},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
};
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
if (usb_register(&sd_driver) < 0)
return -1;
PDEBUG(D_PROBE, "v%s registered", version);
return 0;
}
static void __exit sd_mod_exit(void)
{
usb_deregister(&sd_driver);
PDEBUG(D_PROBE, "deregistered");
}
module_init(sd_mod_init);
module_exit(sd_mod_exit);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -27,8 +27,8 @@
#include "gspca.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 15)
static const char version[] = "0.2.15";
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
MODULE_DESCRIPTION("Pixart PAC207");
@ -297,7 +297,6 @@ static int sd_open(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = 1;
return 0;
}
@ -338,7 +337,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
udelay(1000); /* taken from gspca */
msleep(10);
pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
sd->sof_read = 0;
@ -743,8 +742,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
PDEBUG(D_STREAM, "Incomplete frame");
}
pac207_decode_frame_init(gspca_dev);
gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL,
0);
gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
len -= sof - data;
data = sof;
}

Просмотреть файл

@ -0,0 +1,754 @@
/*
* Pixart PAC7311 library
* Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
*
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define MODULE_NAME "pac7311"
#include "gspca.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
MODULE_DESCRIPTION("Pixart PAC7311");
MODULE_LICENSE("GPL");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
int avg_lum;
unsigned char brightness;
#define BRIGHTNESS_MAX 0x20
unsigned char contrast;
unsigned char colors;
unsigned char autogain;
char ffseq;
signed char ag_cnt;
#define AG_CNT_START 13
};
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
.maximum = BRIGHTNESS_MAX,
.step = 1,
.default_value = 0x10,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
#define SD_CONTRAST 1
{
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 127,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
},
#define SD_COLOR 2
{
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Color",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 127,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
#define SD_AUTOGAIN 3
{
{
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Auto Gain",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = 1,
},
.set = sd_setautogain,
.get = sd_getautogain,
},
};
static struct cam_mode vga_mode[] = {
{V4L2_PIX_FMT_JPEG, 160, 120, 2},
{V4L2_PIX_FMT_JPEG, 320, 240, 1},
{V4L2_PIX_FMT_JPEG, 640, 480, 0},
};
#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
const unsigned char pac7311_jpeg_header[] = {
0xff, 0xd8,
0xff, 0xe0, 0x00, 0x03, 0x20,
0xff, 0xc0, 0x00, 0x11, 0x08,
0x01, 0xe0, /* 12: height */
0x02, 0x80, /* 14: width */
0x03, /* 16 */
0x01, 0x21, 0x00,
0x02, 0x11, 0x01,
0x03, 0x11, 0x01,
0xff, 0xdb, 0x00, 0x84,
0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
0x11, 0x00, 0x3f, 0x00
};
static void reg_w(struct usb_device *dev,
__u16 req,
__u16 value,
__u16 index,
__u8 *buffer, __u16 length)
{
usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, buffer, length,
500);
}
static void pac7311_reg_read(struct usb_device *dev, __u16 index,
__u8 *buffer)
{
usb_control_msg(dev,
usb_rcvctrlpipe(dev, 0),
0, /* request */
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, /* value */
index, buffer, 1,
500);
}
static void pac7311_reg_write(struct usb_device *dev,
__u16 index,
__u8 value)
{
__u8 buf;
buf = value;
reg_w(dev, 0x00, value, index, &buf, 1);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
struct cam *cam;
PDEBUG(D_CONF, "Find Sensor PAC7311");
pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
pac7311_reg_write(dev, 0xff, 0x04);
pac7311_reg_write(dev, 0x27, 0x80);
pac7311_reg_write(dev, 0x28, 0xca);
pac7311_reg_write(dev, 0x29, 0x53);
pac7311_reg_write(dev, 0x2a, 0x0e);
pac7311_reg_write(dev, 0xff, 0x01);
pac7311_reg_write(dev, 0x3e, 0x20);
cam = &gspca_dev->cam;
cam->dev_name = (char *) id->driver_info;
cam->epaddr = 0x05;
cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode);
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
return 0;
}
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int brightness;
/*jfm: inverted?*/
brightness = BRIGHTNESS_MAX - sd->brightness;
pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
/* pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */
pac7311_reg_write(gspca_dev->dev, 0x0f, brightness);
/* load registers to sensor (Bit 0, auto clear) */
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
}
static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast);
/* load registers to sensor (Bit 0, auto clear) */
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
}
static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors);
/* load registers to sensor (Bit 0, auto clear) */
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
}
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
pac7311_reg_write(gspca_dev->dev, 0x78, 0x00); /* Turn on LED */
return 0;
}
static void sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
struct sd *sd = (struct sd *) gspca_dev;
pac7311_reg_write(dev, 0xff, 0x01);
reg_w(dev, 0x01, 0, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
reg_w(dev, 0x01, 0, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
reg_w(dev, 0x01, 0, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
reg_w(dev, 0x01, 0, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
reg_w(dev, 0x01, 0, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
reg_w(dev, 0x01, 0, 0x002a, "\x00\x00\x00", 3);
reg_w(dev, 0x01, 0, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
reg_w(dev, 0x01, 0, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
reg_w(dev, 0x01, 0, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
reg_w(dev, 0x01, 0, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
reg_w(dev, 0x01, 0, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
reg_w(dev, 0x01, 0, 0x0066, "\xd0\xff", 2);
reg_w(dev, 0x01, 0, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
reg_w(dev, 0x01, 0, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
reg_w(dev, 0x01, 0, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
reg_w(dev, 0x01, 0, 0x008f, "\x18\x20", 2);
reg_w(dev, 0x01, 0, 0x0096, "\x01\x08\x04", 3);
reg_w(dev, 0x01, 0, 0x00a0, "\x44\x44\x44\x04", 4);
reg_w(dev, 0x01, 0, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
reg_w(dev, 0x01, 0, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
pac7311_reg_write(dev, 0xff, 0x04);
pac7311_reg_write(dev, 0x02, 0x04);
pac7311_reg_write(dev, 0x03, 0x54);
pac7311_reg_write(dev, 0x04, 0x07);
pac7311_reg_write(dev, 0x05, 0x2b);
pac7311_reg_write(dev, 0x06, 0x09);
pac7311_reg_write(dev, 0x07, 0x0f);
pac7311_reg_write(dev, 0x08, 0x09);
pac7311_reg_write(dev, 0x09, 0x00);
pac7311_reg_write(dev, 0x0c, 0x07);
pac7311_reg_write(dev, 0x0d, 0x00);
pac7311_reg_write(dev, 0x0e, 0x00);
pac7311_reg_write(dev, 0x0f, 0x62);
pac7311_reg_write(dev, 0x10, 0x08);
pac7311_reg_write(dev, 0x12, 0x07);
pac7311_reg_write(dev, 0x13, 0x00);
pac7311_reg_write(dev, 0x14, 0x00);
pac7311_reg_write(dev, 0x15, 0x00);
pac7311_reg_write(dev, 0x16, 0x00);
pac7311_reg_write(dev, 0x17, 0x00);
pac7311_reg_write(dev, 0x18, 0x00);
pac7311_reg_write(dev, 0x19, 0x00);
pac7311_reg_write(dev, 0x1a, 0x00);
pac7311_reg_write(dev, 0x1b, 0x03);
pac7311_reg_write(dev, 0x1c, 0xa0);
pac7311_reg_write(dev, 0x1d, 0x01);
pac7311_reg_write(dev, 0x1e, 0xf4);
pac7311_reg_write(dev, 0x21, 0x00);
pac7311_reg_write(dev, 0x22, 0x08);
pac7311_reg_write(dev, 0x24, 0x03);
pac7311_reg_write(dev, 0x26, 0x00);
pac7311_reg_write(dev, 0x27, 0x01);
pac7311_reg_write(dev, 0x28, 0xca);
pac7311_reg_write(dev, 0x29, 0x10);
pac7311_reg_write(dev, 0x2a, 0x06);
pac7311_reg_write(dev, 0x2b, 0x78);
pac7311_reg_write(dev, 0x2c, 0x00);
pac7311_reg_write(dev, 0x2d, 0x00);
pac7311_reg_write(dev, 0x2e, 0x00);
pac7311_reg_write(dev, 0x2f, 0x00);
pac7311_reg_write(dev, 0x30, 0x23);
pac7311_reg_write(dev, 0x31, 0x28);
pac7311_reg_write(dev, 0x32, 0x04);
pac7311_reg_write(dev, 0x33, 0x11);
pac7311_reg_write(dev, 0x34, 0x00);
pac7311_reg_write(dev, 0x35, 0x00);
pac7311_reg_write(dev, 0x11, 0x01);
setcontrast(gspca_dev);
setbrightness(gspca_dev);
setcolors(gspca_dev);
/* set correct resolution */
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
case 2: /* 160x120 */
pac7311_reg_write(dev, 0xff, 0x04);
pac7311_reg_write(dev, 0x02, 0x03);
pac7311_reg_write(dev, 0xff, 0x01);
pac7311_reg_write(dev, 0x08, 0x09);
pac7311_reg_write(dev, 0x17, 0x20);
pac7311_reg_write(dev, 0x1b, 0x00);
/* pac7311_reg_write(dev, 0x80, 0x69); */
pac7311_reg_write(dev, 0x87, 0x10);
break;
case 1: /* 320x240 */
pac7311_reg_write(dev, 0xff, 0x04);
pac7311_reg_write(dev, 0x02, 0x03);
pac7311_reg_write(dev, 0xff, 0x01);
pac7311_reg_write(dev, 0x08, 0x09);
pac7311_reg_write(dev, 0x17, 0x30);
/* pac7311_reg_write(dev, 0x80, 0x3f); */
pac7311_reg_write(dev, 0x87, 0x11);
break;
case 0: /* 640x480 */
pac7311_reg_write(dev, 0xff, 0x04);
pac7311_reg_write(dev, 0x02, 0x03);
pac7311_reg_write(dev, 0xff, 0x01);
pac7311_reg_write(dev, 0x08, 0x08);
pac7311_reg_write(dev, 0x17, 0x00);
/* pac7311_reg_write(dev, 0x80, 0x1c); */
pac7311_reg_write(dev, 0x87, 0x12);
break;
}
/* start stream */
pac7311_reg_write(dev, 0xff, 0x01);
pac7311_reg_write(dev, 0x78, 0x04);
pac7311_reg_write(dev, 0x78, 0x05);
if (sd->autogain) {
sd->ag_cnt = AG_CNT_START;
sd->avg_lum = 0;
} else {
sd->ag_cnt = -1;
}
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
pac7311_reg_write(dev, 0xff, 0x04);
pac7311_reg_write(dev, 0x27, 0x80);
pac7311_reg_write(dev, 0x28, 0xca);
pac7311_reg_write(dev, 0x29, 0x53);
pac7311_reg_write(dev, 0x2a, 0x0e);
pac7311_reg_write(dev, 0xff, 0x01);
pac7311_reg_write(dev, 0x3e, 0x20);
pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
}
/* this function is called at close time */
static void sd_close(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
pac7311_reg_write(dev, 0xff, 0x04);
pac7311_reg_write(dev, 0x27, 0x80);
pac7311_reg_write(dev, 0x28, 0xca);
pac7311_reg_write(dev, 0x29, 0x53);
pac7311_reg_write(dev, 0x2a, 0x0e);
pac7311_reg_write(dev, 0xff, 0x01);
pac7311_reg_write(dev, 0x3e, 0x20);
pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
}
static void setautogain(struct gspca_dev *gspca_dev, int luma)
{
int luma_mean = 128;
int luma_delta = 20;
__u8 spring = 5;
__u8 Pxclk;
int Gbright;
pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk);
Gbright = Pxclk;
PDEBUG(D_FRAM, "luma mean %d", luma);
if (luma < luma_mean - luma_delta ||
luma > luma_mean + luma_delta) {
Gbright += (luma_mean - luma) >> spring;
if (Gbright > 0x1a)
Gbright = 0x1a;
else if (Gbright < 4)
Gbright = 4;
PDEBUG(D_FRAM, "gbright %d", Gbright);
pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright);
/* load registers to sensor (Bit 0, auto clear) */
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
}
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
unsigned char *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
unsigned char tmpbuf[4];
int i, p, ffseq;
/* if (len < 5) { */
if (len < 6) {
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
return;
}
ffseq = sd->ffseq;
for (p = 0; p < len - 6; p++) {
if ((data[0 + p] == 0xff)
&& (data[1 + p] == 0xff)
&& (data[2 + p] == 0x00)
&& (data[3 + p] == 0xff)
&& (data[4 + p] == 0x96)) {
/* start of frame */
if (sd->ag_cnt >= 0 && p > 28) {
sd->avg_lum += data[p - 23];
if (--sd->ag_cnt < 0) {
sd->ag_cnt = AG_CNT_START;
setautogain(gspca_dev,
sd->avg_lum / AG_CNT_START);
sd->avg_lum = 0;
}
}
/* copy the end of data to the current frame */
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
data, p);
/* put the JPEG header in the new frame */
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
(unsigned char *) pac7311_jpeg_header,
12);
tmpbuf[0] = gspca_dev->height >> 8;
tmpbuf[1] = gspca_dev->height & 0xff;
tmpbuf[2] = gspca_dev->width >> 8;
tmpbuf[3] = gspca_dev->width & 0xff;
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
tmpbuf, 4);
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
(unsigned char *) &pac7311_jpeg_header[16],
PAC7311_JPEG_HEADER_SIZE - 16);
data += p + 7;
len -= p + 7;
ffseq = 0;
break;
}
}
/* remove the 'ff ff ff xx' sequences */
switch (ffseq) {
case 3:
data += 1;
len -= 1;
break;
case 2:
if (data[0] == 0xff) {
data += 2;
len -= 2;
frame->data_end -= 2;
}
break;
case 1:
if (data[0] == 0xff
&& data[1] == 0xff) {
data += 3;
len -= 3;
frame->data_end -= 1;
}
break;
}
for (i = 0; i < len - 4; i++) {
if (data[i] == 0xff
&& data[i + 1] == 0xff
&& data[i + 2] == 0xff) {
memmove(&data[i], &data[i + 4], len - i - 4);
len -= 4;
}
}
ffseq = 0;
if (data[len - 4] == 0xff) {
if (data[len - 3] == 0xff
&& data[len - 2] == 0xff) {
len -= 4;
}
} else if (data[len - 3] == 0xff) {
if (data[len - 2] == 0xff
&& data[len - 1] == 0xff)
ffseq = 3;
} else if (data[len - 2] == 0xff) {
if (data[len - 1] == 0xff)
ffseq = 2;
} else if (data[len - 1] == 0xff)
ffseq = 1;
sd->ffseq = ffseq;
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
static void getbrightness(struct gspca_dev *gspca_dev)
{
/* __u8 brightness = 0;
pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness);
spca50x->brightness = brightness;
return spca50x->brightness; */
/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming)
setbrightness(gspca_dev);
return 0;
}
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
if (gspca_dev->streaming)
setcontrast(gspca_dev);
return 0;
}
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
/* getcontrast(gspca_dev); */
*val = sd->contrast;
return 0;
}
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->colors = val;
if (gspca_dev->streaming)
setcolors(gspca_dev);
return 0;
}
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
/* getcolors(gspca_dev); */
*val = sd->colors;
return 0;
}
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
if (val) {
sd->ag_cnt = AG_CNT_START;
sd->avg_lum = 0;
} else {
sd->ag_cnt = -1;
}
return 0;
}
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->autogain;
return 0;
}
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.open = sd_open,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
#define DVNM(name) .driver_info = (kernel_ulong_t) name
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
{USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
{USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
{USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
{USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350")},
{USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
{USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
};
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
if (usb_register(&sd_driver) < 0)
return -1;
PDEBUG(D_PROBE, "v%s registered", version);
return 0;
}
static void __exit sd_mod_exit(void)
{
usb_deregister(&sd_driver);
PDEBUG(D_PROBE, "deregistered");
}
module_init(sd_mod_init);
module_exit(sd_mod_exit);

Просмотреть файл

@ -0,0 +1,879 @@
/*
* sonix sn9c102 (bayer) library
* Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
* Add Pas106 Stefano Mozzi (C) 2004
*
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define MODULE_NAME "sonixb"
#include "gspca.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
MODULE_LICENSE("GPL");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
unsigned char brightness;
unsigned char contrast;
char sensor; /* Type of image sensor chip */
#define SENSOR_HV7131R 0
#define SENSOR_OV6650 1
#define SENSOR_OV7630 2
#define SENSOR_OV7630_3 3
#define SENSOR_PAS106 4
#define SENSOR_PAS202 5
#define SENSOR_TAS5110 6
#define SENSOR_TAS5130CXX 7
};
#define COMP2 0x8f
#define COMP 0xc7 /* 0x87 //0x07 */
#define COMP1 0xc9 /* 0x89 //0x09 */
#define MCK_INIT 0x63
#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
#define SYS_CLK 0x04
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 127,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
#define SD_CONTRAST 1
{
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 127,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
},
};
/* fixme: should have V4L2_PIX_FMT_SN9C10X */
static struct cam_mode vga_mode[] = {
{V4L2_PIX_FMT_SN9C10X, 160, 120, 2},
{V4L2_PIX_FMT_SN9C10X, 320, 240, 1},
{V4L2_PIX_FMT_SN9C10X, 640, 480, 0},
};
static struct cam_mode sif_mode[] = {
{V4L2_PIX_FMT_SN9C10X, 176, 144, 1},
{V4L2_PIX_FMT_SN9C10X, 352, 288, 0},
};
static const __u8 probe_ov7630[] = {0x08, 0x44};
static const __u8 initHv7131[] = {
0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
0x28, 0x1e, 0x60, 0x8a, 0x20,
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
};
static const __u8 hv7131_sensor_init[][8] = {
{0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
{0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
{0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
{0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
{0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
};
static const __u8 initOv6650[] = {
0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
};
static const __u8 ov6650_sensor_init[][8] =
{
/* Bright, contrast, etc are set througth SCBB interface.
* AVCAP on win2 do not send any data on this controls. */
/* Anyway, some registers appears to alter bright and constrat */
{0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
{0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
{0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
* THIS SET GREEN SCREEN
* (pixels could be innverted in decode kind of "brg",
* but blue wont be there. Avoid this data ... */
{0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
{0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
{0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
{0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
{0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
{0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
{0xa0, 0x60, 0x10, 0x5d, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x2d, 0x0a, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x33, 0x40, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x11, 0xc0, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x00, 0x16, 0x99, 0x04, 0x94, 0x15}, /* bright / Lumino */
{0xa0, 0x60, 0x2b, 0xab, 0x99, 0x04, 0x94, 0x15},
/* ?flicker o brillo */
{0xa0, 0x60, 0x2d, 0x2a, 0x99, 0x04, 0x94, 0x15},
{0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x33, 0x00, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
{0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
/* Low Light (Enabled: 0x32 0x1 | Disabled: 0x32 0x00) */
{0xa0, 0x60, 0x33, 0x29, 0x99, 0x04, 0x94, 0x16},
/* Low Ligth (Enabled: 0x33 0x13 | Disabled: 0x33 0x29) */
/* {0xa0, 0x60, 0x11, 0xc1, 0x99, 0x04, 0x94, 0x16}, */
{0xa0, 0x60, 0x00, 0x17, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
{0xa0, 0x60, 0x00, 0x18, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
};
static const __u8 initOv7630[] = {
0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
0x28, 0x1e, /* H & V sizes r15 .. r16 */
0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
};
static const __u8 initOv7630_3[] = {
0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
0x28, 0x1e, /* H & V sizes r15 .. r16 */
0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
};
static const __u8 ov7630_sensor_init_com[][8] = {
{0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
{0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
{0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10}, /* jfm */
{0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
{0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
{0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
{0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
{0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
{0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
{0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
/* {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, jfm */
{0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, /* jfm */
{0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
{0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
{0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
{0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
{0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
{0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
};
static const __u8 ov7630_sensor_init[][8] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
{0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
{0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
{0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
{0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
};
static const __u8 ov7630_sensor_init_3[][8] = {
{0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
{0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16},
{0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16},
{0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
/* {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
* a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
/* {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d}, * from win */
{0xb0, 0x21, 0x2a, 0xa0, 0x1c, 0x06, 0xf6, 0x1d},
};
static const __u8 initPas106[] = {
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
0x16, 0x12, 0x28, COMP1, MCK_INIT1,
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
};
/* compression 0x86 mckinit1 0x2b */
static const __u8 pas106_data[][2] = {
{0x02, 0x04}, /* Pixel Clock Divider 6 */
{0x03, 0x13}, /* Frame Time MSB */
/* {0x03, 0x12}, * Frame Time MSB */
{0x04, 0x06}, /* Frame Time LSB */
/* {0x04, 0x05}, * Frame Time LSB */
{0x05, 0x65}, /* Shutter Time Line Offset */
/* {0x05, 0x6d}, * Shutter Time Line Offset */
/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
{0x06, 0xcd}, /* Shutter Time Pixel Offset */
{0x07, 0xc1}, /* Black Level Subtract Sign */
/* {0x07, 0x00}, * Black Level Subtract Sign */
{0x08, 0x06}, /* Black Level Subtract Level */
{0x08, 0x06}, /* Black Level Subtract Level */
/* {0x08, 0x01}, * Black Level Subtract Level */
{0x09, 0x05}, /* Color Gain B Pixel 5 a */
{0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
{0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
{0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
{0x0d, 0x00}, /* Color GainH Pixel */
{0x0e, 0x0e}, /* Global Gain */
{0x0f, 0x00}, /* Contrast */
{0x10, 0x06}, /* H&V synchro polarity */
{0x11, 0x06}, /* ?default */
{0x12, 0x06}, /* DAC scale */
{0x14, 0x02}, /* ?default */
{0x13, 0x01}, /* Validate Settings */
};
static const __u8 initPas202[] = {
0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
0x28, 0x1e, 0x28, 0x89, 0x30,
0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
};
static const __u8 pas202_sensor_init[][8] = {
{0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
{0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
{0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
{0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
{0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
{0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
{0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
{0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
{0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
{0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
{0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
{0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
{0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
{0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
{0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
{0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
{0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
{0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
{0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
{0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
};
static const __u8 initTas5110[] = {
0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
0x16, 0x12, 0x60, 0x86, 0x2b,
0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
};
static const __u8 tas5110_sensor_init[][8] = {
{0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
{0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
{0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
};
static const __u8 initTas5130[] = {
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
0x28, 0x1e, 0x60, COMP, MCK_INIT,
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
};
static const __u8 tas5130_sensor_init[][8] = {
/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
* shutter 0x47 short exposure? */
{0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
/* shutter 0x01 long exposure */
{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
};
static void reg_r(struct usb_device *dev,
__u16 value, __u8 *buffer)
{
usb_control_msg(dev,
usb_rcvctrlpipe(dev, 0),
0, /* request */
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value,
0, /* index */
buffer, 1,
500);
}
static void reg_w(struct usb_device *dev,
__u16 value,
const __u8 *buffer,
__u16 len)
{
usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
0x08, /* request */
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value,
0, /* index */
(__u8 *) buffer, len,
500);
}
static int i2c_w(struct usb_device *dev, const __u8 *buffer)
{
int retry = 60;
__u8 ByteReceive;
/* is i2c ready */
reg_w(dev, 0x08, buffer, 8);
while (retry--) {
msleep(10);
reg_r(dev, 0x08, &ByteReceive);
if (ByteReceive == 4)
return 0;
}
return -1;
}
static void i2c_w_vector(struct usb_device *dev,
const __u8 buffer[][8], int len)
{
for (;;) {
reg_w(dev, 0x08, *buffer, 8);
len -= 8;
if (len <= 0)
break;
buffer++;
}
}
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u8 value;
switch (sd->sensor) {
case SENSOR_OV6650: {
__u8 i2cOV6650[] =
{0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
i2cOV6650[3] = sd->brightness;
if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
goto err;
break;
}
case SENSOR_OV7630: {
__u8 i2cOV[] =
{0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
/* change reg 0x06 */
i2cOV[3] = sd->brightness;
if (i2c_w(gspca_dev->dev, i2cOV) < 0)
goto err;
break;
}
case SENSOR_PAS106: {
__u8 i2c1[] =
{0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
i2c1[3] = sd->brightness >> 3;
i2c1[2] = 0x0e;
if (i2c_w(gspca_dev->dev, i2c1) < 0)
goto err;
i2c1[3] = 0x01;
i2c1[2] = 0x13;
if (i2c_w(gspca_dev->dev, i2c1) < 0)
goto err;
break;
}
case SENSOR_PAS202: {
/* __u8 i2cpexpo1[] =
{0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
__u8 i2cpexpo[] =
{0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
__u8 i2cp202[] =
{0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
static __u8 i2cpdoit[] =
{0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
/* change reg 0x10 */
i2cpexpo[4] = 0xff - sd->brightness;
/* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
goto err; */
/* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
goto err; */
if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
goto err;
if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
goto err;
i2cp202[3] = sd->brightness >> 3;
if (i2c_w(gspca_dev->dev, i2cp202) < 0)
goto err;
if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
goto err;
break;
}
case SENSOR_TAS5130CXX:
case SENSOR_TAS5110: {
__u8 i2c[] =
{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
value = 0xff - sd->brightness;
i2c[4] = value;
PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
if (i2c_w(gspca_dev->dev, i2c) < 0)
goto err;
break;
}
}
return;
err:
PDEBUG(D_ERR, "i2c error brightness");
}
static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u8 gain;
__u8 rgb_value;
gain = sd->contrast >> 4;
/* red and blue gain */
rgb_value = gain << 4 | gain;
reg_w(gspca_dev->dev, 0x10, &rgb_value, 1);
/* green gain */
rgb_value = gain;
reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
/* __u16 vendor; */
__u16 product;
int sif = 0;
/* vendor = id->idVendor; */
product = id->idProduct;
/* switch (vendor) { */
/* case 0x0c45: * Sonix */
switch (product) {
case 0x6001: /* SN9C102 */
case 0x6005: /* SN9C101 */
case 0x6007: /* SN9C101 */
sd->sensor = SENSOR_TAS5110;
sif = 1;
break;
case 0x6009: /* SN9C101 */
case 0x600d: /* SN9C101 */
case 0x6029: /* SN9C101 */
sd->sensor = SENSOR_PAS106;
sif = 1;
break;
case 0x6011: /* SN9C101 - SN9C101G */
sd->sensor = SENSOR_OV6650;
sif = 1;
break;
case 0x6019: /* SN9C101 */
case 0x602c: /* SN9C102 */
case 0x602e: /* SN9C102 */
sd->sensor = SENSOR_OV7630;
break;
case 0x60b0: /* SN9C103 */
sd->sensor = SENSOR_OV7630_3;
break;
case 0x6024: /* SN9C102 */
case 0x6025: /* SN9C102 */
sd->sensor = SENSOR_TAS5130CXX;
break;
case 0x6028: /* SN9C102 */
sd->sensor = SENSOR_PAS202;
break;
case 0x602d: /* SN9C102 */
sd->sensor = SENSOR_HV7131R;
break;
case 0x60af: /* SN9C103 */
sd->sensor = SENSOR_PAS202;
break;
}
/* break; */
/* } */
cam = &gspca_dev->cam;
cam->dev_name = (char *) id->driver_info;
cam->epaddr = 0x01;
if (!sif) {
cam->cam_mode = vga_mode;
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
} else {
cam->cam_mode = sif_mode;
cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
}
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
reg_w(gspca_dev->dev, 0x01, probe_ov7630, sizeof probe_ov7630);
return 0;
}
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
__u8 ByteReceive;
reg_r(gspca_dev->dev, 0x00, &ByteReceive);
if (ByteReceive != 0x10)
return -ENODEV;
return 0;
}
static void pas106_i2cinit(struct usb_device *dev)
{
int i;
const __u8 *data;
__u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
i = ARRAY_SIZE(pas106_data);
data = pas106_data[0];
while (--i >= 0) {
memcpy(&i2c1[2], data, 2);
/* copy 2 bytes from the template */
if (i2c_w(dev, i2c1) < 0)
PDEBUG(D_ERR, "i2c error pas106");
data += 2;
}
}
/* -- start the camera -- */
static void sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
int mode, l;
const __u8 *sn9c10x;
__u8 reg01, reg17;
__u8 reg17_19[3];
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
switch (sd->sensor) {
case SENSOR_HV7131R:
sn9c10x = initHv7131;
reg17_19[0] = 0x60;
reg17_19[1] = (mode << 4) | 0x8a;
reg17_19[2] = 0x20;
break;
case SENSOR_OV6650:
sn9c10x = initOv6650;
reg17_19[0] = 0x68;
reg17_19[1] = (mode << 4) | 0x8b;
reg17_19[2] = 0x20;
break;
case SENSOR_OV7630:
sn9c10x = initOv7630;
reg17_19[0] = 0x68;
reg17_19[1] = (mode << 4) | COMP2;
reg17_19[2] = MCK_INIT1;
break;
case SENSOR_OV7630_3:
sn9c10x = initOv7630_3;
reg17_19[0] = 0x68;
reg17_19[1] = (mode << 4) | COMP2;
reg17_19[2] = MCK_INIT1;
break;
case SENSOR_PAS106:
sn9c10x = initPas106;
reg17_19[0] = 0x24; /* 0x28 */
reg17_19[1] = (mode << 4) | COMP1;
reg17_19[2] = MCK_INIT1;
break;
case SENSOR_PAS202:
sn9c10x = initPas202;
reg17_19[0] = mode ? 0x24 : 0x20;
reg17_19[1] = (mode << 4) | 0x89;
reg17_19[2] = 0x20;
break;
case SENSOR_TAS5110:
sn9c10x = initTas5110;
reg17_19[0] = 0x60;
reg17_19[1] = (mode << 4) | 0x86;
reg17_19[2] = 0x2b; /* 0xf3; */
break;
default:
/* case SENSOR_TAS5130CXX: */
sn9c10x = initTas5130;
reg17_19[0] = 0x60;
reg17_19[1] = (mode << 4) | COMP;
reg17_19[2] = mode ? 0x23 : 0x43;
break;
}
switch (sd->sensor) {
case SENSOR_OV7630:
reg01 = 0x06;
reg17 = 0x29;
l = 0x10;
break;
case SENSOR_OV7630_3:
reg01 = 0x44;
reg17 = 0x68;
l = 0x10;
break;
default:
reg01 = sn9c10x[0];
reg17 = sn9c10x[0x17 - 1];
l = 0x1f;
break;
}
/* reg 0x01 bit 2 video transfert on */
reg_w(dev, 0x01, &reg01, 1);
/* reg 0x17 SensorClk enable inv Clk 0x60 */
reg_w(dev, 0x17, &reg17, 1);
/*fixme: for ov7630 102
reg_w(dev, 0x01, {0x06, sn9c10x[1]}, 2); */
/* Set the registers from the template */
reg_w(dev, 0x01, sn9c10x, l);
switch (sd->sensor) {
case SENSOR_HV7131R:
i2c_w_vector(dev, hv7131_sensor_init,
sizeof hv7131_sensor_init);
break;
case SENSOR_OV6650:
i2c_w_vector(dev, ov6650_sensor_init,
sizeof ov6650_sensor_init);
break;
case SENSOR_OV7630:
i2c_w_vector(dev, ov7630_sensor_init_com,
sizeof ov7630_sensor_init_com);
msleep(200);
i2c_w_vector(dev, ov7630_sensor_init,
sizeof ov7630_sensor_init);
break;
case SENSOR_OV7630_3:
i2c_w_vector(dev, ov7630_sensor_init_com,
sizeof ov7630_sensor_init_com);
msleep(200);
i2c_w_vector(dev, ov7630_sensor_init_3,
sizeof ov7630_sensor_init_3);
break;
case SENSOR_PAS106:
pas106_i2cinit(dev);
break;
case SENSOR_PAS202:
i2c_w_vector(dev, pas202_sensor_init,
sizeof pas202_sensor_init);
break;
case SENSOR_TAS5110:
i2c_w_vector(dev, tas5110_sensor_init,
sizeof tas5110_sensor_init);
break;
default:
/* case SENSOR_TAS5130CXX: */
i2c_w_vector(dev, tas5130_sensor_init,
sizeof tas5130_sensor_init);
break;
}
/* H_size V_size 0x28, 0x1e maybe 640x480 */
reg_w(dev, 0x15, &sn9c10x[0x15 - 1], 2);
/* compression register */
reg_w(dev, 0x18, &reg17_19[1], 1);
/* H_start */ /*fixme: not ov7630*/
reg_w(dev, 0x12, &sn9c10x[0x12 - 1], 1);
/* V_START */ /*fixme: not ov7630*/
reg_w(dev, 0x13, &sn9c10x[0x13 - 1], 1);
/* reset 0x17 SensorClk enable inv Clk 0x60 */
/*fixme: ov7630 [17]=68 8f (+20 if 102)*/
reg_w(dev, 0x17, &reg17_19[0], 1);
/*MCKSIZE ->3 */ /*fixme: not ov7630*/
reg_w(dev, 0x19, &reg17_19[2], 1);
/* AE_STRX AE_STRY AE_ENDX AE_ENDY */
reg_w(dev, 0x1c, &sn9c10x[0x1c - 1], 4);
/* Enable video transfert */
reg_w(dev, 0x01, &sn9c10x[0], 1);
/* Compression */
reg_w(dev, 0x18, &reg17_19[1], 2);
msleep(20);
setcontrast(gspca_dev);
setbrightness(gspca_dev);
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
__u8 ByteSend = 0;
ByteSend = 0x09; /* 0X00 */
reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
}
static void sd_close(struct gspca_dev *gspca_dev)
{
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
unsigned char *data, /* isoc packet */
int len) /* iso packet length */
{
int p;
if (len > 6 && len < 24) {
for (p = 0; p < len - 6; p++) {
if (data[0 + p] == 0xff
&& data[1 + p] == 0xff
&& data[2 + p] == 0x00
&& data[3 + p] == 0xc4
&& data[4 + p] == 0xc4
&& data[5 + p] == 0x96) { /* start of frame */
frame = gspca_frame_add(gspca_dev,
LAST_PACKET,
frame,
data, 0);
data += 12;
len -= 12;
gspca_frame_add(gspca_dev, FIRST_PACKET,
frame, data, len);
return;
}
}
}
gspca_frame_add(gspca_dev, INTER_PACKET,
frame, data, len);
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming)
setbrightness(gspca_dev);
return 0;
}
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->brightness;
return 0;
}
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
if (gspca_dev->streaming)
setcontrast(gspca_dev);
return 0;
}
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->contrast;
return 0;
}
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.open = sd_open,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
#define DVNM(name) .driver_info = (kernel_ulong_t) name
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
{USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
{USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
{USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
{USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
{USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia-OV6650-SN9C101G")},
{USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
{USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
{USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
{USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
{USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
{USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
{USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
{USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
{USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
{USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
};
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
if (usb_register(&sd_driver) < 0)
return -1;
PDEBUG(D_PROBE, "v%s registered", version);
return 0;
}
static void __exit sd_mod_exit(void)
{
usb_deregister(&sd_driver);
PDEBUG(D_PROBE, "deregistered");
}
module_init(sd_mod_init);
module_exit(sd_mod_exit);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,933 @@
/*
* SPCA505 chip based cameras initialization data
*
* V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define MODULE_NAME "spca505"
#include "gspca.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
MODULE_LICENSE("GPL");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
int buflen;
unsigned char tmpbuf[640 * 480 * 3 / 2]; /* YYUV per line */
unsigned char tmpbuf2[640 * 480 * 2]; /* YUYV */
unsigned char brightness;
char subtype;
#define IntelPCCameraPro 0
#define Nxultra 1
};
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 127,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
};
static struct cam_mode vga_mode[] = {
{V4L2_PIX_FMT_YUYV, 160, 120, 5},
{V4L2_PIX_FMT_YUYV, 176, 144, 4},
{V4L2_PIX_FMT_YUYV, 320, 240, 2},
{V4L2_PIX_FMT_YUYV, 352, 288, 1},
{V4L2_PIX_FMT_YUYV, 640, 480, 0},
};
#define SPCA50X_OFFSET_DATA 10
#define SPCA50X_REG_USB 0x02 /* spca505 501 */
#define SPCA50X_USB_CTRL 0x00 /* spca505 */
#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
/*
* Data to initialize a SPCA505. Common to the CCD and external modes
*/
static __u16 spca505_init_data[][3] = {
/* line bmRequest,value,index */
/* 1819 */
{SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
/* Sensor reset */
/* 1822 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
/* 1825 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
/* Block USB reset */
/* 1828 */ {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL,
SPCA50X_GLOBAL_MISC0},
/* 1831 */ {0x5, 0x01, 0x10},
/* Maybe power down some stuff */
/* 1834 */ {0x5, 0x0f, 0x11},
/* Setup internal CCD ? */
/* 1837 */ {0x6, 0x10, 0x08},
/* 1840 */ {0x6, 0x00, 0x09},
/* 1843 */ {0x6, 0x00, 0x0a},
/* 1846 */ {0x6, 0x00, 0x0b},
/* 1849 */ {0x6, 0x10, 0x0c},
/* 1852 */ {0x6, 0x00, 0x0d},
/* 1855 */ {0x6, 0x00, 0x0e},
/* 1858 */ {0x6, 0x00, 0x0f},
/* 1861 */ {0x6, 0x10, 0x10},
/* 1864 */ {0x6, 0x02, 0x11},
/* 1867 */ {0x6, 0x00, 0x12},
/* 1870 */ {0x6, 0x04, 0x13},
/* 1873 */ {0x6, 0x02, 0x14},
/* 1876 */ {0x6, 0x8a, 0x51},
/* 1879 */ {0x6, 0x40, 0x52},
/* 1882 */ {0x6, 0xb6, 0x53},
/* 1885 */ {0x6, 0x3d, 0x54},
{}
};
/*
* Data to initialize the camera using the internal CCD
*/
static __u16 spca505_open_data_ccd[][3] = {
/* line bmRequest,value,index */
/* Internal CCD data set */
/* 1891 */ {0x3, 0x04, 0x01},
/* This could be a reset */
/* 1894 */ {0x3, 0x00, 0x01},
/* Setup compression and image registers. 0x6 and 0x7 seem to be
related to H&V hold, and are resolution mode specific */
/* 1897 */ {0x4, 0x10, 0x01},
/* DIFF(0x50), was (0x10) */
/* 1900 */ {0x4, 0x00, 0x04},
/* 1903 */ {0x4, 0x00, 0x05},
/* 1906 */ {0x4, 0x20, 0x06},
/* 1909 */ {0x4, 0x20, 0x07},
/* 1912 */ {0x8, 0x0a, 0x00},
/* DIFF (0x4a), was (0xa) */
/* 1915 */ {0x5, 0x00, 0x10},
/* 1918 */ {0x5, 0x00, 0x11},
/* 1921 */ {0x5, 0x00, 0x00},
/* DIFF not written */
/* 1924 */ {0x5, 0x00, 0x01},
/* DIFF not written */
/* 1927 */ {0x5, 0x00, 0x02},
/* DIFF not written */
/* 1930 */ {0x5, 0x00, 0x03},
/* DIFF not written */
/* 1933 */ {0x5, 0x00, 0x04},
/* DIFF not written */
/* 1936 */ {0x5, 0x80, 0x05},
/* DIFF not written */
/* 1939 */ {0x5, 0xe0, 0x06},
/* DIFF not written */
/* 1942 */ {0x5, 0x20, 0x07},
/* DIFF not written */
/* 1945 */ {0x5, 0xa0, 0x08},
/* DIFF not written */
/* 1948 */ {0x5, 0x0, 0x12},
/* DIFF not written */
/* 1951 */ {0x5, 0x02, 0x0f},
/* DIFF not written */
/* 1954 */ {0x5, 0x10, 0x46},
/* DIFF not written */
/* 1957 */ {0x5, 0x8, 0x4a},
/* DIFF not written */
/* 1960 */ {0x3, 0x08, 0x03},
/* DIFF (0x3,0x28,0x3) */
/* 1963 */ {0x3, 0x08, 0x01},
/* 1966 */ {0x3, 0x0c, 0x03},
/* DIFF not written */
/* 1969 */ {0x3, 0x21, 0x00},
/* DIFF (0x39) */
/* Extra block copied from init to hopefully ensure CCD is in a sane state */
/* 1837 */ {0x6, 0x10, 0x08},
/* 1840 */ {0x6, 0x00, 0x09},
/* 1843 */ {0x6, 0x00, 0x0a},
/* 1846 */ {0x6, 0x00, 0x0b},
/* 1849 */ {0x6, 0x10, 0x0c},
/* 1852 */ {0x6, 0x00, 0x0d},
/* 1855 */ {0x6, 0x00, 0x0e},
/* 1858 */ {0x6, 0x00, 0x0f},
/* 1861 */ {0x6, 0x10, 0x10},
/* 1864 */ {0x6, 0x02, 0x11},
/* 1867 */ {0x6, 0x00, 0x12},
/* 1870 */ {0x6, 0x04, 0x13},
/* 1873 */ {0x6, 0x02, 0x14},
/* 1876 */ {0x6, 0x8a, 0x51},
/* 1879 */ {0x6, 0x40, 0x52},
/* 1882 */ {0x6, 0xb6, 0x53},
/* 1885 */ {0x6, 0x3d, 0x54},
/* End of extra block */
/* 1972 */ {0x6, 0x3f, 0x1},
/* Block skipped */
/* 1975 */ {0x6, 0x10, 0x02},
/* 1978 */ {0x6, 0x64, 0x07},
/* 1981 */ {0x6, 0x10, 0x08},
/* 1984 */ {0x6, 0x00, 0x09},
/* 1987 */ {0x6, 0x00, 0x0a},
/* 1990 */ {0x6, 0x00, 0x0b},
/* 1993 */ {0x6, 0x10, 0x0c},
/* 1996 */ {0x6, 0x00, 0x0d},
/* 1999 */ {0x6, 0x00, 0x0e},
/* 2002 */ {0x6, 0x00, 0x0f},
/* 2005 */ {0x6, 0x10, 0x10},
/* 2008 */ {0x6, 0x02, 0x11},
/* 2011 */ {0x6, 0x00, 0x12},
/* 2014 */ {0x6, 0x04, 0x13},
/* 2017 */ {0x6, 0x02, 0x14},
/* 2020 */ {0x6, 0x8a, 0x51},
/* 2023 */ {0x6, 0x40, 0x52},
/* 2026 */ {0x6, 0xb6, 0x53},
/* 2029 */ {0x6, 0x3d, 0x54},
/* 2032 */ {0x6, 0x60, 0x57},
/* 2035 */ {0x6, 0x20, 0x58},
/* 2038 */ {0x6, 0x15, 0x59},
/* 2041 */ {0x6, 0x05, 0x5a},
/* 2044 */ {0x5, 0x01, 0xc0},
/* 2047 */ {0x5, 0x10, 0xcb},
/* 2050 */ {0x5, 0x80, 0xc1},
/* */
/* 2053 */ {0x5, 0x0, 0xc2},
/* 4 was 0 */
/* 2056 */ {0x5, 0x00, 0xca},
/* 2059 */ {0x5, 0x80, 0xc1},
/* */
/* 2062 */ {0x5, 0x04, 0xc2},
/* 2065 */ {0x5, 0x00, 0xca},
/* 2068 */ {0x5, 0x0, 0xc1},
/* */
/* 2071 */ {0x5, 0x00, 0xc2},
/* 2074 */ {0x5, 0x00, 0xca},
/* 2077 */ {0x5, 0x40, 0xc1},
/* */
/* 2080 */ {0x5, 0x17, 0xc2},
/* 2083 */ {0x5, 0x00, 0xca},
/* 2086 */ {0x5, 0x80, 0xc1},
/* */
/* 2089 */ {0x5, 0x06, 0xc2},
/* 2092 */ {0x5, 0x00, 0xca},
/* 2095 */ {0x5, 0x80, 0xc1},
/* */
/* 2098 */ {0x5, 0x04, 0xc2},
/* 2101 */ {0x5, 0x00, 0xca},
/* 2104 */ {0x3, 0x4c, 0x3},
/* 2107 */ {0x3, 0x18, 0x1},
/* 2110 */ {0x6, 0x70, 0x51},
/* 2113 */ {0x6, 0xbe, 0x53},
/* 2116 */ {0x6, 0x71, 0x57},
/* 2119 */ {0x6, 0x20, 0x58},
/* 2122 */ {0x6, 0x05, 0x59},
/* 2125 */ {0x6, 0x15, 0x5a},
/* 2128 */ {0x4, 0x00, 0x08},
/* Compress = OFF (0x1 to turn on) */
/* 2131 */ {0x4, 0x12, 0x09},
/* 2134 */ {0x4, 0x21, 0x0a},
/* 2137 */ {0x4, 0x10, 0x0b},
/* 2140 */ {0x4, 0x21, 0x0c},
/* 2143 */ {0x4, 0x05, 0x00},
/* was 5 (Image Type ? ) */
/* 2146 */ {0x4, 0x00, 0x01},
/* 2149 */ {0x6, 0x3f, 0x01},
/* 2152 */ {0x4, 0x00, 0x04},
/* 2155 */ {0x4, 0x00, 0x05},
/* 2158 */ {0x4, 0x40, 0x06},
/* 2161 */ {0x4, 0x40, 0x07},
/* 2164 */ {0x6, 0x1c, 0x17},
/* 2167 */ {0x6, 0xe2, 0x19},
/* 2170 */ {0x6, 0x1c, 0x1b},
/* 2173 */ {0x6, 0xe2, 0x1d},
/* 2176 */ {0x6, 0xaa, 0x1f},
/* 2179 */ {0x6, 0x70, 0x20},
/* 2182 */ {0x5, 0x01, 0x10},
/* 2185 */ {0x5, 0x00, 0x11},
/* 2188 */ {0x5, 0x01, 0x00},
/* 2191 */ {0x5, 0x05, 0x01},
/* 2194 */ {0x5, 0x00, 0xc1},
/* */
/* 2197 */ {0x5, 0x00, 0xc2},
/* 2200 */ {0x5, 0x00, 0xca},
/* 2203 */ {0x6, 0x70, 0x51},
/* 2206 */ {0x6, 0xbe, 0x53},
{}
};
/*
Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
* SPCA505b chip based cameras initialization data
*
*/
/* jfm */
#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */
/*
* Data to initialize a SPCA505. Common to the CCD and external modes
*/
static __u16 spca505b_init_data[][3] = {
/* start */
{0x02, 0x00, 0x00}, /* init */
{0x02, 0x00, 0x01},
{0x02, 0x00, 0x02},
{0x02, 0x00, 0x03},
{0x02, 0x00, 0x04},
{0x02, 0x00, 0x05},
{0x02, 0x00, 0x06},
{0x02, 0x00, 0x07},
{0x02, 0x00, 0x08},
{0x02, 0x00, 0x09},
{0x03, 0x00, 0x00},
{0x03, 0x00, 0x01},
{0x03, 0x00, 0x02},
{0x03, 0x00, 0x03},
{0x03, 0x00, 0x04},
{0x03, 0x00, 0x05},
{0x03, 0x00, 0x06},
{0x04, 0x00, 0x00},
{0x04, 0x00, 0x02},
{0x04, 0x00, 0x04},
{0x04, 0x00, 0x05},
{0x04, 0x00, 0x06},
{0x04, 0x00, 0x07},
{0x04, 0x00, 0x08},
{0x04, 0x00, 0x09},
{0x04, 0x00, 0x0a},
{0x04, 0x00, 0x0b},
{0x04, 0x00, 0x0c},
{0x07, 0x00, 0x00},
{0x07, 0x00, 0x03},
{0x08, 0x00, 0x00},
{0x08, 0x00, 0x01},
{0x08, 0x00, 0x02},
{0x00, 0x01, 0x00},
{0x00, 0x01, 0x01},
{0x00, 0x01, 0x34},
{0x00, 0x01, 0x35},
{0x06, 0x18, 0x08},
{0x06, 0xfc, 0x09},
{0x06, 0xfc, 0x0a},
{0x06, 0xfc, 0x0b},
{0x06, 0x18, 0x0c},
{0x06, 0xfc, 0x0d},
{0x06, 0xfc, 0x0e},
{0x06, 0xfc, 0x0f},
{0x06, 0x18, 0x10},
{0x06, 0xfe, 0x12},
{0x06, 0x00, 0x11},
{0x06, 0x00, 0x14},
{0x06, 0x00, 0x13},
{0x06, 0x28, 0x51},
{0x06, 0xff, 0x53},
{0x02, 0x00, 0x08},
{0x03, 0x00, 0x03},
{0x03, 0x10, 0x03},
{}
};
/*
* Data to initialize the camera using the internal CCD
*/
static __u16 spca505b_open_data_ccd[][3] = {
/* {0x02,0x00,0x00}, */
{0x03, 0x04, 0x01}, /* rst */
{0x03, 0x00, 0x01},
{0x03, 0x00, 0x00},
{0x03, 0x21, 0x00},
{0x03, 0x00, 0x04},
{0x03, 0x00, 0x03},
{0x03, 0x18, 0x03},
{0x03, 0x08, 0x01},
{0x03, 0x1c, 0x03},
{0x03, 0x5c, 0x03},
{0x03, 0x5c, 0x03},
{0x03, 0x18, 0x01},
/* same as 505 */
{0x04, 0x10, 0x01},
{0x04, 0x00, 0x04},
{0x04, 0x00, 0x05},
{0x04, 0x20, 0x06},
{0x04, 0x20, 0x07},
{0x08, 0x0a, 0x00},
{0x05, 0x00, 0x10},
{0x05, 0x00, 0x11},
{0x05, 0x00, 0x12},
{0x05, 0x6f, 0x00},
{0x05, initial_brightness >> 6, 0x00},
{0x05, initial_brightness << 2, 0x01},
{0x05, 0x00, 0x02},
{0x05, 0x01, 0x03},
{0x05, 0x00, 0x04},
{0x05, 0x03, 0x05},
{0x05, 0xe0, 0x06},
{0x05, 0x20, 0x07},
{0x05, 0xa0, 0x08},
{0x05, 0x00, 0x12},
{0x05, 0x02, 0x0f},
{0x05, 128, 0x14}, /* max exposure off (0=on) */
{0x05, 0x01, 0xb0},
{0x05, 0x01, 0xbf},
{0x03, 0x02, 0x06},
{0x05, 0x10, 0x46},
{0x05, 0x08, 0x4a},
{0x06, 0x00, 0x01},
{0x06, 0x10, 0x02},
{0x06, 0x64, 0x07},
{0x06, 0x18, 0x08},
{0x06, 0xfc, 0x09},
{0x06, 0xfc, 0x0a},
{0x06, 0xfc, 0x0b},
{0x04, 0x00, 0x01},
{0x06, 0x18, 0x0c},
{0x06, 0xfc, 0x0d},
{0x06, 0xfc, 0x0e},
{0x06, 0xfc, 0x0f},
{0x06, 0x11, 0x10}, /* contrast */
{0x06, 0x00, 0x11},
{0x06, 0xfe, 0x12},
{0x06, 0x00, 0x13},
{0x06, 0x00, 0x14},
{0x06, 0x9d, 0x51},
{0x06, 0x40, 0x52},
{0x06, 0x7c, 0x53},
{0x06, 0x40, 0x54},
{0x06, 0x02, 0x57},
{0x06, 0x03, 0x58},
{0x06, 0x15, 0x59},
{0x06, 0x05, 0x5a},
{0x06, 0x03, 0x56},
{0x06, 0x02, 0x3f},
{0x06, 0x00, 0x40},
{0x06, 0x39, 0x41},
{0x06, 0x69, 0x42},
{0x06, 0x87, 0x43},
{0x06, 0x9e, 0x44},
{0x06, 0xb1, 0x45},
{0x06, 0xbf, 0x46},
{0x06, 0xcc, 0x47},
{0x06, 0xd5, 0x48},
{0x06, 0xdd, 0x49},
{0x06, 0xe3, 0x4a},
{0x06, 0xe8, 0x4b},
{0x06, 0xed, 0x4c},
{0x06, 0xf2, 0x4d},
{0x06, 0xf7, 0x4e},
{0x06, 0xfc, 0x4f},
{0x06, 0xff, 0x50},
{0x05, 0x01, 0xc0},
{0x05, 0x10, 0xcb},
{0x05, 0x40, 0xc1},
{0x05, 0x04, 0xc2},
{0x05, 0x00, 0xca},
{0x05, 0x40, 0xc1},
{0x05, 0x09, 0xc2},
{0x05, 0x00, 0xca},
{0x05, 0xc0, 0xc1},
{0x05, 0x09, 0xc2},
{0x05, 0x00, 0xca},
{0x05, 0x40, 0xc1},
{0x05, 0x59, 0xc2},
{0x05, 0x00, 0xca},
{0x04, 0x00, 0x01},
{0x05, 0x80, 0xc1},
{0x05, 0xec, 0xc2},
{0x05, 0x0, 0xca},
{0x06, 0x02, 0x57},
{0x06, 0x01, 0x58},
{0x06, 0x15, 0x59},
{0x06, 0x0a, 0x5a},
{0x06, 0x01, 0x57},
{0x06, 0x8a, 0x03},
{0x06, 0x0a, 0x6c},
{0x06, 0x30, 0x01},
{0x06, 0x20, 0x02},
{0x06, 0x00, 0x03},
{0x05, 0x8c, 0x25},
{0x06, 0x4d, 0x51}, /* maybe saturation (4d) */
{0x06, 0x84, 0x53}, /* making green (84) */
{0x06, 0x00, 0x57}, /* sharpness (1) */
{0x06, 0x18, 0x08},
{0x06, 0xfc, 0x09},
{0x06, 0xfc, 0x0a},
{0x06, 0xfc, 0x0b},
{0x06, 0x18, 0x0c}, /* maybe hue (18) */
{0x06, 0xfc, 0x0d},
{0x06, 0xfc, 0x0e},
{0x06, 0xfc, 0x0f},
{0x06, 0x18, 0x10}, /* maybe contrast (18) */
{0x05, 0x01, 0x02},
{0x04, 0x00, 0x08}, /* compression */
{0x04, 0x12, 0x09},
{0x04, 0x21, 0x0a},
{0x04, 0x10, 0x0b},
{0x04, 0x21, 0x0c},
{0x04, 0x1d, 0x00}, /* imagetype (1d) */
{0x04, 0x41, 0x01}, /* hardware snapcontrol */
{0x04, 0x00, 0x04},
{0x04, 0x00, 0x05},
{0x04, 0x10, 0x06},
{0x04, 0x10, 0x07},
{0x04, 0x40, 0x06},
{0x04, 0x40, 0x07},
{0x04, 0x00, 0x04},
{0x04, 0x00, 0x05},
{0x06, 0x1c, 0x17},
{0x06, 0xe2, 0x19},
{0x06, 0x1c, 0x1b},
{0x06, 0xe2, 0x1d},
{0x06, 0x5f, 0x1f},
{0x06, 0x32, 0x20},
{0x05, initial_brightness >> 6, 0x00},
{0x05, initial_brightness << 2, 0x01},
{0x05, 0x06, 0xc1},
{0x05, 0x58, 0xc2},
{0x05, 0x0, 0xca},
{0x05, 0x0, 0x11},
{}
};
static int reg_write(struct usb_device *dev,
__u16 reg, __u16 index, __u16 value)
{
int ret;
ret = usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
reg,
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, NULL, 0, 500);
PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x",
reg, index, value, ret);
if (ret < 0)
PDEBUG(D_ERR, "reg write: error %d", ret);
return ret;
}
/* returns: negative is error, pos or zero is data */
static int reg_read(struct usb_device *dev,
__u16 reg, /* bRequest */
__u16 index, /* wIndex */
__u16 length) /* wLength (1 or 2 only) */
{
int ret;
unsigned char buf[4];
buf[1] = 0;
ret = usb_control_msg(dev,
usb_rcvctrlpipe(dev, 0),
reg,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
(__u16) 0, /* value */
(__u16) index,
buf,
length,
500); /* timeout */
if (ret < 0) {
PDEBUG(D_ERR, "reg_read err %d", ret);
return -1;
}
return (buf[1] << 8) + buf[0];
}
static int write_vector(struct gspca_dev *gspca_dev,
__u16 data[][3])
{
struct usb_device *dev = gspca_dev->dev;
int ret, i = 0;
while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
if (ret < 0) {
PDEBUG(D_ERR,
"Register write failed for 0x%x,0x%x,0x%x",
data[i][0], data[i][1], data[i][2]);
return ret;
}
i++;
}
return 0;
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
__u16 vendor;
__u16 product;
vendor = id->idVendor;
product = id->idProduct;
switch (vendor) {
case 0x041e: /* Creative cameras */
/* switch (product) { */
/* case 0x401d: * here505b */
sd->subtype = Nxultra;
/* break; */
/* } */
break;
case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
/* switch (product) { */
/* case 0x0430: */
/* fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
sd->subtype = IntelPCCameraPro;
/* break; */
/* } */
break;
}
cam = &gspca_dev->cam;
cam->dev_name = (char *) id->driver_info;
cam->epaddr = 0x01;
cam->cam_mode = vga_mode;
if (sd->subtype != IntelPCCameraPro)
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
else /* no 640x480 for IntelPCCameraPro */
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0] - 1;
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
if (sd->subtype == Nxultra) {
if (write_vector(gspca_dev, spca505b_init_data))
return -EIO;
} else {
if (write_vector(gspca_dev, spca505_init_data))
return -EIO;
}
return 0;
}
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret;
PDEBUG(D_STREAM, "Initializing SPCA505");
if (sd->subtype == Nxultra)
write_vector(gspca_dev, spca505b_open_data_ccd);
else
write_vector(gspca_dev, spca505_open_data_ccd);
ret = reg_read(gspca_dev->dev, 6, 0x16, 2);
if (ret < 0) {
PDEBUG(D_ERR|D_STREAM,
"register read failed for after vector read err = %d",
ret);
return -EIO;
}
PDEBUG(D_STREAM,
"After vector read returns : 0x%x should be 0x0101",
ret & 0xffff);
ret = reg_write(gspca_dev->dev, 6, 0x16, 0x0a);
if (ret < 0) {
PDEBUG(D_ERR, "register write failed for (6,0xa,0x16) err=%d",
ret);
return -EIO;
}
reg_write(gspca_dev->dev, 5, 0xc2, 18);
return 0;
}
static void sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
int ret;
/* necessary because without it we can see stream
* only once after loading module */
/* stopping usb registers Tomasz change */
reg_write(dev, 0x02, 0x0, 0x0);
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
case 0:
reg_write(dev, 0x04, 0x00, 0x00);
reg_write(dev, 0x04, 0x06, 0x10);
reg_write(dev, 0x04, 0x07, 0x10);
break;
case 1:
reg_write(dev, 0x04, 0x00, 0x01);
reg_write(dev, 0x04, 0x06, 0x1a);
reg_write(dev, 0x04, 0x07, 0x1a);
break;
case 2:
reg_write(dev, 0x04, 0x00, 0x02);
reg_write(dev, 0x04, 0x06, 0x1c);
reg_write(dev, 0x04, 0x07, 0x1d);
break;
case 4:
reg_write(dev, 0x04, 0x00, 0x04);
reg_write(dev, 0x04, 0x06, 0x34);
reg_write(dev, 0x04, 0x07, 0x34);
break;
default:
/* case 5: */
reg_write(dev, 0x04, 0x00, 0x05);
reg_write(dev, 0x04, 0x06, 0x40);
reg_write(dev, 0x04, 0x07, 0x40);
break;
}
/* Enable ISO packet machine - should we do this here or in ISOC init ? */
ret = reg_write(dev, SPCA50X_REG_USB,
SPCA50X_USB_CTRL,
SPCA50X_CUSB_ENABLE);
/* reg_write(dev, 0x5, 0x0, 0x0); */
/* reg_write(dev, 0x5, 0x0, 0x1); */
/* reg_write(dev, 0x5, 0x11, 0x2); */
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
/* Disable ISO packet machine */
reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
}
/* this function is called at close time */
static void sd_close(struct gspca_dev *gspca_dev)
{
/* This maybe reset or power control */
reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
reg_write(gspca_dev->dev, 0x03, 0x00, 0x1);
reg_write(gspca_dev->dev, 0x05, 0x10, 0x1);
reg_write(gspca_dev->dev, 0x05, 0x11, 0xf);
}
/* convert YYUV per line to YUYV (YUV 4:2:2) */
static void yyuv_decode(unsigned char *out,
unsigned char *in,
int width,
int height)
{
unsigned char *Ui, *Vi, *yi, *yi1;
unsigned char *out1;
int i, j;
yi = in;
for (i = height / 2; --i >= 0; ) {
out1 = out + width * 2; /* next line */
yi1 = yi + width;
Ui = yi1 + width;
Vi = Ui + width / 2;
for (j = width / 2; --j >= 0; ) {
*out++ = 128 + *yi++;
*out++ = 128 + *Ui;
*out++ = 128 + *yi++;
*out++ = 128 + *Vi;
*out1++ = 128 + *yi1++;
*out1++ = 128 + *Ui++;
*out1++ = 128 + *yi1++;
*out1++ = 128 + *Vi++;
}
yi += width * 2;
out = out1;
}
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
unsigned char *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
switch (data[0]) {
case 0: /* start of frame */
if (gspca_dev->last_packet_type == FIRST_PACKET) {
yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
gspca_dev->width,
gspca_dev->height);
frame = gspca_frame_add(gspca_dev,
LAST_PACKET,
frame,
sd->tmpbuf2,
gspca_dev->width
* gspca_dev->height
* 2);
}
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
data, 0);
data += SPCA50X_OFFSET_DATA;
len -= SPCA50X_OFFSET_DATA;
if (len > 0)
memcpy(sd->tmpbuf, data, len);
else
len = 0;
sd->buflen = len;
return;
case 0xff: /* drop */
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
return;
}
data += 1;
len -= 1;
memcpy(&sd->tmpbuf[sd->buflen], data, len);
sd->buflen += len;
}
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u8 brightness = sd->brightness;
reg_write(gspca_dev->dev, 5, 0x00, (255 - brightness) >> 6);
reg_write(gspca_dev->dev, 5, 0x01, (255 - brightness) << 2);
}
static void getbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = 255
- ((reg_read(gspca_dev->dev, 5, 0x01, 1) >> 2)
+ (reg_read(gspca_dev->dev, 5, 0x0, 1) << 6));
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming)
setbrightness(gspca_dev);
return 0;
}
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.open = sd_open,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
#define DVNM(name) .driver_info = (kernel_ulong_t) name
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x041e, 0x401d), DVNM("Creative Webcam NX ULTRA")},
{USB_DEVICE(0x0733, 0x0430), DVNM("Intel PC Camera Pro")},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc, sizeof (struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
};
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
if (usb_register(&sd_driver) < 0)
return -1;
PDEBUG(D_PROBE, "v%s registered", version);
return 0;
}
static void __exit sd_mod_exit(void)
{
usb_deregister(&sd_driver);
PDEBUG(D_PROBE, "deregistered");
}
module_init(sd_mod_init);
module_exit(sd_mod_exit);

Просмотреть файл

@ -0,0 +1,830 @@
/*
* SPCA506 chip based cameras function
* M Xhaard 15/04/2004 based on different work Mark Taylor and others
* and my own snoopy file on a pv-321c donate by a german compagny
* "Firma Frank Gmbh" from Saarbruecken
*
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define MODULE_NAME "spca506"
#include "gspca.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
MODULE_LICENSE("GPL");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
int buflen;
unsigned char tmpbuf[640 * 480 * 3]; /* YYUV per line */
unsigned char tmpbuf2[640 * 480 * 2]; /* YUYV */
unsigned char brightness;
unsigned char contrast;
unsigned char colors;
unsigned char hue;
char norme;
char channel;
};
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
.maximum = 0xff,
.step = 1,
.default_value = 0x80,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
#define SD_CONTRAST 1
{
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
.maximum = 0xff,
.step = 1,
.default_value = 0x47,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
},
#define SD_COLOR 2
{
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Saturation",
.minimum = 0,
.maximum = 0xff,
.step = 1,
.default_value = 0x40,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
#define SD_HUE 3
{
{
.id = V4L2_CID_HUE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Hue",
.minimum = 0,
.maximum = 0xff,
.step = 1,
.default_value = 0,
},
.set = sd_sethue,
.get = sd_gethue,
},
};
static struct cam_mode vga_mode[] = {
{V4L2_PIX_FMT_YUYV, 160, 120, 5},
{V4L2_PIX_FMT_YUYV, 176, 144, 4},
{V4L2_PIX_FMT_YUYV, 320, 240, 2},
{V4L2_PIX_FMT_YUYV, 352, 288, 1},
{V4L2_PIX_FMT_YUYV, 640, 480, 0},
};
#define SPCA50X_OFFSET_DATA 10
#define SAA7113_bright 0x0a /* defaults 0x80 */
#define SAA7113_contrast 0x0b /* defaults 0x47 */
#define SAA7113_saturation 0x0c /* defaults 0x40 */
#define SAA7113_hue 0x0d /* defaults 0x00 */
#define SAA7113_I2C_BASE_WRITE 0x4a
static void reg_r(struct usb_device *dev,
__u16 req,
__u16 index,
__u8 *buffer, __u16 length)
{
usb_control_msg(dev,
usb_rcvctrlpipe(dev, 0),
req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, /* value */
index, buffer, length,
500);
}
static void reg_w(struct usb_device *dev,
__u16 req,
__u16 value,
__u16 index)
{
usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index,
NULL, 0, 500);
}
static void spca506_Initi2c(struct gspca_dev *gspca_dev)
{
reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
}
static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
__u16 reg)
{
int retry = 60;
unsigned char Data[2];
reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
while (retry--) {
reg_r(gspca_dev->dev, 0x07, 0x0003, Data, 2);
if ((Data[0] | Data[1]) == 0x00)
break;
}
}
static int spca506_ReadI2c(struct gspca_dev *gspca_dev, __u16 reg)
{
int retry = 60;
unsigned char Data[2];
unsigned char value;
reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
reg_w(gspca_dev->dev, 0x07, 0x01, 0x0002);
while (--retry) {
reg_r(gspca_dev->dev, 0x07, 0x0003, Data, 2);
if ((Data[0] | Data[1]) == 0x00)
break;
}
if (retry == 0)
return -1;
reg_r(gspca_dev->dev, 0x07, 0x0000, &value, 1);
return value;
}
static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
__u16 norme,
__u16 channel)
{
struct sd *sd = (struct sd *) gspca_dev;
/* fixme: check if channel == 0..3 and 6..9 (8 values) */
__u8 setbit0 = 0x00;
__u8 setbit1 = 0x00;
__u8 videomask = 0x00;
PDEBUG(D_STREAM, "** Open Set Norme **");
spca506_Initi2c(gspca_dev);
/* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
/* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
/* and exclude SAA7113 reserved channel set default 0 otherwise */
if (norme & V4L2_STD_NTSC)
setbit0 = 0x01;
if (channel == 4 || channel == 5 || channel > 9)
channel = 0;
if (channel < 4)
setbit1 = 0x02;
videomask = (0x48 | setbit0 | setbit1);
reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
if (norme & V4L2_STD_NTSC)
spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
/* Chrominance Control NTSC N */
else if (norme & V4L2_STD_SECAM)
spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
/* Chrominance Control SECAM */
else
spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
/* Chrominance Control PAL BGHIV */
sd->norme = norme;
sd->channel = channel;
PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
}
static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
__u16 *norme, __u16 *channel)
{
struct sd *sd = (struct sd *) gspca_dev;
/* Read the register is not so good value change so
we use your own copy in spca50x struct */
*norme = sd->norme;
*channel = sd->channel;
PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
}
static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
__u16 xmult, __u16 ymult)
{
struct usb_device *dev = gspca_dev->dev;
PDEBUG(D_STREAM, "** SetSize **");
reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
/* Soft snap 0x40 Hard 0x41 */
reg_w(dev, 0x04, 0x41, 0x0001);
reg_w(dev, 0x04, 0x00, 0x0002);
/* reserved */
reg_w(dev, 0x04, 0x00, 0x0003);
/* reserved */
reg_w(dev, 0x04, 0x00, 0x0004);
/* reserved */
reg_w(dev, 0x04, 0x01, 0x0005);
/* reserced */
reg_w(dev, 0x04, xmult, 0x0006);
/* reserved */
reg_w(dev, 0x04, ymult, 0x0007);
/* compression 1 */
reg_w(dev, 0x04, 0x00, 0x0008);
/* T=64 -> 2 */
reg_w(dev, 0x04, 0x00, 0x0009);
/* threshold2D */
reg_w(dev, 0x04, 0x21, 0x000a);
/* quantization */
reg_w(dev, 0x04, 0x00, 0x000b);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
cam = &gspca_dev->cam;
cam->dev_name = (char *) id->driver_info;
cam->epaddr = 0x01;
cam->cam_mode = vga_mode;
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
sd->hue = sd_ctrls[SD_HUE].qctrl.default_value;
return 0;
}
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
reg_w(dev, 0x03, 0x00, 0x0004);
reg_w(dev, 0x03, 0xFF, 0x0003);
reg_w(dev, 0x03, 0x00, 0x0000);
reg_w(dev, 0x03, 0x1c, 0x0001);
reg_w(dev, 0x03, 0x18, 0x0001);
/* Init on PAL and composite input0 */
spca506_SetNormeInput(gspca_dev, 0, 0);
reg_w(dev, 0x03, 0x1c, 0x0001);
reg_w(dev, 0x03, 0x18, 0x0001);
reg_w(dev, 0x05, 0x00, 0x0000);
reg_w(dev, 0x05, 0xef, 0x0001);
reg_w(dev, 0x05, 0x00, 0x00c1);
reg_w(dev, 0x05, 0x00, 0x00c2);
reg_w(dev, 0x06, 0x18, 0x0002);
reg_w(dev, 0x06, 0xf5, 0x0011);
reg_w(dev, 0x06, 0x02, 0x0012);
reg_w(dev, 0x06, 0xfb, 0x0013);
reg_w(dev, 0x06, 0x00, 0x0014);
reg_w(dev, 0x06, 0xa4, 0x0051);
reg_w(dev, 0x06, 0x40, 0x0052);
reg_w(dev, 0x06, 0x71, 0x0053);
reg_w(dev, 0x06, 0x40, 0x0054);
/************************************************/
reg_w(dev, 0x03, 0x00, 0x0004);
reg_w(dev, 0x03, 0x00, 0x0003);
reg_w(dev, 0x03, 0x00, 0x0004);
reg_w(dev, 0x03, 0xFF, 0x0003);
reg_w(dev, 0x02, 0x00, 0x0000);
reg_w(dev, 0x03, 0x60, 0x0000);
reg_w(dev, 0x03, 0x18, 0x0001);
/* for a better reading mx :) */
/*sdca506_WriteI2c(value,register) */
spca506_Initi2c(gspca_dev);
spca506_WriteI2c(gspca_dev, 0x08, 0x01);
spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
/* input composite video */
spca506_WriteI2c(gspca_dev, 0x33, 0x03);
spca506_WriteI2c(gspca_dev, 0x00, 0x04);
spca506_WriteI2c(gspca_dev, 0x00, 0x05);
spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
spca506_WriteI2c(gspca_dev, 0x98, 0x08);
spca506_WriteI2c(gspca_dev, 0x03, 0x09);
spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */
spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
spca506_WriteI2c(gspca_dev, 0x00, 0x10);
spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
spca506_WriteI2c(gspca_dev, 0x01, 0x13);
spca506_WriteI2c(gspca_dev, 0x00, 0x14);
spca506_WriteI2c(gspca_dev, 0x00, 0x15);
spca506_WriteI2c(gspca_dev, 0x00, 0x16);
spca506_WriteI2c(gspca_dev, 0x00, 0x17);
spca506_WriteI2c(gspca_dev, 0x00, 0x18);
spca506_WriteI2c(gspca_dev, 0x00, 0x19);
spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
spca506_WriteI2c(gspca_dev, 0x02, 0x40);
spca506_WriteI2c(gspca_dev, 0xff, 0x41);
spca506_WriteI2c(gspca_dev, 0xff, 0x42);
spca506_WriteI2c(gspca_dev, 0xff, 0x43);
spca506_WriteI2c(gspca_dev, 0xff, 0x44);
spca506_WriteI2c(gspca_dev, 0xff, 0x45);
spca506_WriteI2c(gspca_dev, 0xff, 0x46);
spca506_WriteI2c(gspca_dev, 0xff, 0x47);
spca506_WriteI2c(gspca_dev, 0xff, 0x48);
spca506_WriteI2c(gspca_dev, 0xff, 0x49);
spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
spca506_WriteI2c(gspca_dev, 0xff, 0x50);
spca506_WriteI2c(gspca_dev, 0xff, 0x51);
spca506_WriteI2c(gspca_dev, 0xff, 0x52);
spca506_WriteI2c(gspca_dev, 0xff, 0x53);
spca506_WriteI2c(gspca_dev, 0xff, 0x54);
spca506_WriteI2c(gspca_dev, 0xff, 0x55);
spca506_WriteI2c(gspca_dev, 0xff, 0x56);
spca506_WriteI2c(gspca_dev, 0xff, 0x57);
spca506_WriteI2c(gspca_dev, 0x00, 0x58);
spca506_WriteI2c(gspca_dev, 0x54, 0x59);
spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
spca506_WriteI2c(gspca_dev, 0x00, 0x60);
spca506_WriteI2c(gspca_dev, 0x05, 0x61);
spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
PDEBUG(D_STREAM, "** Close Init *");
return 0;
}
static void sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u16 norme;
__u16 channel;
__u8 Data[2];
/**************************************/
reg_w(dev, 0x03, 0x00, 0x0004);
reg_w(dev, 0x03, 0x00, 0x0003);
reg_w(dev, 0x03, 0x00, 0x0004);
reg_w(dev, 0x03, 0xFF, 0x0003);
reg_w(dev, 0x02, 0x00, 0x0000);
reg_w(dev, 0x03, 0x60, 0x0000);
reg_w(dev, 0x03, 0x18, 0x0001);
/*sdca506_WriteI2c(value,register) */
spca506_Initi2c(gspca_dev);
spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */
/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
spca506_WriteI2c(gspca_dev, 0x33, 0x03);
/* Analog Input Control 2 */
spca506_WriteI2c(gspca_dev, 0x00, 0x04);
/* Analog Input Control 3 */
spca506_WriteI2c(gspca_dev, 0x00, 0x05);
/* Analog Input Control 4 */
spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
/* Horizontal Sync Start 0xe9-0x0d */
spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
/* Horizontal Sync Stop 0x0d-0xf0 */
spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */
/* Defaults value */
spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */
spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
/* Luminance Brightness */
spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */
spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
/* Chrominance Saturation */
spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
/* Chrominance Hue Control */
spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
/* Chrominance Gain Control */
/**************************************/
spca506_WriteI2c(gspca_dev, 0x00, 0x10);
/* Format/Delay Control */
spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */
spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */
spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */
spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */
spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */
spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */
spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */
spca506_WriteI2c(gspca_dev, 0x00, 0x18);
spca506_WriteI2c(gspca_dev, 0x00, 0x19);
spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
spca506_WriteI2c(gspca_dev, 0x02, 0x40);
spca506_WriteI2c(gspca_dev, 0xff, 0x41);
spca506_WriteI2c(gspca_dev, 0xff, 0x42);
spca506_WriteI2c(gspca_dev, 0xff, 0x43);
spca506_WriteI2c(gspca_dev, 0xff, 0x44);
spca506_WriteI2c(gspca_dev, 0xff, 0x45);
spca506_WriteI2c(gspca_dev, 0xff, 0x46);
spca506_WriteI2c(gspca_dev, 0xff, 0x47);
spca506_WriteI2c(gspca_dev, 0xff, 0x48);
spca506_WriteI2c(gspca_dev, 0xff, 0x49);
spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
spca506_WriteI2c(gspca_dev, 0xff, 0x50);
spca506_WriteI2c(gspca_dev, 0xff, 0x51);
spca506_WriteI2c(gspca_dev, 0xff, 0x52);
spca506_WriteI2c(gspca_dev, 0xff, 0x53);
spca506_WriteI2c(gspca_dev, 0xff, 0x54);
spca506_WriteI2c(gspca_dev, 0xff, 0x55);
spca506_WriteI2c(gspca_dev, 0xff, 0x56);
spca506_WriteI2c(gspca_dev, 0xff, 0x57);
spca506_WriteI2c(gspca_dev, 0x00, 0x58);
spca506_WriteI2c(gspca_dev, 0x54, 0x59);
spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
spca506_WriteI2c(gspca_dev, 0x00, 0x60);
spca506_WriteI2c(gspca_dev, 0x05, 0x61);
spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
/**************************************/
reg_w(dev, 0x05, 0x00, 0x0003);
reg_w(dev, 0x05, 0x00, 0x0004);
reg_w(dev, 0x03, 0x10, 0x0001);
reg_w(dev, 0x03, 0x78, 0x0000);
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
case 0:
spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
break;
case 1:
spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
break;
case 2:
spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
break;
case 4:
spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
break;
default:
/* case 5: */
spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
break;
}
/* compress setting and size */
/* set i2c luma */
reg_w(dev, 0x02, 0x01, 0x0000);
reg_w(dev, 0x03, 0x12, 0x000);
reg_r(dev, 0x04, 0x0001, Data, 2);
PDEBUG(D_STREAM, "webcam started");
spca506_GetNormeInput(gspca_dev, &norme, &channel);
spca506_SetNormeInput(gspca_dev, norme, channel);
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
reg_w(dev, 0x02, 0x00, 0x0000);
reg_w(dev, 0x03, 0x00, 0x0004);
reg_w(dev, 0x03, 0x00, 0x0003);
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
}
static void sd_close(struct gspca_dev *gspca_dev)
{
}
/* convert YYUV per line to YUYV (YUV 4:2:2) */
static void yyuv_decode(unsigned char *out,
unsigned char *in,
int width,
int height)
{
unsigned char *Ui, *Vi, *yi, *yi1;
unsigned char *out1;
int i, j;
yi = in;
for (i = height / 2; --i >= 0; ) {
out1 = out + width * 2; /* next line */
yi1 = yi + width;
Ui = yi1 + width;
Vi = Ui + width / 2;
for (j = width / 2; --j >= 0; ) {
*out++ = 128 + *yi++;
*out++ = 128 + *Ui;
*out++ = 128 + *yi++;
*out++ = 128 + *Vi;
*out1++ = 128 + *yi1++;
*out1++ = 128 + *Ui++;
*out1++ = 128 + *yi1++;
*out1++ = 128 + *Vi++;
}
yi += width * 2;
out = out1;
}
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
unsigned char *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
switch (data[0]) {
case 0: /* start of frame */
if (gspca_dev->last_packet_type == FIRST_PACKET) {
yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
gspca_dev->width,
gspca_dev->height);
frame = gspca_frame_add(gspca_dev,
LAST_PACKET,
frame,
sd->tmpbuf2,
gspca_dev->width
* gspca_dev->height
* 2);
}
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
data, 0);
data += SPCA50X_OFFSET_DATA;
len -= SPCA50X_OFFSET_DATA;
if (len > 0)
memcpy(sd->tmpbuf, data, len);
else
len = 0;
sd->buflen = len;
return;
case 0xff: /* drop */
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
return;
}
data += 1;
len -= 1;
memcpy(&sd->tmpbuf[sd->buflen], data, len);
sd->buflen += len;
}
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
spca506_Initi2c(gspca_dev);
spca506_WriteI2c(gspca_dev, sd->brightness, SAA7113_bright);
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
}
static void getbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = spca506_ReadI2c(gspca_dev, SAA7113_bright);
}
static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
spca506_Initi2c(gspca_dev);
spca506_WriteI2c(gspca_dev, sd->contrast, SAA7113_contrast);
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
}
static void getcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = spca506_ReadI2c(gspca_dev, SAA7113_contrast);
}
static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
spca506_Initi2c(gspca_dev);
spca506_WriteI2c(gspca_dev, sd->colors, SAA7113_saturation);
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
}
static void getcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->colors = spca506_ReadI2c(gspca_dev, SAA7113_saturation);
}
static void sethue(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
spca506_Initi2c(gspca_dev);
spca506_WriteI2c(gspca_dev, sd->hue, SAA7113_hue);
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
}
static void gethue(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->hue = spca506_ReadI2c(gspca_dev, SAA7113_hue);
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming)
setbrightness(gspca_dev);
return 0;
}
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
if (gspca_dev->streaming)
setcontrast(gspca_dev);
return 0;
}
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
getcontrast(gspca_dev);
*val = sd->contrast;
return 0;
}
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->colors = val;
if (gspca_dev->streaming)
setcolors(gspca_dev);
return 0;
}
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
getcolors(gspca_dev);
*val = sd->colors;
return 0;
}
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->hue = val;
if (gspca_dev->streaming)
sethue(gspca_dev);
return 0;
}
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
gethue(gspca_dev);
*val = sd->hue;
return 0;
}
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.open = sd_open,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
#define DVNM(name) .driver_info = (kernel_ulong_t) name
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x06e1, 0xa190), DVNM("ADS Instant VCD")},
/* {USB_DEVICE(0x0733, 0x0430), DVNM("UsbGrabber PV321c")}, */
{USB_DEVICE(0x0734, 0x043b), DVNM("3DeMon USB Capture aka")},
{USB_DEVICE(0x99fa, 0x8988), DVNM("Grandtec V.cap")},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
};
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
if (usb_register(&sd_driver) < 0)
return -1;
PDEBUG(D_PROBE, "v%s registered", version);
return 0;
}
static void __exit sd_mod_exit(void)
{
usb_deregister(&sd_driver);
PDEBUG(D_PROBE, "deregistered");
}
module_init(sd_mod_init);
module_exit(sd_mod_exit);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -23,8 +23,8 @@
#include "gspca.h"
#include "jpeg.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 7)
static const char version[] = "0.2.7";
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
@ -37,10 +37,10 @@ struct sd {
unsigned char brightness;
unsigned char contrast;
unsigned char colors;
unsigned char lightfreq;
};
/* global parameters */
static int lightfreq = 50;
static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */
/* V4L2 controls supported by the driver */
@ -50,6 +50,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define SD_BRIGHTNESS 0
@ -94,6 +96,20 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setcolors,
.get = sd_getcolors,
},
#define SD_FREQ 3
{
{
.id = V4L2_CID_POWER_LINE_FREQUENCY,
.type = V4L2_CTRL_TYPE_MENU,
.name = "Light frequency filter",
.minimum = 1,
.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
.step = 1,
.default_value = 1,
},
.set = sd_setfreq,
.get = sd_getfreq,
},
};
static struct cam_mode vga_mode[] = {
@ -102,11 +118,11 @@ static struct cam_mode vga_mode[] = {
};
/* -- read a register -- */
static int reg_read(struct gspca_dev *gspca_dev,
static int reg_r(struct gspca_dev *gspca_dev,
__u16 index, __u8 *buf)
{
int ret;
struct usb_device *dev = gspca_dev->dev;
int ret;
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
0x00,
@ -116,12 +132,12 @@ static int reg_read(struct gspca_dev *gspca_dev,
buf, 1,
500);
if (ret < 0)
PDEBUG(D_ERR, "reg_read err %d", ret);
PDEBUG(D_ERR, "reg_r err %d", ret);
return ret;
}
/* -- write a register -- */
static int reg_write(struct gspca_dev *gspca_dev,
static int reg_w(struct gspca_dev *gspca_dev,
__u16 index, __u16 value)
{
struct usb_device *dev = gspca_dev->dev;
@ -136,7 +152,7 @@ static int reg_write(struct gspca_dev *gspca_dev,
0,
500);
if (ret < 0)
PDEBUG(D_ERR, "reg_write err %d", ret);
PDEBUG(D_ERR, "reg_w err %d", ret);
return ret;
}
@ -149,15 +165,15 @@ static int rcv_val(struct gspca_dev *gspca_dev,
int alen, ret;
unsigned char bulk_buf[4];
reg_write(gspca_dev, 0x634, (ads >> 16) & 0xff);
reg_write(gspca_dev, 0x635, (ads >> 8) & 0xff);
reg_write(gspca_dev, 0x636, ads & 0xff);
reg_write(gspca_dev, 0x637, 0);
reg_write(gspca_dev, 0x638, len & 0xff);
reg_write(gspca_dev, 0x639, len >> 8);
reg_write(gspca_dev, 0x63a, 0);
reg_write(gspca_dev, 0x63b, 0);
reg_write(gspca_dev, 0x630, 5);
reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
reg_w(gspca_dev, 0x636, ads & 0xff);
reg_w(gspca_dev, 0x637, 0);
reg_w(gspca_dev, 0x638, len & 0xff);
reg_w(gspca_dev, 0x639, len >> 8);
reg_w(gspca_dev, 0x63a, 0);
reg_w(gspca_dev, 0x63b, 0);
reg_w(gspca_dev, 0x630, 5);
if (len > sizeof bulk_buf)
return -1;
ret = usb_bulk_msg(dev,
@ -180,26 +196,26 @@ static int snd_val(struct gspca_dev *gspca_dev,
unsigned char bulk_buf[4];
if (ads == 0x003f08) {
ret = reg_read(gspca_dev, 0x0704, &value);
ret = reg_r(gspca_dev, 0x0704, &value);
if (ret < 0)
goto ko;
ret = reg_read(gspca_dev, 0x0705, &seq);
ret = reg_r(gspca_dev, 0x0705, &seq);
if (ret < 0)
goto ko;
ret = reg_read(gspca_dev, 0x0650, &value);
ret = reg_r(gspca_dev, 0x0650, &value);
if (ret < 0)
goto ko;
reg_write(gspca_dev, 0x654, seq);
reg_w(gspca_dev, 0x654, seq);
} else
reg_write(gspca_dev, 0x654, (ads >> 16) & 0xff);
reg_write(gspca_dev, 0x655, (ads >> 8) & 0xff);
reg_write(gspca_dev, 0x656, ads & 0xff);
reg_write(gspca_dev, 0x657, 0);
reg_write(gspca_dev, 0x658, 0x04); /* size */
reg_write(gspca_dev, 0x659, 0);
reg_write(gspca_dev, 0x65a, 0);
reg_write(gspca_dev, 0x65b, 0);
reg_write(gspca_dev, 0x650, 5);
reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
reg_w(gspca_dev, 0x656, ads & 0xff);
reg_w(gspca_dev, 0x657, 0);
reg_w(gspca_dev, 0x658, 0x04); /* size */
reg_w(gspca_dev, 0x659, 0);
reg_w(gspca_dev, 0x65a, 0);
reg_w(gspca_dev, 0x65b, 0);
reg_w(gspca_dev, 0x650, 5);
bulk_buf[0] = (val >> 24) & 0xff;
bulk_buf[1] = (val >> 16) & 0xff;
bulk_buf[2] = (val >> 8) & 0xff;
@ -215,7 +231,7 @@ static int snd_val(struct gspca_dev *gspca_dev,
if (ads == 0x003f08) {
seq += 4;
seq &= 0x3f;
reg_write(gspca_dev, 0x705, seq);
reg_w(gspca_dev, 0x705, seq);
}
return ret;
ko:
@ -235,7 +251,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
int parval;
PDEBUG(D_CONF, "brightness: %d", sd->brightness);
parval = 0x06000000 /* whiteness */
+ (sd->brightness << 16);
set_par(gspca_dev, parval);
@ -246,7 +261,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
int parval;
PDEBUG(D_CONF, "contrast: %d", sd->contrast);
parval = 0x07000000 /* contrast */
+ (sd->contrast << 16);
set_par(gspca_dev, parval);
@ -257,13 +271,20 @@ static void setcolors(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
int parval;
PDEBUG(D_CONF, "saturation: %d",
sd->colors);
parval = 0x08000000 /* saturation */
+ (sd->colors << 16);
set_par(gspca_dev, parval);
}
static void setfreq(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
set_par(gspca_dev, sd->lightfreq == 1
? 0x33640000 /* 50 Hz */
: 0x33780000); /* 60 Hz */
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
@ -278,6 +299,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
return 0;
}
@ -289,7 +311,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
/* check if the device responds */
usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
ret = reg_read(gspca_dev, 0x0740, &value);
ret = reg_r(gspca_dev, 0x0740, &value);
if (ret < 0)
return ret;
if (value != 0xff) {
@ -320,21 +342,24 @@ static void sd_start(struct gspca_dev *gspca_dev)
ret = usb_set_interface(gspca_dev->dev,
gspca_dev->iface,
gspca_dev->alt);
if (ret < 0)
if (ret < 0) {
PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed",
gspca_dev->iface, gspca_dev->alt);
goto out;
ret = reg_read(gspca_dev, 0x0630, &dum);
}
ret = reg_r(gspca_dev, 0x0630, &dum);
if (ret < 0)
goto out;
rcv_val(gspca_dev, 0x000020, 4); /* << (value ff ff ff ff) */
ret = reg_read(gspca_dev, 0x0650, &dum);
ret = reg_r(gspca_dev, 0x0650, &dum);
if (ret < 0)
goto out;
snd_val(gspca_dev, 0x000020, 0xffffffff);
reg_write(gspca_dev, 0x0620, 0);
reg_write(gspca_dev, 0x0630, 0);
reg_write(gspca_dev, 0x0640, 0);
reg_write(gspca_dev, 0x0650, 0);
reg_write(gspca_dev, 0x0660, 0);
reg_w(gspca_dev, 0x0620, 0);
reg_w(gspca_dev, 0x0630, 0);
reg_w(gspca_dev, 0x0640, 0);
reg_w(gspca_dev, 0x0650, 0);
reg_w(gspca_dev, 0x0660, 0);
setbrightness(gspca_dev); /* whiteness */
setcontrast(gspca_dev); /* contrast */
setcolors(gspca_dev); /* saturation */
@ -342,9 +367,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
set_par(gspca_dev, 0x0a800000); /* Green ? */
set_par(gspca_dev, 0x0b800000); /* Blue ? */
set_par(gspca_dev, 0x0d030000); /* Gamma ? */
set_par(gspca_dev, lightfreq == 60
? 0x33780000 /* 60 Hz */
: 0x33640000); /* 50 Hz */
setfreq(gspca_dev); /* light frequency */
/* start the video flow */
set_par(gspca_dev, 0x01000000);
@ -363,15 +386,15 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
set_par(gspca_dev, 0x02000000);
set_par(gspca_dev, 0x02000000);
usb_set_interface(dev, gspca_dev->iface, 1);
reg_read(gspca_dev, 0x0630, &value);
reg_r(gspca_dev, 0x0630, &value);
rcv_val(gspca_dev, 0x000020, 4); /* << (value ff ff ff ff) */
reg_read(gspca_dev, 0x0650, &value);
reg_r(gspca_dev, 0x0650, &value);
snd_val(gspca_dev, 0x000020, 0xffffffff);
reg_write(gspca_dev, 0x0620, 0);
reg_write(gspca_dev, 0x0630, 0);
reg_write(gspca_dev, 0x0640, 0);
reg_write(gspca_dev, 0x0650, 0);
reg_write(gspca_dev, 0x0660, 0);
reg_w(gspca_dev, 0x0620, 0);
reg_w(gspca_dev, 0x0630, 0);
reg_w(gspca_dev, 0x0640, 0);
reg_w(gspca_dev, 0x0650, 0);
reg_w(gspca_dev, 0x0660, 0);
PDEBUG(D_STREAM, "camera stopped");
}
@ -470,6 +493,42 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->lightfreq = val;
if (gspca_dev->streaming)
setfreq(gspca_dev);
return 0;
}
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->lightfreq;
return 0;
}
static int sd_querymenu(struct gspca_dev *gspca_dev,
struct v4l2_querymenu *menu)
{
switch (menu->id) {
case V4L2_CID_POWER_LINE_FREQUENCY:
switch (menu->index) {
case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
strcpy(menu->name, "50 Hz");
return 0;
case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
strcpy(menu->name, "60 Hz");
return 0;
}
break;
}
return -EINVAL;
}
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
@ -482,6 +541,7 @@ static struct sd_desc sd_desc = {
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
};
/* -- module initialisation -- */
@ -524,7 +584,5 @@ static void __exit sd_mod_exit(void)
module_init(sd_mod_init);
module_exit(sd_mod_exit);
module_param(lightfreq, int, 0644);
MODULE_PARM_DESC(lightfreq, "Light frequency 50 or 60 Hz");
module_param_named(quant, sd_quant, int, 0644);
MODULE_PARM_DESC(quant, "Quantization index (0..8)");

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,709 @@
/*
* Quickcam cameras initialization data
*
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define MODULE_NAME "tv8532"
#include "gspca.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
static const char version[] = "2.1.0";
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("TV8532 USB Camera Driver");
MODULE_LICENSE("GPL");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
int buflen; /* current length of tmpbuf */
__u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */
__u8 tmpbuf2[352 * 288]; /* no protection... */
unsigned short brightness;
unsigned short contrast;
char packet;
char synchro;
};
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 1,
.maximum = 0x2ff,
.step = 1,
.default_value = 0x18f,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
#define SD_CONTRAST 1
{
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
.maximum = 0xffff,
.step = 1,
.default_value = 0x7fff,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
},
};
static struct cam_mode sif_mode[] = {
{V4L2_PIX_FMT_SBGGR8, 176, 144, 1},
{V4L2_PIX_FMT_SBGGR8, 352, 288, 0},
};
/*
* Initialization data: this is the first set-up data written to the
* device (before the open data).
*/
#define TESTCLK 0x10 /* reg 0x2c -> 0x12 //10 */
#define TESTCOMP 0x90 /* reg 0x28 -> 0x80 */
#define TESTLINE 0x81 /* reg 0x29 -> 0x81 */
#define QCIFLINE 0x41 /* reg 0x29 -> 0x81 */
#define TESTPTL 0x14 /* reg 0x2D -> 0x14 */
#define TESTPTH 0x01 /* reg 0x2E -> 0x01 */
#define TESTPTBL 0x12 /* reg 0x2F -> 0x0a */
#define TESTPTBH 0x01 /* reg 0x30 -> 0x01 */
#define ADWIDTHL 0xe8 /* reg 0x0c -> 0xe8 */
#define ADWIDTHH 0x03 /* reg 0x0d -> 0x03 */
#define ADHEIGHL 0x90 /* reg 0x0e -> 0x91 //93 */
#define ADHEIGHH 0x01 /* reg 0x0f -> 0x01 */
#define EXPOL 0x8f /* reg 0x1c -> 0x8f */
#define EXPOH 0x01 /* reg 0x1d -> 0x01 */
#define ADCBEGINL 0x44 /* reg 0x10 -> 0x46 //47 */
#define ADCBEGINH 0x00 /* reg 0x11 -> 0x00 */
#define ADRBEGINL 0x0a /* reg 0x14 -> 0x0b //0x0c */
#define ADRBEGINH 0x00 /* reg 0x15 -> 0x00 */
#define TV8532_CMD_UPDATE 0x84
#define TV8532_EEprom_Add 0x03
#define TV8532_EEprom_DataL 0x04
#define TV8532_EEprom_DataM 0x05
#define TV8532_EEprom_DataH 0x06
#define TV8532_EEprom_TableLength 0x07
#define TV8532_EEprom_Write 0x08
#define TV8532_PART_CTRL 0x00
#define TV8532_CTRL 0x01
#define TV8532_CMD_EEprom_Open 0x30
#define TV8532_CMD_EEprom_Close 0x29
#define TV8532_UDP_UPDATE 0x31
#define TV8532_GPIO 0x39
#define TV8532_GPIO_OE 0x3B
#define TV8532_REQ_RegWrite 0x02
#define TV8532_REQ_RegRead 0x03
#define TV8532_ADWIDTH_L 0x0C
#define TV8532_ADWIDTH_H 0x0D
#define TV8532_ADHEIGHT_L 0x0E
#define TV8532_ADHEIGHT_H 0x0F
#define TV8532_EXPOSURE 0x1C
#define TV8532_QUANT_COMP 0x28
#define TV8532_MODE_PACKET 0x29
#define TV8532_SETCLK 0x2C
#define TV8532_POINT_L 0x2D
#define TV8532_POINT_H 0x2E
#define TV8532_POINTB_L 0x2F
#define TV8532_POINTB_H 0x30
#define TV8532_BUDGET_L 0x2A
#define TV8532_BUDGET_H 0x2B
#define TV8532_VID_L 0x34
#define TV8532_VID_H 0x35
#define TV8532_PID_L 0x36
#define TV8532_PID_H 0x37
#define TV8532_DeviceID 0x83
#define TV8532_AD_SLOPE 0x91
#define TV8532_AD_BITCTRL 0x94
#define TV8532_AD_COLBEGIN_L 0x10
#define TV8532_AD_COLBEGIN_H 0x11
#define TV8532_AD_ROWBEGIN_L 0x14
#define TV8532_AD_ROWBEGIN_H 0x15
static __u32 tv_8532_eeprom_data[] = {
/* add dataL dataM dataH */
0x00010001, 0x01018011, 0x02050014, 0x0305001c,
0x040d001e, 0x0505001f, 0x06050519, 0x0705011b,
0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9,
0x0c0509f1, 0
};
static void reg_r(struct usb_device *dev,
__u16 index, __u8 *buffer)
{
usb_control_msg(dev,
usb_rcvctrlpipe(dev, 0),
TV8532_REQ_RegRead,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, /* value */
index, buffer, sizeof(__u8),
500);
}
static void reg_w(struct usb_device *dev,
__u16 index, __u8 *buffer, __u16 length)
{
usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
TV8532_REQ_RegWrite,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, /* value */
index, buffer, length, 500);
}
static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
{
int i = 0;
__u8 reg, data0, data1, data2, datacmd;
struct usb_device *dev = gspca_dev->dev;
datacmd = 0xb0;;
reg_w(dev, TV8532_GPIO, &datacmd, 1);
datacmd = TV8532_CMD_EEprom_Open;
reg_w(dev, TV8532_CTRL, &datacmd,
1);
/* msleep(1); */
while (tv_8532_eeprom_data[i]) {
reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24;
reg_w(dev, TV8532_EEprom_Add, &reg, 1);
/* msleep(1); */
data0 = (tv_8532_eeprom_data[i] & 0x000000ff);
reg_w(dev, TV8532_EEprom_DataL, &data0, 1);
/* msleep(1); */
data1 = (tv_8532_eeprom_data[i] & 0x0000FF00) >> 8;
reg_w(dev, TV8532_EEprom_DataM, &data1, 1);
/* msleep(1); */
data2 = (tv_8532_eeprom_data[i] & 0x00FF0000) >> 16;
reg_w(dev, TV8532_EEprom_DataH, &data2, 1);
/* msleep(1); */
datacmd = 0;
reg_w(dev, TV8532_EEprom_Write, &datacmd, 1);
/* msleep(10); */
i++;
}
datacmd = i;
reg_w(dev, TV8532_EEprom_TableLength, &datacmd, 1);
/* msleep(1); */
datacmd = TV8532_CMD_EEprom_Close;
reg_w(dev, TV8532_CTRL, &datacmd, 1);
msleep(10);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
tv_8532WriteEEprom(gspca_dev);
cam = &gspca_dev->cam;
cam->dev_name = (char *) id->driver_info;
cam->epaddr = 1;
cam->cam_mode = sif_mode;
cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
return 0;
}
static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u8 data = 0;
/* __u16 vid, pid; */
reg_r(dev, 0x0001, &data);
PDEBUG(D_USBI, "register 0x01-> %x", data);
reg_r(dev, 0x0002, &data);
PDEBUG(D_USBI, "register 0x02-> %x", data);
reg_r(dev, TV8532_ADWIDTH_L, &data);
reg_r(dev, TV8532_ADWIDTH_H, &data);
reg_r(dev, TV8532_QUANT_COMP, &data);
reg_r(dev, TV8532_MODE_PACKET, &data);
reg_r(dev, TV8532_SETCLK, &data);
reg_r(dev, TV8532_POINT_L, &data);
reg_r(dev, TV8532_POINT_H, &data);
reg_r(dev, TV8532_POINTB_L, &data);
reg_r(dev, TV8532_POINTB_H, &data);
reg_r(dev, TV8532_BUDGET_L, &data);
reg_r(dev, TV8532_BUDGET_H, &data);
reg_r(dev, TV8532_VID_L, &data);
reg_r(dev, TV8532_VID_H, &data);
reg_r(dev, TV8532_PID_L, &data);
reg_r(dev, TV8532_PID_H, &data);
reg_r(dev, TV8532_DeviceID, &data);
reg_r(dev, TV8532_AD_COLBEGIN_L, &data);
reg_r(dev, TV8532_AD_COLBEGIN_H, &data);
reg_r(dev, TV8532_AD_ROWBEGIN_L, &data);
reg_r(dev, TV8532_AD_ROWBEGIN_H, &data);
}
static void tv_8532_setReg(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u8 data = 0;
__u8 value[2] = { 0, 0 };
data = ADCBEGINL;
reg_w(dev, TV8532_AD_COLBEGIN_L, &data, 1); /* 0x10 */
data = ADCBEGINH; /* also digital gain */
reg_w(dev, TV8532_AD_COLBEGIN_H, &data, 1);
data = TV8532_CMD_UPDATE;
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
data = 0x0a;
reg_w(dev, TV8532_GPIO_OE, &data, 1);
/******************************************************/
data = ADHEIGHL;
reg_w(dev, TV8532_ADHEIGHT_L, &data, 1); /* 0e */
data = ADHEIGHH;
reg_w(dev, TV8532_ADHEIGHT_H, &data, 1); /* 0f */
value[0] = EXPOL;
value[1] = EXPOH; /* 350d 0x014c; */
reg_w(dev, TV8532_EXPOSURE, value, 2); /* 1c */
data = ADCBEGINL;
reg_w(dev, TV8532_AD_COLBEGIN_L, &data, 1); /* 0x10 */
data = ADCBEGINH; /* also digital gain */
reg_w(dev, TV8532_AD_COLBEGIN_H, &data, 1);
data = ADRBEGINL;
reg_w(dev, TV8532_AD_ROWBEGIN_L, &data, 1); /* 0x14 */
data = 0x00;
reg_w(dev, TV8532_AD_SLOPE, &data, 1); /* 0x91 */
data = 0x02;
reg_w(dev, TV8532_AD_BITCTRL, &data, 1); /* 0x94 */
data = TV8532_CMD_EEprom_Close;
reg_w(dev, TV8532_CTRL, &data, 1); /* 0x01 */
data = 0x00;
reg_w(dev, TV8532_AD_SLOPE, &data, 1); /* 0x91 */
data = TV8532_CMD_UPDATE;
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
}
static void tv_8532_PollReg(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u8 data = 0;
int i;
/* strange polling from tgc */
for (i = 0; i < 10; i++) {
data = TESTCLK; /* 0x48; //0x08; */
reg_w(dev, TV8532_SETCLK, &data, 1); /* 0x2c */
data = TV8532_CMD_UPDATE;
reg_w(dev, TV8532_PART_CTRL, &data, 1);
data = 0x01;
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
}
}
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u8 data = 0;
__u8 dataStart = 0;
__u8 value[2] = { 0, 0 };
data = 0x32;
reg_w(dev, TV8532_AD_SLOPE, &data, 1);
data = 0;
reg_w(dev, TV8532_AD_BITCTRL, &data, 1);
tv_8532ReadRegisters(gspca_dev);
data = 0x0b;
reg_w(dev, TV8532_GPIO_OE, &data, 1);
value[0] = ADHEIGHL;
value[1] = ADHEIGHH; /* 401d 0x0169; */
reg_w(dev, TV8532_ADHEIGHT_L, value, 2); /* 0e */
value[0] = EXPOL;
value[1] = EXPOH; /* 350d 0x014c; */
reg_w(dev, TV8532_EXPOSURE, value, 2); /* 1c */
data = ADWIDTHL; /* 0x20; */
reg_w(dev, TV8532_ADWIDTH_L, &data, 1); /* 0x0c */
data = ADWIDTHH;
reg_w(dev, TV8532_ADWIDTH_H, &data, 1); /* 0x0d */
/*******************************************************************/
data = TESTCOMP; /* 0x72 compressed mode */
reg_w(dev, TV8532_QUANT_COMP, &data, 1); /* 0x28 */
data = TESTLINE; /* 0x84; // CIF | 4 packet */
reg_w(dev, TV8532_MODE_PACKET, &data, 1); /* 0x29 */
/************************************************/
data = TESTCLK; /* 0x48; //0x08; */
reg_w(dev, TV8532_SETCLK, &data, 1); /* 0x2c */
data = TESTPTL; /* 0x38; */
reg_w(dev, TV8532_POINT_L, &data, 1); /* 0x2d */
data = TESTPTH; /* 0x04; */
reg_w(dev, TV8532_POINT_H, &data, 1); /* 0x2e */
dataStart = TESTPTBL; /* 0x04; */
reg_w(dev, TV8532_POINTB_L, &dataStart, 1); /* 0x2f */
data = TESTPTBH; /* 0x04; */
reg_w(dev, TV8532_POINTB_H, &data, 1); /* 0x30 */
data = TV8532_CMD_UPDATE;
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
/*************************************************/
data = 0x01;
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
msleep(200);
data = 0x00;
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
/*************************************************/
tv_8532_setReg(gspca_dev);
/*************************************************/
data = 0x0b;
reg_w(dev, TV8532_GPIO_OE, &data,
1);
/*************************************************/
tv_8532_setReg(gspca_dev);
/*************************************************/
tv_8532_PollReg(gspca_dev);
return 0;
}
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u8 value[2];
__u8 data;
int brightness = sd->brightness;
value[1] = (brightness >> 8) & 0xff;
value[0] = (brightness) & 0xff;
reg_w(gspca_dev->dev, TV8532_EXPOSURE, value, 2); /* 1c */
data = TV8532_CMD_UPDATE;
reg_w(gspca_dev->dev, TV8532_PART_CTRL, &data, 1);
}
/* -- start the camera -- */
static void sd_start(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u8 data = 0;
__u8 dataStart = 0;
__u8 value[2];
data = 0x32;
reg_w(dev, TV8532_AD_SLOPE, &data, 1);
data = 0;
reg_w(dev, TV8532_AD_BITCTRL, &data, 1);
tv_8532ReadRegisters(gspca_dev);
data = 0x0b;
reg_w(dev, TV8532_GPIO_OE, &data, 1);
value[0] = ADHEIGHL;
value[1] = ADHEIGHH; /* 401d 0x0169; */
reg_w(dev, TV8532_ADHEIGHT_L, value, 2); /* 0e */
/* value[0] = EXPOL; value[1] =EXPOH; * 350d 0x014c; */
/* reg_w(dev,TV8532_REQ_RegWrite,0,TV8532_EXPOSURE,value,2); * 1c */
setbrightness(gspca_dev);
data = ADWIDTHL; /* 0x20; */
reg_w(dev, TV8532_ADWIDTH_L, &data, 1); /* 0x0c */
data = ADWIDTHH;
reg_w(dev, TV8532_ADWIDTH_H, &data, 1); /* 0x0d */
/************************************************/
data = TESTCOMP; /* 0x72 compressed mode */
reg_w(dev, TV8532_QUANT_COMP, &data, 1); /* 0x28 */
if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
/* 176x144 */
data = QCIFLINE; /* 0x84; // CIF | 4 packet */
reg_w(dev, TV8532_MODE_PACKET, &data, 1); /* 0x29 */
} else {
/* 352x288 */
data = TESTLINE; /* 0x84; // CIF | 4 packet */
reg_w(dev, TV8532_MODE_PACKET, &data, 1); /* 0x29 */
}
/************************************************/
data = TESTCLK; /* 0x48; //0x08; */
reg_w(dev, TV8532_SETCLK, &data, 1); /* 0x2c */
data = TESTPTL; /* 0x38; */
reg_w(dev, TV8532_POINT_L, &data, 1); /* 0x2d */
data = TESTPTH; /* 0x04; */
reg_w(dev, TV8532_POINT_H, &data, 1); /* 0x2e */
dataStart = TESTPTBL; /* 0x04; */
reg_w(dev, TV8532_POINTB_L, &dataStart, 1); /* 0x2f */
data = TESTPTBH; /* 0x04; */
reg_w(dev, TV8532_POINTB_H, &data, 1); /* 0x30 */
data = TV8532_CMD_UPDATE;
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
/************************************************/
data = 0x01;
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
msleep(200);
data = 0x00;
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
/************************************************/
tv_8532_setReg(gspca_dev);
/************************************************/
data = 0x0b;
reg_w(dev, TV8532_GPIO_OE, &data, 1);
/************************************************/
tv_8532_setReg(gspca_dev);
/************************************************/
tv_8532_PollReg(gspca_dev);
data = 0x00;
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
__u8 data;
data = 0x0b;
reg_w(dev, TV8532_GPIO_OE, &data, 1);
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
}
static void sd_close(struct gspca_dev *gspca_dev)
{
}
static void tv8532_preprocess(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
/* we should received a whole frame with header and EOL marker
* in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2
* sequence 2bytes header the Alternate pixels bayer GB 4 bytes
* Alternate pixels bayer RG 4 bytes EOL */
int width = gspca_dev->width;
int height = gspca_dev->height;
unsigned char *dst = sd->tmpbuf2;
unsigned char *data = sd->tmpbuf;
int i;
/* precompute where is the good bayer line */
if (((data[3] + data[width + 7]) >> 1)
+ (data[4] >> 2)
+ (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
+ (data[3] >> 2)
+ (data[width + 5] >> 1))
data += 3;
else
data += 2;
for (i = 0; i < height / 2; i++) {
memcpy(dst, data, width);
data += width + 3;
dst += width;
memcpy(dst, data, width);
data += width + 7;
dst += width;
}
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
if (data[0] != 0x80) {
sd->packet++;
if (sd->buflen + len > sizeof sd->tmpbuf) {
if (gspca_dev->last_packet_type != DISCARD_PACKET) {
PDEBUG(D_PACK, "buffer overflow");
gspca_dev->last_packet_type = DISCARD_PACKET;
}
return;
}
memcpy(&sd->tmpbuf[sd->buflen], data, len);
sd->buflen += len;
return;
}
/* here we detect 0x80 */
/* counter is limited so we need few header for a frame :) */
/* header 0x80 0x80 0x80 0x80 0x80 */
/* packet 00 63 127 145 00 */
/* sof 0 1 1 0 0 */
/* update sequence */
if (sd->packet == 63 || sd->packet == 127)
sd->synchro = 1;
/* is there a frame start ? */
if (sd->packet >= (gspca_dev->height >> 1) - 1) {
PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro,
sd->packet);
if (!sd->synchro) { /* start of frame */
if (gspca_dev->last_packet_type == FIRST_PACKET) {
tv8532_preprocess(gspca_dev);
frame = gspca_frame_add(gspca_dev,
LAST_PACKET,
frame, sd->tmpbuf2,
gspca_dev->width *
gspca_dev->width);
}
gspca_frame_add(gspca_dev, FIRST_PACKET,
frame, data, 0);
memcpy(sd->tmpbuf, data, len);
sd->buflen = len;
sd->packet = 0;
return;
}
if (gspca_dev->last_packet_type != DISCARD_PACKET) {
PDEBUG(D_PACK,
"Warning wrong TV8532 frame detection %d",
sd->packet);
gspca_dev->last_packet_type = DISCARD_PACKET;
}
return;
}
if (!sd->synchro) {
/* Drop packet frame corrupt */
PDEBUG(D_PACK, "DROP SOF %d packet %d",
sd->synchro, sd->packet);
sd->packet = 0;
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
sd->synchro = 1;
sd->packet++;
memcpy(&sd->tmpbuf[sd->buflen], data, len);
sd->buflen += len;
}
static void setcontrast(struct gspca_dev *gspca_dev)
{
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming)
setbrightness(gspca_dev);
return 0;
}
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->brightness;
return 0;
}
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
if (gspca_dev->streaming)
setcontrast(gspca_dev);
return 0;
}
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->contrast;
return 0;
}
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.open = sd_open,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.close = sd_close,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
#define DVNM(name) .driver_info = (kernel_ulong_t) name
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x046d, 0x0920), DVNM("QC Express")},
{USB_DEVICE(0x046d, 0x0921), DVNM("Labtec Webcam")},
{USB_DEVICE(0x0545, 0x808b), DVNM("Veo Stingray")},
{USB_DEVICE(0x0545, 0x8333), DVNM("Veo Stingray")},
{USB_DEVICE(0x0923, 0x010f), DVNM("ICM532 cams")},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
};
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
if (usb_register(&sd_driver) < 0)
return -1;
PDEBUG(D_PROBE, "v%s registered", version);
return 0;
}
static void __exit sd_mod_exit(void)
{
usb_deregister(&sd_driver);
PDEBUG(D_PROBE, "deregistered");
}
module_init(sd_mod_init);
module_exit(sd_mod_exit);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -324,6 +324,8 @@ struct v4l2_pix_format
#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */
#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */
#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S','5','0','1') /* YUYV per line */
#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S','5','6','1') /* compressed BGGR bayer */
/*
* F O R M A T E N U M E R A T I O N