diff options
author | Kyle Guinn <elyk03@gmail.com> | 2009-01-16 03:36:14 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:32 -0400 |
commit | d661e62205498ce6518b9859bc30444e59737d8b (patch) | |
tree | a73119ae42513fc6a2b60ff1d3dad33be078daa5 | |
parent | 553d0d839b93550780d1b46e6bcd01a3c5c5883e (diff) |
V4L/DVB (10366): gspca - mr97310a: New subdriver.
This patch adds support for USB webcams based on the MR97310A chip. It was
tested with an Aiptek PenCam VGA+ webcam.
Signed-off-by: Kyle Guinn <elyk03@gmail.com>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | Documentation/video4linux/gspca.txt | 1 | ||||
-rw-r--r-- | drivers/media/video/gspca/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/video/gspca/Makefile | 98 | ||||
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 1 | ||||
-rw-r--r-- | drivers/media/video/gspca/mr97310a.c | 378 |
5 files changed, 439 insertions, 48 deletions
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 1c58a7630146..af80c3344567 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt | |||
@@ -193,6 +193,7 @@ spca500 084d:0003 D-Link DSC-350 | |||
193 | spca500 08ca:0103 Aiptek PocketDV | 193 | spca500 08ca:0103 Aiptek PocketDV |
194 | sunplus 08ca:0104 Aiptek PocketDVII 1.3 | 194 | sunplus 08ca:0104 Aiptek PocketDVII 1.3 |
195 | sunplus 08ca:0106 Aiptek Pocket DV3100+ | 195 | sunplus 08ca:0106 Aiptek Pocket DV3100+ |
196 | mr97310a 08ca:0111 Aiptek PenCam VGA+ | ||
196 | sunplus 08ca:2008 Aiptek Mini PenCam 2 M | 197 | sunplus 08ca:2008 Aiptek Mini PenCam 2 M |
197 | sunplus 08ca:2010 Aiptek PocketCam 3M | 198 | sunplus 08ca:2010 Aiptek PocketCam 3M |
198 | sunplus 08ca:2016 Aiptek PocketCam 2 Mega | 199 | sunplus 08ca:2016 Aiptek PocketCam 2 Mega |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index ee6a691dff22..11c5d2fc20de 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -56,6 +56,15 @@ config USB_GSPCA_MARS | |||
56 | To compile this driver as a module, choose M here: the | 56 | To compile this driver as a module, choose M here: the |
57 | module will be called gspca_mars. | 57 | module will be called gspca_mars. |
58 | 58 | ||
59 | config USB_GSPCA_MR97310A | ||
60 | tristate "Mars-Semi MR97310A USB Camera Driver" | ||
61 | depends on VIDEO_V4L2 && USB_GSPCA | ||
62 | help | ||
63 | Say Y here if you want support for cameras based on the MR97310A chip. | ||
64 | |||
65 | To compile this driver as a module, choose M here: the | ||
66 | module will be called gspca_mr97310a. | ||
67 | |||
59 | config USB_GSPCA_OV519 | 68 | config USB_GSPCA_OV519 |
60 | tristate "OV519 USB Camera Driver" | 69 | tristate "OV519 USB Camera Driver" |
61 | depends on VIDEO_V4L2 && USB_GSPCA | 70 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index bd8d9ee40504..b3cbcc1764f4 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -1,50 +1,52 @@ | |||
1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o | 1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o |
2 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o | 2 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o |
3 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o | 3 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
4 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o | 4 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
5 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o | 5 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o |
6 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o | 6 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o |
7 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o | 7 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o |
8 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o | 8 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o |
9 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | 9 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o |
10 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o | 10 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o |
11 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o | 11 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o |
12 | obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o | 12 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o |
13 | obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o | 13 | obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o |
14 | obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o | 14 | obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o |
15 | obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o | 15 | obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o |
16 | obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o | 16 | obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o |
17 | obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o | 17 | obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o |
18 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | 18 | obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o |
19 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | 19 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o |
20 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o | 20 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o |
21 | obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o | 21 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o |
22 | obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o | 22 | obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o |
23 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o | 23 | obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o |
24 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o | ||
24 | 25 | ||
25 | gspca_main-objs := gspca.o | 26 | gspca_main-objs := gspca.o |
26 | gspca_conex-objs := conex.o | 27 | gspca_conex-objs := conex.o |
27 | gspca_etoms-objs := etoms.o | 28 | gspca_etoms-objs := etoms.o |
28 | gspca_finepix-objs := finepix.o | 29 | gspca_finepix-objs := finepix.o |
29 | gspca_mars-objs := mars.o | 30 | gspca_mars-objs := mars.o |
30 | gspca_ov519-objs := ov519.o | 31 | gspca_mr97310a-objs := mr97310a.o |
31 | gspca_ov534-objs := ov534.o | 32 | gspca_ov519-objs := ov519.o |
32 | gspca_pac207-objs := pac207.o | 33 | gspca_ov534-objs := ov534.o |
33 | gspca_pac7311-objs := pac7311.o | 34 | gspca_pac207-objs := pac207.o |
34 | gspca_sonixb-objs := sonixb.o | 35 | gspca_pac7311-objs := pac7311.o |
35 | gspca_sonixj-objs := sonixj.o | 36 | gspca_sonixb-objs := sonixb.o |
36 | gspca_spca500-objs := spca500.o | 37 | gspca_sonixj-objs := sonixj.o |
37 | gspca_spca501-objs := spca501.o | 38 | gspca_spca500-objs := spca500.o |
38 | gspca_spca505-objs := spca505.o | 39 | gspca_spca501-objs := spca501.o |
39 | gspca_spca506-objs := spca506.o | 40 | gspca_spca505-objs := spca505.o |
40 | gspca_spca508-objs := spca508.o | 41 | gspca_spca506-objs := spca506.o |
41 | gspca_spca561-objs := spca561.o | 42 | gspca_spca508-objs := spca508.o |
42 | gspca_stk014-objs := stk014.o | 43 | gspca_spca561-objs := spca561.o |
43 | gspca_sunplus-objs := sunplus.o | 44 | gspca_stk014-objs := stk014.o |
44 | gspca_t613-objs := t613.o | 45 | gspca_sunplus-objs := sunplus.o |
45 | gspca_tv8532-objs := tv8532.o | 46 | gspca_t613-objs := t613.o |
46 | gspca_vc032x-objs := vc032x.o | 47 | gspca_tv8532-objs := tv8532.o |
47 | gspca_zc3xx-objs := zc3xx.o | 48 | gspca_vc032x-objs := vc032x.o |
49 | gspca_zc3xx-objs := zc3xx.o | ||
48 | 50 | ||
49 | obj-$(CONFIG_USB_M5602) += m5602/ | 51 | obj-$(CONFIG_USB_M5602) += m5602/ |
50 | obj-$(CONFIG_USB_STV06XX) += stv06xx/ | 52 | obj-$(CONFIG_USB_STV06XX) += stv06xx/ |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 5dd2abc17ae6..6c03d57ae506 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -318,6 +318,7 @@ static int gspca_is_compressed(__u32 format) | |||
318 | case V4L2_PIX_FMT_JPEG: | 318 | case V4L2_PIX_FMT_JPEG: |
319 | case V4L2_PIX_FMT_SPCA561: | 319 | case V4L2_PIX_FMT_SPCA561: |
320 | case V4L2_PIX_FMT_PAC207: | 320 | case V4L2_PIX_FMT_PAC207: |
321 | case V4L2_PIX_FMT_MR97310A: | ||
321 | return 1; | 322 | return 1; |
322 | } | 323 | } |
323 | return 0; | 324 | return 0; |
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c new file mode 100644 index 000000000000..24180bf0cdab --- /dev/null +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -0,0 +1,378 @@ | |||
1 | /* | ||
2 | * Mars MR97310A library | ||
3 | * | ||
4 | * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "mr97310a" | ||
22 | |||
23 | #include "gspca.h" | ||
24 | |||
25 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>"); | ||
26 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct sd { | ||
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
32 | |||
33 | u8 sof_read; | ||
34 | u8 header_read; | ||
35 | }; | ||
36 | |||
37 | /* V4L2 controls supported by the driver */ | ||
38 | static struct ctrl sd_ctrls[] = { | ||
39 | }; | ||
40 | |||
41 | static const struct v4l2_pix_format vga_mode[] = { | ||
42 | {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, | ||
43 | .bytesperline = 160, | ||
44 | .sizeimage = 160 * 120, | ||
45 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
46 | .priv = 4}, | ||
47 | {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, | ||
48 | .bytesperline = 176, | ||
49 | .sizeimage = 176 * 144, | ||
50 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
51 | .priv = 3}, | ||
52 | {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, | ||
53 | .bytesperline = 320, | ||
54 | .sizeimage = 320 * 240, | ||
55 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
56 | .priv = 2}, | ||
57 | {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, | ||
58 | .bytesperline = 352, | ||
59 | .sizeimage = 352 * 288, | ||
60 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
61 | .priv = 1}, | ||
62 | {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, | ||
63 | .bytesperline = 640, | ||
64 | .sizeimage = 640 * 480, | ||
65 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
66 | .priv = 0}, | ||
67 | }; | ||
68 | |||
69 | /* the bytes to write are in gspca_dev->usb_buf */ | ||
70 | static int reg_w(struct gspca_dev *gspca_dev, int len) | ||
71 | { | ||
72 | int rc; | ||
73 | |||
74 | rc = usb_bulk_msg(gspca_dev->dev, | ||
75 | usb_sndbulkpipe(gspca_dev->dev, 4), | ||
76 | gspca_dev->usb_buf, len, 0, 500); | ||
77 | if (rc < 0) | ||
78 | PDEBUG(D_ERR, "reg write [%02x] error %d", | ||
79 | gspca_dev->usb_buf[0], rc); | ||
80 | return rc; | ||
81 | } | ||
82 | |||
83 | /* this function is called at probe time */ | ||
84 | static int sd_config(struct gspca_dev *gspca_dev, | ||
85 | const struct usb_device_id *id) | ||
86 | { | ||
87 | struct cam *cam; | ||
88 | |||
89 | cam = &gspca_dev->cam; | ||
90 | cam->cam_mode = vga_mode; | ||
91 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | /* this function is called at probe and resume time */ | ||
96 | static int sd_init(struct gspca_dev *gspca_dev) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int sd_start(struct gspca_dev *gspca_dev) | ||
102 | { | ||
103 | struct sd *sd = (struct sd *) gspca_dev; | ||
104 | __u8 *data = gspca_dev->usb_buf; | ||
105 | int err_code; | ||
106 | |||
107 | sd->sof_read = 0; | ||
108 | |||
109 | /* Note: register descriptions guessed from MR97113A driver */ | ||
110 | |||
111 | data[0] = 0x01; | ||
112 | data[1] = 0x01; | ||
113 | err_code = reg_w(gspca_dev, 2); | ||
114 | if (err_code < 0) | ||
115 | return err_code; | ||
116 | |||
117 | data[0] = 0x00; | ||
118 | data[1] = 0x0d; | ||
119 | data[2] = 0x01; | ||
120 | data[5] = 0x2b; | ||
121 | data[7] = 0x00; | ||
122 | data[9] = 0x50; /* reg 8, no scale down */ | ||
123 | data[10] = 0xc0; | ||
124 | |||
125 | switch (gspca_dev->width) { | ||
126 | case 160: | ||
127 | data[9] |= 0x0c; /* reg 8, 4:1 scale down */ | ||
128 | /* fall thru */ | ||
129 | case 320: | ||
130 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ | ||
131 | /* fall thru */ | ||
132 | case 640: | ||
133 | default: | ||
134 | data[3] = 0x50; /* reg 2, H size */ | ||
135 | data[4] = 0x78; /* reg 3, V size */ | ||
136 | data[6] = 0x04; /* reg 5, H start */ | ||
137 | data[8] = 0x03; /* reg 7, V start */ | ||
138 | break; | ||
139 | |||
140 | case 176: | ||
141 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ | ||
142 | /* fall thru */ | ||
143 | case 352: | ||
144 | data[3] = 0x2c; /* reg 2, H size */ | ||
145 | data[4] = 0x48; /* reg 3, V size */ | ||
146 | data[6] = 0x94; /* reg 5, H start */ | ||
147 | data[8] = 0x63; /* reg 7, V start */ | ||
148 | break; | ||
149 | } | ||
150 | |||
151 | err_code = reg_w(gspca_dev, 11); | ||
152 | if (err_code < 0) | ||
153 | return err_code; | ||
154 | |||
155 | data[0] = 0x0a; | ||
156 | data[1] = 0x80; | ||
157 | err_code = reg_w(gspca_dev, 2); | ||
158 | if (err_code < 0) | ||
159 | return err_code; | ||
160 | |||
161 | data[0] = 0x14; | ||
162 | data[1] = 0x0a; | ||
163 | err_code = reg_w(gspca_dev, 2); | ||
164 | if (err_code < 0) | ||
165 | return err_code; | ||
166 | |||
167 | data[0] = 0x1b; | ||
168 | data[1] = 0x00; | ||
169 | err_code = reg_w(gspca_dev, 2); | ||
170 | if (err_code < 0) | ||
171 | return err_code; | ||
172 | |||
173 | data[0] = 0x15; | ||
174 | data[1] = 0x16; | ||
175 | err_code = reg_w(gspca_dev, 2); | ||
176 | if (err_code < 0) | ||
177 | return err_code; | ||
178 | |||
179 | data[0] = 0x16; | ||
180 | data[1] = 0x10; | ||
181 | err_code = reg_w(gspca_dev, 2); | ||
182 | if (err_code < 0) | ||
183 | return err_code; | ||
184 | |||
185 | data[0] = 0x17; | ||
186 | data[1] = 0x3a; | ||
187 | err_code = reg_w(gspca_dev, 2); | ||
188 | if (err_code < 0) | ||
189 | return err_code; | ||
190 | |||
191 | data[0] = 0x18; | ||
192 | data[1] = 0x68; | ||
193 | err_code = reg_w(gspca_dev, 2); | ||
194 | if (err_code < 0) | ||
195 | return err_code; | ||
196 | |||
197 | data[0] = 0x1f; | ||
198 | data[1] = 0x00; | ||
199 | data[2] = 0x02; | ||
200 | data[3] = 0x06; | ||
201 | data[4] = 0x59; | ||
202 | data[5] = 0x0c; | ||
203 | data[6] = 0x16; | ||
204 | data[7] = 0x00; | ||
205 | data[8] = 0x07; | ||
206 | data[9] = 0x00; | ||
207 | data[10] = 0x01; | ||
208 | err_code = reg_w(gspca_dev, 11); | ||
209 | if (err_code < 0) | ||
210 | return err_code; | ||
211 | |||
212 | data[0] = 0x1f; | ||
213 | data[1] = 0x04; | ||
214 | data[2] = 0x11; | ||
215 | data[3] = 0x01; | ||
216 | err_code = reg_w(gspca_dev, 4); | ||
217 | if (err_code < 0) | ||
218 | return err_code; | ||
219 | |||
220 | data[0] = 0x1f; | ||
221 | data[1] = 0x00; | ||
222 | data[2] = 0x0a; | ||
223 | data[3] = 0x00; | ||
224 | data[4] = 0x01; | ||
225 | data[5] = 0x00; | ||
226 | data[6] = 0x00; | ||
227 | data[7] = 0x01; | ||
228 | data[8] = 0x00; | ||
229 | data[9] = 0x0a; | ||
230 | err_code = reg_w(gspca_dev, 10); | ||
231 | if (err_code < 0) | ||
232 | return err_code; | ||
233 | |||
234 | data[0] = 0x1f; | ||
235 | data[1] = 0x04; | ||
236 | data[2] = 0x11; | ||
237 | data[3] = 0x01; | ||
238 | err_code = reg_w(gspca_dev, 4); | ||
239 | if (err_code < 0) | ||
240 | return err_code; | ||
241 | |||
242 | data[0] = 0x1f; | ||
243 | data[1] = 0x00; | ||
244 | data[2] = 0x12; | ||
245 | data[3] = 0x00; | ||
246 | data[4] = 0x63; | ||
247 | data[5] = 0x00; | ||
248 | data[6] = 0x70; | ||
249 | data[7] = 0x00; | ||
250 | data[8] = 0x01; | ||
251 | err_code = reg_w(gspca_dev, 10); | ||
252 | if (err_code < 0) | ||
253 | return err_code; | ||
254 | |||
255 | data[0] = 0x1f; | ||
256 | data[1] = 0x04; | ||
257 | data[2] = 0x11; | ||
258 | data[3] = 0x01; | ||
259 | err_code = reg_w(gspca_dev, 4); | ||
260 | if (err_code < 0) | ||
261 | return err_code; | ||
262 | |||
263 | data[0] = 0x00; | ||
264 | data[1] = 0x4d; /* ISOC transfering enable... */ | ||
265 | err_code = reg_w(gspca_dev, 2); | ||
266 | return err_code; | ||
267 | } | ||
268 | |||
269 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
270 | { | ||
271 | int result; | ||
272 | |||
273 | gspca_dev->usb_buf[0] = 1; | ||
274 | gspca_dev->usb_buf[1] = 0; | ||
275 | result = reg_w(gspca_dev, 2); | ||
276 | if (result < 0) | ||
277 | PDEBUG(D_ERR, "Camera Stop failed"); | ||
278 | } | ||
279 | |||
280 | /* Include pac common sof detection functions */ | ||
281 | #include "pac_common.h" | ||
282 | |||
283 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
284 | struct gspca_frame *frame, /* target */ | ||
285 | __u8 *data, /* isoc packet */ | ||
286 | int len) /* iso packet length */ | ||
287 | { | ||
288 | struct sd *sd = (struct sd *) gspca_dev; | ||
289 | unsigned char *sof; | ||
290 | |||
291 | sof = pac_find_sof(gspca_dev, data, len); | ||
292 | if (sof) { | ||
293 | int n; | ||
294 | |||
295 | /* finish decoding current frame */ | ||
296 | n = sof - data; | ||
297 | if (n > sizeof pac_sof_marker) | ||
298 | n -= sizeof pac_sof_marker; | ||
299 | else | ||
300 | n = 0; | ||
301 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
302 | data, n); | ||
303 | sd->header_read = 0; | ||
304 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); | ||
305 | len -= sof - data; | ||
306 | data = sof; | ||
307 | } | ||
308 | if (sd->header_read < 7) { | ||
309 | int needed; | ||
310 | |||
311 | /* skip the rest of the header */ | ||
312 | needed = 7 - sd->header_read; | ||
313 | if (len <= needed) { | ||
314 | sd->header_read += len; | ||
315 | return; | ||
316 | } | ||
317 | data += needed; | ||
318 | len -= needed; | ||
319 | sd->header_read = 7; | ||
320 | } | ||
321 | |||
322 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
323 | } | ||
324 | |||
325 | /* sub-driver description */ | ||
326 | static const struct sd_desc sd_desc = { | ||
327 | .name = MODULE_NAME, | ||
328 | .ctrls = sd_ctrls, | ||
329 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
330 | .config = sd_config, | ||
331 | .init = sd_init, | ||
332 | .start = sd_start, | ||
333 | .stopN = sd_stopN, | ||
334 | .pkt_scan = sd_pkt_scan, | ||
335 | }; | ||
336 | |||
337 | /* -- module initialisation -- */ | ||
338 | static const __devinitdata struct usb_device_id device_table[] = { | ||
339 | {USB_DEVICE(0x08ca, 0x0111)}, | ||
340 | {} | ||
341 | }; | ||
342 | MODULE_DEVICE_TABLE(usb, device_table); | ||
343 | |||
344 | /* -- device connect -- */ | ||
345 | static int sd_probe(struct usb_interface *intf, | ||
346 | const struct usb_device_id *id) | ||
347 | { | ||
348 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
349 | THIS_MODULE); | ||
350 | } | ||
351 | |||
352 | static struct usb_driver sd_driver = { | ||
353 | .name = MODULE_NAME, | ||
354 | .id_table = device_table, | ||
355 | .probe = sd_probe, | ||
356 | .disconnect = gspca_disconnect, | ||
357 | #ifdef CONFIG_PM | ||
358 | .suspend = gspca_suspend, | ||
359 | .resume = gspca_resume, | ||
360 | #endif | ||
361 | }; | ||
362 | |||
363 | /* -- module insert / remove -- */ | ||
364 | static int __init sd_mod_init(void) | ||
365 | { | ||
366 | if (usb_register(&sd_driver) < 0) | ||
367 | return -1; | ||
368 | PDEBUG(D_PROBE, "registered"); | ||
369 | return 0; | ||
370 | } | ||
371 | static void __exit sd_mod_exit(void) | ||
372 | { | ||
373 | usb_deregister(&sd_driver); | ||
374 | PDEBUG(D_PROBE, "deregistered"); | ||
375 | } | ||
376 | |||
377 | module_init(sd_mod_init); | ||
378 | module_exit(sd_mod_exit); | ||