mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
V4L/DVB (8152): Initial release of gspca with only one driver.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
8b53b39d62
commit
63eb9546dc
238
Documentation/video4linux/gspca.txt
Normal file
238
Documentation/video4linux/gspca.txt
Normal file
@ -0,0 +1,238 @@
|
||||
Here the list of the known working cameras with gspca.
|
||||
|
||||
The modules are:
|
||||
gspca_main main driver
|
||||
gspca_xxxx subdriver module with xxxx as follows
|
||||
|
||||
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
|
||||
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
|
||||
zc3xx 041e:401c Creative NX
|
||||
zc3xx 041e:401e Creative Nx Pro
|
||||
zc3xx 041e:401f Creative Webcam Notebook PD1171
|
||||
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
|
||||
zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250)
|
||||
zc3xx 041e:4053 Creative Live!Cam Video IM
|
||||
zc3xx 0458:7007 Genius VideoCam V2
|
||||
zc3xx 0458:700c Genius VideoCam V3
|
||||
zc3xx 0458:700f Genius VideoCam Web V2
|
||||
zc3xx 0461:0a00 MicroInnovation WebCam320
|
||||
zc3xx 046d:08a0 Logitech QC IM
|
||||
zc3xx 046d:08a1 Logitech QC IM 0x08A1 +sound
|
||||
zc3xx 046d:08a2 Labtec Webcam Pro
|
||||
zc3xx 046d:08a3 Logitech QC Chat
|
||||
zc3xx 046d:08a6 Logitech QCim
|
||||
zc3xx 046d:08a7 Logitech QuickCam Image
|
||||
zc3xx 046d:08a9 Logitech Notebook Deluxe
|
||||
zc3xx 046d:08aa Labtec Webcam Notebook
|
||||
zc3xx 046d:08ac Logitech QuickCam Cool
|
||||
zc3xx 046d:08ad Logitech QCCommunicate STX
|
||||
zc3xx 046d:08ae Logitech QuickCam for Notebooks
|
||||
zc3xx 046d:08af Logitech QuickCam Cool
|
||||
zc3xx 046d:08b9 Logitech QC IM ???
|
||||
zc3xx 046d:08d7 Logitech QCam STX
|
||||
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
|
||||
zc3xx 0471:0325 Philips SPC 200 NC
|
||||
zc3xx 0471:0326 Philips SPC 300 NC
|
||||
zc3xx 0471:032d Philips spc210nc
|
||||
zc3xx 0471:032e Philips spc315nc
|
||||
zc3xx 055f:c005 Mustek Wcam300A
|
||||
zc3xx 055f:d003 Mustek WCam300A
|
||||
zc3xx 055f:d004 Mustek WCam300 AN
|
||||
zc3xx 0698:2003 CTX M730V built in
|
||||
zc3xx 0ac8:0302 Z-star Vimicro zc0302
|
||||
zc3xx 0ac8:301b Z-Star zc301b
|
||||
zc3xx 0ac8:303b Vimicro 0x303b
|
||||
zc3xx 0ac8:305b Z-star Vimicro zc0305b
|
||||
zc3xx 0ac8:307b Ldlc VC302+Ov7620
|
||||
zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128
|
||||
zc3xx 10fd:8050 Typhoon Webshot II USB 300k
|
@ -801,6 +801,8 @@ config USB_VIDEO_CLASS
|
||||
|
||||
For more information see: <http://linux-uvc.berlios.de/>
|
||||
|
||||
source "drivers/media/video/gspca/Kconfig"
|
||||
|
||||
source "drivers/media/video/pvrusb2/Kconfig"
|
||||
|
||||
source "drivers/media/video/em28xx/Kconfig"
|
||||
|
13
drivers/media/video/gspca/Kconfig
Normal file
13
drivers/media/video/gspca/Kconfig
Normal file
@ -0,0 +1,13 @@
|
||||
config USB_GSPCA
|
||||
tristate "USB GSPCA driver"
|
||||
depends on VIDEO_V4L2
|
||||
---help---
|
||||
Say Y here if you want support for various USB cameras.
|
||||
|
||||
See <file:Documentation/video4linux/gspca.txt> for more info.
|
||||
|
||||
This driver uses the Video For Linux API. You must say Y or M to
|
||||
"Video For Linux" to use this driver.
|
||||
|
||||
To compile this driver as modules, choose M here: the
|
||||
modules will be called gspca_xxxx.
|
4
drivers/media/video/gspca/Makefile
Normal file
4
drivers/media/video/gspca/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
obj-$(CONFIG_GSPCA) += gspca_main.o gspca_stk014.o
|
||||
|
||||
gspca_main-objs := gspca.o
|
||||
gspca_stk014-objs := stk014.o
|
1750
drivers/media/video/gspca/gspca.c
Normal file
1750
drivers/media/video/gspca/gspca.c
Normal file
File diff suppressed because it is too large
Load Diff
178
drivers/media/video/gspca/gspca.h
Normal file
178
drivers/media/video/gspca/gspca.h
Normal file
@ -0,0 +1,178 @@
|
||||
#ifndef GSPCAV2_H
|
||||
#define GSPCAV2_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#ifdef GSPCA_DEBUG
|
||||
/* GSPCA our debug messages */
|
||||
extern int gspca_debug;
|
||||
#define PDEBUG(level, fmt, args...) \
|
||||
do {\
|
||||
if (gspca_debug & (level)) \
|
||||
printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
|
||||
} while (0)
|
||||
#define D_ERR 0x01
|
||||
#define D_PROBE 0x02
|
||||
#define D_CONF 0x04
|
||||
#define D_STREAM 0x08
|
||||
#define D_FRAM 0x10
|
||||
#define D_PACK 0x20
|
||||
#define D_USBI 0x40
|
||||
#define D_USBO 0x80
|
||||
#else
|
||||
#define PDEBUG(level, fmt, args...)
|
||||
#endif
|
||||
#undef err
|
||||
#define err(fmt, args...) \
|
||||
do {\
|
||||
printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args); \
|
||||
} while (0)
|
||||
#undef info
|
||||
#define info(fmt, args...) \
|
||||
do {\
|
||||
printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
|
||||
} while (0)
|
||||
#undef warn
|
||||
#define warn(fmt, args...) \
|
||||
do {\
|
||||
printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args); \
|
||||
} while (0)
|
||||
|
||||
#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
|
||||
/* ISOC transfers */
|
||||
#define NURBS 4 /* number of URBs */
|
||||
#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */
|
||||
#define ISO_MAX_SIZE 0x10000 /* max size of one URB buffer (64 Kb) */
|
||||
|
||||
/* device information - set at probe time */
|
||||
struct cam_mode {
|
||||
__u32 pixfmt;
|
||||
short width;
|
||||
short height;
|
||||
short mode; /* subdriver value */
|
||||
short reserved; /* subdriver value */
|
||||
};
|
||||
struct cam {
|
||||
char *dev_name;
|
||||
struct cam_mode *cam_mode; /* size nmodes */
|
||||
char nmodes;
|
||||
__u8 epaddr;
|
||||
};
|
||||
|
||||
struct gspca_dev;
|
||||
struct gspca_frame;
|
||||
|
||||
/* subdriver operations */
|
||||
typedef int (*cam_op) (struct gspca_dev *);
|
||||
typedef void (*cam_v_op) (struct gspca_dev *);
|
||||
typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
|
||||
typedef int (*cam_jpg_op) (struct gspca_dev *,
|
||||
struct v4l2_jpegcompression *);
|
||||
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,
|
||||
int len);
|
||||
|
||||
struct ctrl {
|
||||
struct v4l2_queryctrl qctrl;
|
||||
int (*set)(struct gspca_dev *, __s32);
|
||||
int (*get)(struct gspca_dev *, __s32 *);
|
||||
};
|
||||
|
||||
/* subdriver description */
|
||||
struct sd_desc {
|
||||
/* information */
|
||||
char *name; /* sub-driver name */
|
||||
/* controls */
|
||||
struct ctrl *ctrls;
|
||||
int nctrls;
|
||||
/* operations */
|
||||
cam_cf_op config; /* called on probe */
|
||||
cam_op open; /* called on open */
|
||||
cam_v_op start; /* called on stream on */
|
||||
cam_v_op stopN; /* called on stream off - main alt */
|
||||
cam_v_op stop0; /* called on stream off - alt 0 */
|
||||
cam_v_op close; /* called on close */
|
||||
cam_pkt_op pkt_scan;
|
||||
cam_jpg_op get_jcomp;
|
||||
cam_jpg_op set_jcomp;
|
||||
cam_qmnu_op querymenu;
|
||||
};
|
||||
|
||||
struct gspca_pktbuf {
|
||||
char *data;
|
||||
struct urb *urb;
|
||||
};
|
||||
|
||||
/* packet types when moving from iso buf to frame buf */
|
||||
#define DISCARD_PACKET 0
|
||||
#define FIRST_PACKET 1
|
||||
#define INTER_PACKET 2
|
||||
#define LAST_PACKET 3
|
||||
|
||||
struct gspca_frame {
|
||||
unsigned char *data; /* frame buffer */
|
||||
unsigned char *data_end; /* current end of frame while filling */
|
||||
int vma_use_count;
|
||||
struct v4l2_buffer v4l2_buf;
|
||||
};
|
||||
|
||||
struct gspca_dev {
|
||||
struct video_device vdev; /* !! must be the first item */
|
||||
struct usb_device *dev;
|
||||
|
||||
struct cam cam; /* device information */
|
||||
const struct sd_desc *sd_desc; /* subdriver description */
|
||||
|
||||
struct gspca_pktbuf pktbuf[NURBS];
|
||||
|
||||
__u8 *frbuf; /* buffer for nframes */
|
||||
struct gspca_frame frame[GSPCA_MAX_FRAMES];
|
||||
unsigned int frsz; /* frame size */
|
||||
char nframes; /* number of frames */
|
||||
char fr_i; /* frame being filled */
|
||||
char fr_q; /* next frame to queue */
|
||||
char fr_o; /* next frame to dequeue */
|
||||
signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
|
||||
char last_packet_type;
|
||||
|
||||
__u8 iface; /* USB interface number */
|
||||
__u8 alt; /* USB alternate setting */
|
||||
char curr_mode; /* current camera mode */
|
||||
__u32 pixfmt; /* current mode parameters */
|
||||
short width;
|
||||
short height;
|
||||
|
||||
atomic_t nevent; /* number of frames done */
|
||||
wait_queue_head_t wq; /* wait queue */
|
||||
struct mutex usb_lock; /* usb exchange protection */
|
||||
struct mutex read_lock; /* read protection */
|
||||
struct mutex queue_lock; /* ISOC queue protection */
|
||||
__u32 sequence; /* frame sequence number */
|
||||
signed char streaming;
|
||||
char users; /* # open */
|
||||
char present; /* device connected */
|
||||
char nbufread; /* number of buffers for read() */
|
||||
};
|
||||
|
||||
int gspca_dev_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id,
|
||||
const struct sd_desc *sd_desc,
|
||||
int dev_size);
|
||||
int gspca_dev_init(struct gspca_dev *gspca_dev,
|
||||
struct usb_interface *intf);
|
||||
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,
|
||||
int len);
|
||||
#endif /* GSPCAV2_H */
|
301
drivers/media/video/gspca/jpeg.h
Normal file
301
drivers/media/video/gspca/jpeg.h
Normal file
@ -0,0 +1,301 @@
|
||||
#ifndef JPEG_H
|
||||
#define JPEG_H 1
|
||||
/*
|
||||
* Insert a JPEG header at start of frame
|
||||
*
|
||||
* This module is used by the gspca subdrivers.
|
||||
* A special case is done for Conexant webcams.
|
||||
*
|
||||
* Copyright (C) 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* start of jpeg frame + quantization table */
|
||||
static const unsigned char quant[][0x88] = {
|
||||
/* index 0 - Q40*/
|
||||
{
|
||||
0xff, 0xd8, /* jpeg */
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0, /* quantization table part 1 */
|
||||
20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50,
|
||||
33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64,
|
||||
70, 69, 80, 90, 115, 98, 80, 85, 109, 86, 69, 70, 100, 136, 101,
|
||||
109,
|
||||
119, 123, 129, 130, 129, 78, 96, 141, 151, 140, 125, 150, 115,
|
||||
126, 129, 124,
|
||||
1, /* quantization table part 2 */
|
||||
21, 23, 23, 30, 26, 30, 59, 33, 33, 59, 124, 83, 70, 83, 124, 124,
|
||||
124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
|
||||
124, 124, 124,
|
||||
124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
|
||||
124, 124, 124,
|
||||
124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
|
||||
124, 124, 124},
|
||||
/* index 1 - Q50 */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40,
|
||||
26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51,
|
||||
56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87,
|
||||
95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101,
|
||||
103, 99,
|
||||
1,
|
||||
17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99},
|
||||
/* index 2 Q60 */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32,
|
||||
21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41,
|
||||
45, 44, 51, 58, 74, 62, 51, 54, 70, 55, 44, 45, 64, 87, 65, 70,
|
||||
76, 78, 82, 83, 82, 50, 62, 90, 97, 90, 80, 96, 74, 81, 82, 79,
|
||||
1,
|
||||
14, 14, 14, 19, 17, 19, 38, 21, 21, 38, 79, 53, 45, 53, 79, 79,
|
||||
79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
|
||||
79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
|
||||
79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79},
|
||||
/* index 3 - Q70 */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24,
|
||||
16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31,
|
||||
34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52,
|
||||
57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59,
|
||||
1,
|
||||
10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59,
|
||||
59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
|
||||
59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
|
||||
59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59},
|
||||
/* index 4 - Q80 */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16,
|
||||
10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20,
|
||||
22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35,
|
||||
38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40,
|
||||
1,
|
||||
7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40,
|
||||
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
|
||||
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
|
||||
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40},
|
||||
/* index 5 - Q85 */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12,
|
||||
8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15,
|
||||
17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26,
|
||||
29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30,
|
||||
1,
|
||||
5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30,
|
||||
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
|
||||
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
|
||||
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
|
||||
/* index 6 - 86 */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04,
|
||||
0x04, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0B,
|
||||
0x07, 0x07, 0x06, 0x06, 0x07, 0x0E, 0x0A, 0x0A,
|
||||
0x08, 0x0B, 0x10, 0x0E, 0x11, 0x11, 0x10, 0x0E,
|
||||
0x10, 0x0F, 0x12, 0x14, 0x1A, 0x16, 0x12, 0x13,
|
||||
0x18, 0x13, 0x0F, 0x10, 0x16, 0x1F, 0x17, 0x18,
|
||||
0x1B, 0x1B, 0x1D, 0x1D, 0x1D, 0x11, 0x16, 0x20,
|
||||
0x22, 0x1F, 0x1C, 0x22, 0x1A, 0x1C, 0x1D, 0x1C,
|
||||
1,
|
||||
0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0D, 0x07,
|
||||
0x07, 0x0D, 0x1C, 0x12, 0x10, 0x12, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||
},
|
||||
/* index 7 - 88 */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03,
|
||||
0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0A,
|
||||
0x06, 0x06, 0x05, 0x05, 0x06, 0x0C, 0x08, 0x09,
|
||||
0x07, 0x0A, 0x0E, 0x0C, 0x0F, 0x0E, 0x0E, 0x0C,
|
||||
0x0D, 0x0D, 0x0F, 0x11, 0x16, 0x13, 0x0F, 0x10,
|
||||
0x15, 0x11, 0x0D, 0x0D, 0x13, 0x1A, 0x13, 0x15,
|
||||
0x17, 0x18, 0x19, 0x19, 0x19, 0x0F, 0x12, 0x1B,
|
||||
0x1D, 0x1B, 0x18, 0x1D, 0x16, 0x18, 0x19, 0x18,
|
||||
1,
|
||||
0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0B, 0x06,
|
||||
0x06, 0x0B, 0x18, 0x10, 0x0D, 0x10, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
},
|
||||
/* index 8 - ?? */
|
||||
{
|
||||
0xff, 0xd8,
|
||||
0xff, 0xdb, 0x00, 0x84, /* DQT */
|
||||
0,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x05,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x05,
|
||||
0x04, 0x05, 0x07, 0x06, 0x08, 0x08, 0x07, 0x06,
|
||||
0x07, 0x07, 0x08, 0x09, 0x0C, 0x0A, 0x08, 0x09,
|
||||
0x0B, 0x09, 0x07, 0x07, 0x0A, 0x0E, 0x0A, 0x0B,
|
||||
0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x08, 0x0A, 0x0E,
|
||||
0x0F, 0x0E, 0x0D, 0x0F, 0x0C, 0x0D, 0x0D, 0x0C,
|
||||
1,
|
||||
0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x06, 0x03,
|
||||
0x03, 0x06, 0x0C, 0x08, 0x07, 0x08, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C
|
||||
}
|
||||
};
|
||||
|
||||
/* huffman table + start of SOF0 */
|
||||
static unsigned char huffman[] = {
|
||||
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, 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, 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, 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,
|
||||
#ifdef CONEX_CAM
|
||||
/* the Conexant frames start with SOF0 */
|
||||
#else
|
||||
0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */
|
||||
0x08, /* data precision */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef CONEX_CAM
|
||||
/* variable part:
|
||||
* 0x01, 0xe0, height
|
||||
* 0x02, 0x80, width
|
||||
* 0x03, component number
|
||||
* 0x01,
|
||||
* 0x21, samples Y
|
||||
*/
|
||||
|
||||
/* end of header */
|
||||
static unsigned char eoh[] = {
|
||||
0x00, /* quant Y */
|
||||
0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */
|
||||
0x03, 0x11, 0x01,
|
||||
|
||||
0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan */
|
||||
0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
/* -- output the JPEG header -- */
|
||||
static void jpeg_put_header(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame,
|
||||
int qindex,
|
||||
int samplesY)
|
||||
{
|
||||
#ifndef CONEX_CAM
|
||||
unsigned char tmpbuf[8];
|
||||
#endif
|
||||
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
|
||||
(unsigned char *) quant[qindex], sizeof quant[0]);
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
|
||||
(unsigned char *) huffman, sizeof huffman);
|
||||
#ifndef CONEX_CAM
|
||||
tmpbuf[0] = gspca_dev->height >> 8;
|
||||
tmpbuf[1] = gspca_dev->height & 0xff;
|
||||
tmpbuf[2] = gspca_dev->width >> 8;
|
||||
tmpbuf[3] = gspca_dev->width & 0xff;
|
||||
tmpbuf[4] = 0x03; /* component number */
|
||||
tmpbuf[5] = 0x01; /* first component */
|
||||
tmpbuf[6] = samplesY;
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
|
||||
tmpbuf, 7);
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
|
||||
eoh, sizeof eoh);
|
||||
#endif
|
||||
}
|
||||
#endif
|
562
drivers/media/video/gspca/stk014.c
Normal file
562
drivers/media/video/gspca/stk014.c
Normal file
@ -0,0 +1,562 @@
|
||||
/*
|
||||
* Syntek DV4000 (STK014) subdriver
|
||||
*
|
||||
* Copyright (C) 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 "stk014"
|
||||
|
||||
#include "gspca.h"
|
||||
#include "jpeg.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 22)
|
||||
static const char version[] = "0.0.22";
|
||||
|
||||
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
|
||||
MODULE_DESCRIPTION("Syntek DV4000 (STK014) 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;
|
||||
unsigned char colors;
|
||||
};
|
||||
|
||||
/* global parameters */
|
||||
static int lightfreq = 50;
|
||||
static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */
|
||||
|
||||
/* 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 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,
|
||||
},
|
||||
#define SD_COLOR 2
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_SATURATION,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Saturation",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 127,
|
||||
},
|
||||
.set = sd_setcolors,
|
||||
.get = sd_getcolors,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_mode vga_mode[] = {
|
||||
{V4L2_PIX_FMT_JPEG, 320, 240},
|
||||
{V4L2_PIX_FMT_JPEG, 640, 480},
|
||||
};
|
||||
|
||||
/* -- read a register -- */
|
||||
static int reg_read(struct gspca_dev *gspca_dev,
|
||||
__u16 index, __u8 *buf)
|
||||
{
|
||||
int ret;
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
||||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
0x00,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0x00,
|
||||
index,
|
||||
buf, 1,
|
||||
500);
|
||||
if (ret < 0)
|
||||
PDEBUG(D_ERR, "reg_read err %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -- write a register -- */
|
||||
static int reg_write(struct gspca_dev *gspca_dev,
|
||||
__u16 index, __u16 value)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
0x01,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
value,
|
||||
index,
|
||||
NULL,
|
||||
0,
|
||||
500);
|
||||
if (ret < 0)
|
||||
PDEBUG(D_ERR, "reg_write err %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -- get a value -- */
|
||||
static int rcv_val(struct gspca_dev *gspca_dev,
|
||||
int ads,
|
||||
int len)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->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);
|
||||
if (len > sizeof bulk_buf)
|
||||
return -1;
|
||||
ret = usb_bulk_msg(dev,
|
||||
usb_rcvbulkpipe(dev, 5),
|
||||
bulk_buf,
|
||||
len,
|
||||
&alen,
|
||||
500); /* timeout in milliseconds */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -- send a value -- */
|
||||
static int snd_val(struct gspca_dev *gspca_dev,
|
||||
int ads,
|
||||
unsigned int val)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
int alen, ret;
|
||||
__u8 value, seq;
|
||||
unsigned char bulk_buf[4];
|
||||
|
||||
if (ads == 0x003f08) {
|
||||
ret = reg_read(gspca_dev, 0x0704, &value);
|
||||
if (ret < 0)
|
||||
goto ko;
|
||||
ret = reg_read(gspca_dev, 0x0705, &seq);
|
||||
if (ret < 0)
|
||||
goto ko;
|
||||
ret = reg_read(gspca_dev, 0x0650, &value);
|
||||
if (ret < 0)
|
||||
goto ko;
|
||||
reg_write(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);
|
||||
bulk_buf[0] = (val >> 24) & 0xff;
|
||||
bulk_buf[1] = (val >> 16) & 0xff;
|
||||
bulk_buf[2] = (val >> 8) & 0xff;
|
||||
bulk_buf[3] = val & 0xff;
|
||||
ret = usb_bulk_msg(dev,
|
||||
usb_sndbulkpipe(dev, 6),
|
||||
bulk_buf,
|
||||
4,
|
||||
&alen,
|
||||
500); /* timeout in milliseconds */
|
||||
if (ret < 0)
|
||||
goto ko;
|
||||
if (ads == 0x003f08) {
|
||||
seq += 4;
|
||||
seq &= 0x3f;
|
||||
reg_write(gspca_dev, 0x705, seq);
|
||||
}
|
||||
return ret;
|
||||
ko:
|
||||
PDEBUG(D_ERR, "snd_val err %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set a camera parameter */
|
||||
static int set_par(struct gspca_dev *gspca_dev,
|
||||
int parval)
|
||||
{
|
||||
return snd_val(gspca_dev, 0x003f08, parval);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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 = &gspca_dev->cam;
|
||||
|
||||
cam->dev_name = (char *) id->driver_info;
|
||||
cam->epaddr = 0x02;
|
||||
gspca_dev->cam.cam_mode = vga_mode;
|
||||
gspca_dev->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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function is called at open time */
|
||||
static int sd_open(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
__u8 value;
|
||||
int ret;
|
||||
|
||||
/* check if the device responds */
|
||||
usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
|
||||
ret = reg_read(gspca_dev, 0x0740, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (value != 0xff) {
|
||||
PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", value);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- start the camera -- */
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
__u8 dum;
|
||||
int ret, value;
|
||||
|
||||
/* work on alternate 1 */
|
||||
usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
|
||||
|
||||
set_par(gspca_dev, 0x10000000);
|
||||
set_par(gspca_dev, 0x00000000);
|
||||
set_par(gspca_dev, 0x8002e001);
|
||||
set_par(gspca_dev, 0x14000000);
|
||||
if (gspca_dev->width > 320)
|
||||
value = 0x8002e001; /* 640x480 */
|
||||
else
|
||||
value = 0x4001f000; /* 320x240 */
|
||||
set_par(gspca_dev, value);
|
||||
ret = usb_set_interface(gspca_dev->dev,
|
||||
gspca_dev->iface,
|
||||
gspca_dev->alt);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = reg_read(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);
|
||||
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);
|
||||
setbrightness(gspca_dev); /* whiteness */
|
||||
setcontrast(gspca_dev); /* contrast */
|
||||
setcolors(gspca_dev); /* saturation */
|
||||
set_par(gspca_dev, 0x09800000); /* Red ? */
|
||||
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 */
|
||||
|
||||
/* start the video flow */
|
||||
set_par(gspca_dev, 0x01000000);
|
||||
set_par(gspca_dev, 0x01000000);
|
||||
PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
|
||||
return;
|
||||
out:
|
||||
PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret);
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u8 value;
|
||||
|
||||
set_par(gspca_dev, 0x02000000);
|
||||
set_par(gspca_dev, 0x02000000);
|
||||
usb_set_interface(dev, gspca_dev->iface, 1);
|
||||
reg_read(gspca_dev, 0x0630, &value);
|
||||
rcv_val(gspca_dev, 0x000020, 4); /* << (value ff ff ff ff) */
|
||||
reg_read(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);
|
||||
PDEBUG(D_STREAM, "camera stopped");
|
||||
}
|
||||
|
||||
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 l;
|
||||
|
||||
/* a frame starts with:
|
||||
* - 0xff 0xfe
|
||||
* - 0x08 0x00 // length (little endian ?!)
|
||||
* - 4 bytes = size of whole frame (big endian - including header)
|
||||
* - 0x00 0x0c
|
||||
* - 0xff 0xd8
|
||||
* - .. JPEG image with escape sequences (ff 00)
|
||||
*/
|
||||
if (data[0] == 0xff && data[1] == 0xfe) {
|
||||
if (gspca_dev->last_packet_type == INTER_PACKET) {
|
||||
PDEBUG(D_ERR|D_FRAM, "sof actual l: %d init l: %d",
|
||||
frame->data_end - frame->data,
|
||||
frame->v4l2_buf.bytesused);
|
||||
}
|
||||
|
||||
/* put the JPEG headaer */
|
||||
jpeg_put_header(gspca_dev, frame, sd_quant, 0x22);
|
||||
|
||||
/* beginning of the frame */
|
||||
#define STKHDRSZ 12
|
||||
l = (data[4] << 24) /* frame size */
|
||||
+ (data[5] << 16)
|
||||
+ (data[6] << 8)
|
||||
+ data[7]
|
||||
- STKHDRSZ
|
||||
+ (frame->data_end - frame->data)
|
||||
+ 2; /* EOF (ff d9) */
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
|
||||
data + STKHDRSZ, len - STKHDRSZ);
|
||||
#undef STKHDRSZ
|
||||
frame->v4l2_buf.bytesused = l;
|
||||
return;
|
||||
}
|
||||
if (gspca_dev->last_packet_type != INTER_PACKET) {
|
||||
if (gspca_dev->last_packet_type == LAST_PACKET) {
|
||||
PDEBUG(D_ERR|D_PACK, "mof actual l: %d init l: %d",
|
||||
frame->data_end - frame->data,
|
||||
frame->v4l2_buf.bytesused);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* intermediate packet */
|
||||
l = frame->data_end - frame->data;
|
||||
if (len < frame->v4l2_buf.bytesused - 2 - l) {
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
|
||||
data, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* last packet */
|
||||
if (len > frame->v4l2_buf.bytesused - 2 - l)
|
||||
len = frame->v4l2_buf.bytesused - 2 - l;
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
|
||||
gspca_frame_add(gspca_dev, LAST_PACKET, frame, "\xff\xd9", 2);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
*val = sd->colors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0],
|
||||
.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(0x05e1, 0x0893), DVNM("Syntek DV4000")},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
||||
/* -- device connect -- */
|
||||
static int sd_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
PDEBUG(D_PROBE, "camera probe");
|
||||
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd));
|
||||
}
|
||||
|
||||
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;
|
||||
info("v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
static void __exit sd_mod_exit(void)
|
||||
{
|
||||
usb_deregister(&sd_driver);
|
||||
info("deregistered");
|
||||
}
|
||||
|
||||
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)");
|
Loading…
Reference in New Issue
Block a user