diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-07-14 08:38:29 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:26:14 -0400 |
commit | 739570bb218bb4607df1f197282561e97a98e54a (patch) | |
tree | 25555dfe5ac873bc96866c486d6f6c1dcabf24f4 /drivers/media/video/gspca/mars.c | |
parent | 5b77ae7776183d733ec86727bcc34c52a336afd6 (diff) |
V4L/DVB (8352): gspca: Buffers for USB exchanges cannot be in the stack.
gspca: Protect dq_callback() against simultaneous USB exchanges.
Temporary buffer for USB exchanges added in the device struct.
(all) Use a temporary buffer for all USB exchanges.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/mars.c')
-rw-r--r-- | drivers/media/video/gspca/mars.c | 158 |
1 files changed, 85 insertions, 73 deletions
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 23f3dba8012a..88c2b02f380a 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
@@ -24,8 +24,8 @@ | |||
24 | #include "gspca.h" | 24 | #include "gspca.h" |
25 | #include "jpeg.h" | 25 | #include "jpeg.h" |
26 | 26 | ||
27 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5) | 27 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7) |
28 | static const char version[] = "2.1.5"; | 28 | static const char version[] = "2.1.7"; |
29 | 29 | ||
30 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 30 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); |
31 | MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver"); | 31 | MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver"); |
@@ -83,39 +83,53 @@ enum { | |||
83 | REG_HW_MI_63, | 83 | REG_HW_MI_63, |
84 | REG_HW_MI_64, | 84 | REG_HW_MI_64, |
85 | REG_HW_MI_F1 = 0xf1, | 85 | REG_HW_MI_F1 = 0xf1, |
86 | ATTR_TOTAL_MI_REG = 242 | 86 | ATTR_TOTAL_MI_REG = 0xf2 |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static int pcam_reg_write(struct usb_device *dev, | 89 | /* the bytes to write are in gspca_dev->usb_buf */ |
90 | __u16 index, __u8 *value, int len) | 90 | static int reg_w(struct gspca_dev *gspca_dev, |
91 | __u16 index, int len) | ||
91 | { | 92 | { |
92 | int rc; | 93 | int rc; |
93 | 94 | ||
94 | rc = usb_control_msg(dev, | 95 | rc = usb_control_msg(gspca_dev->dev, |
95 | usb_sndbulkpipe(dev, 4), | 96 | usb_sndbulkpipe(gspca_dev->dev, 4), |
96 | 0x12, | 97 | 0x12, |
97 | /* ?? 0xc8 = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_??? !? */ | 98 | 0xc8, /* ?? */ |
98 | 0xc8, | ||
99 | 0, /* value */ | 99 | 0, /* value */ |
100 | index, value, len, 500); | 100 | index, gspca_dev->usb_buf, len, 500); |
101 | if (rc < 0) | 101 | if (rc < 0) |
102 | PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc); | 102 | PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc); |
103 | return rc; | 103 | return rc; |
104 | } | 104 | } |
105 | 105 | ||
106 | static void MISensor_BulkWrite(struct usb_device *dev, | 106 | static int reg_w_buf(struct gspca_dev *gspca_dev, |
107 | unsigned short *pch, | 107 | __u16 index, __u8 *buf, int len) |
108 | char Address) | ||
109 | { | 108 | { |
110 | __u8 data[6]; | 109 | int rc; |
110 | |||
111 | rc = usb_control_msg(gspca_dev->dev, | ||
112 | usb_sndbulkpipe(gspca_dev->dev, 4), | ||
113 | 0x12, | ||
114 | 0xc8, /* ?? */ | ||
115 | 0, /* value */ | ||
116 | index, buf, len, 500); | ||
117 | if (rc < 0) | ||
118 | PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc); | ||
119 | return rc; | ||
120 | } | ||
111 | 121 | ||
112 | data[0] = 0x1f; | 122 | static void bulk_w(struct gspca_dev *gspca_dev, |
113 | data[1] = 0; /* control byte */ | 123 | __u16 *pch, |
114 | data[2] = Address; | 124 | __u16 Address) |
115 | data[3] = *pch >> 8; /* high byte */ | 125 | { |
116 | data[4] = *pch; /* low byte */ | 126 | gspca_dev->usb_buf[0] = 0x1f; |
127 | gspca_dev->usb_buf[1] = 0; /* control byte */ | ||
128 | gspca_dev->usb_buf[2] = Address; | ||
129 | gspca_dev->usb_buf[3] = *pch >> 8; /* high byte */ | ||
130 | gspca_dev->usb_buf[4] = *pch; /* low byte */ | ||
117 | 131 | ||
118 | pcam_reg_write(dev, Address, data, 5); | 132 | reg_w(gspca_dev, Address, 5); |
119 | } | 133 | } |
120 | 134 | ||
121 | /* this function is called at probe time */ | 135 | /* this function is called at probe time */ |
@@ -142,33 +156,30 @@ static int sd_open(struct gspca_dev *gspca_dev) | |||
142 | 156 | ||
143 | static void sd_start(struct gspca_dev *gspca_dev) | 157 | static void sd_start(struct gspca_dev *gspca_dev) |
144 | { | 158 | { |
145 | struct usb_device *dev = gspca_dev->dev; | ||
146 | int err_code; | 159 | int err_code; |
147 | __u8 data[12]; | 160 | __u8 *data; |
148 | __u16 MI_buf[242]; | 161 | __u16 *MI_buf; |
149 | int h_size, v_size; | 162 | int h_size, v_size; |
150 | int intpipe; | 163 | int intpipe; |
151 | /* struct usb_device *dev = pcam->dev; */ | ||
152 | |||
153 | memset(data, 0, sizeof data); | ||
154 | memset(MI_buf, 0, sizeof MI_buf); | ||
155 | 164 | ||
156 | PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); | 165 | PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); |
157 | if (usb_set_interface(dev, gspca_dev->iface, 8) < 0) { | 166 | if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) { |
158 | PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); | 167 | PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); |
159 | return; | 168 | return; |
160 | } | 169 | } |
161 | 170 | ||
171 | data = gspca_dev->usb_buf; | ||
162 | data[0] = 0x01; /* address */ | 172 | data[0] = 0x01; /* address */ |
163 | data[1] = 0x01; | 173 | data[1] = 0x01; |
164 | 174 | ||
165 | err_code = pcam_reg_write(dev, data[0], data, 2); | 175 | err_code = reg_w(gspca_dev, data[0], 2); |
166 | if (err_code < 0) | 176 | if (err_code < 0) |
167 | return; | 177 | return; |
168 | 178 | ||
169 | /* | 179 | /* |
170 | Initialize the MR97113 chip register | 180 | Initialize the MR97113 chip register |
171 | */ | 181 | */ |
182 | data = kmalloc(16, GFP_KERNEL); | ||
172 | data[0] = 0x00; /* address */ | 183 | data[0] = 0x00; /* address */ |
173 | data[1] = 0x0c | 0x01; /* reg 0 */ | 184 | data[1] = 0x0c | 0x01; /* reg 0 */ |
174 | data[2] = 0x01; /* reg 1 */ | 185 | data[2] = 0x01; /* reg 1 */ |
@@ -181,34 +192,34 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
181 | data[6] = 4; /* reg 5, H start */ | 192 | data[6] = 4; /* reg 5, H start */ |
182 | data[7] = 0xc0; /* reg 6, gamma 1.5 */ | 193 | data[7] = 0xc0; /* reg 6, gamma 1.5 */ |
183 | data[8] = 3; /* reg 7, V start */ | 194 | data[8] = 3; /* reg 7, V start */ |
184 | /* if(h_size == 320 ) */ | 195 | /* if (h_size == 320 ) */ |
185 | /* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */ | 196 | /* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */ |
186 | /* else */ | 197 | /* else */ |
187 | data[9] = 0x52; /* reg 8, 24MHz, no scale down */ | 198 | data[9] = 0x52; /* reg 8, 24MHz, no scale down */ |
188 | data[10] = 0x5d; /* reg 9, I2C device address | 199 | data[10] = 0x5d; /* reg 9, I2C device address |
189 | * [for PAS5101 (0x40)] [for MI (0x5d)] */ | 200 | * [for PAS5101 (0x40)] [for MI (0x5d)] */ |
190 | 201 | ||
191 | err_code = pcam_reg_write(dev, data[0], data, 11); | 202 | err_code = reg_w_buf(gspca_dev, data[0], data, 11); |
203 | kfree(data); | ||
192 | if (err_code < 0) | 204 | if (err_code < 0) |
193 | return; | 205 | return; |
194 | 206 | ||
207 | data = gspca_dev->usb_buf; | ||
195 | data[0] = 0x23; /* address */ | 208 | data[0] = 0x23; /* address */ |
196 | data[1] = 0x09; /* reg 35, append frame header */ | 209 | data[1] = 0x09; /* reg 35, append frame header */ |
197 | 210 | ||
198 | err_code = pcam_reg_write(dev, data[0], data, 2); | 211 | err_code = reg_w(gspca_dev, data[0], 2); |
199 | if (err_code < 0) { | 212 | if (err_code < 0) |
200 | PDEBUG(D_ERR, "Register write failed"); | ||
201 | return; | 213 | return; |
202 | } | ||
203 | 214 | ||
204 | data[0] = 0x3C; /* address */ | 215 | data[0] = 0x3c; /* address */ |
205 | /* if (pcam->width == 1280) */ | 216 | /* if (gspca_dev->width == 1280) */ |
206 | /* data[1] = 200; * reg 60, pc-cam frame size | 217 | /* data[1] = 200; * reg 60, pc-cam frame size |
207 | * (unit: 4KB) 800KB */ | 218 | * (unit: 4KB) 800KB */ |
208 | /* else */ | 219 | /* else */ |
209 | data[1] = 50; /* 50 reg 60, pc-cam frame size | 220 | data[1] = 50; /* 50 reg 60, pc-cam frame size |
210 | * (unit: 4KB) 200KB */ | 221 | * (unit: 4KB) 200KB */ |
211 | err_code = pcam_reg_write(dev, data[0], data, 2); | 222 | err_code = reg_w(gspca_dev, data[0], 2); |
212 | if (err_code < 0) | 223 | if (err_code < 0) |
213 | return; | 224 | return; |
214 | 225 | ||
@@ -250,19 +261,20 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
250 | /* auto dark-gain */ | 261 | /* auto dark-gain */ |
251 | data[0] = 0x5e; /* address */ | 262 | data[0] = 0x5e; /* address */ |
252 | 263 | ||
253 | err_code = pcam_reg_write(dev, data[0], data, 6); | 264 | err_code = reg_w(gspca_dev, data[0], 6); |
254 | if (err_code < 0) | 265 | if (err_code < 0) |
255 | return; | 266 | return; |
256 | 267 | ||
257 | data[0] = 0x67; | 268 | data[0] = 0x67; |
258 | data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ | 269 | data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ |
259 | err_code = pcam_reg_write(dev, data[0], data, 2); | 270 | err_code = reg_w(gspca_dev, data[0], 2); |
260 | if (err_code < 0) | 271 | if (err_code < 0) |
261 | return; | 272 | return; |
262 | 273 | ||
263 | /* | 274 | /* |
264 | * initialize the value of MI sensor... | 275 | * initialize the value of MI sensor... |
265 | */ | 276 | */ |
277 | MI_buf = kzalloc(ATTR_TOTAL_MI_REG * sizeof *MI_buf, GFP_KERNEL); | ||
266 | MI_buf[REG_HW_MI_1] = 0x000a; | 278 | MI_buf[REG_HW_MI_1] = 0x000a; |
267 | MI_buf[REG_HW_MI_2] = 0x000c; | 279 | MI_buf[REG_HW_MI_2] = 0x000c; |
268 | MI_buf[REG_HW_MI_3] = 0x0405; | 280 | MI_buf[REG_HW_MI_3] = 0x0405; |
@@ -304,48 +316,48 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
304 | } | 316 | } |
305 | MI_buf[0x20] = 0x1104; | 317 | MI_buf[0x20] = 0x1104; |
306 | 318 | ||
307 | MISensor_BulkWrite(dev, MI_buf + 1, 1); | 319 | bulk_w(gspca_dev, MI_buf + 1, 1); |
308 | MISensor_BulkWrite(dev, MI_buf + 2, 2); | 320 | bulk_w(gspca_dev, MI_buf + 2, 2); |
309 | MISensor_BulkWrite(dev, MI_buf + 3, 3); | 321 | bulk_w(gspca_dev, MI_buf + 3, 3); |
310 | MISensor_BulkWrite(dev, MI_buf + 4, 4); | 322 | bulk_w(gspca_dev, MI_buf + 4, 4); |
311 | MISensor_BulkWrite(dev, MI_buf + 5, 5); | 323 | bulk_w(gspca_dev, MI_buf + 5, 5); |
312 | MISensor_BulkWrite(dev, MI_buf + 6, 6); | 324 | bulk_w(gspca_dev, MI_buf + 6, 6); |
313 | MISensor_BulkWrite(dev, MI_buf + 7, 7); | 325 | bulk_w(gspca_dev, MI_buf + 7, 7); |
314 | MISensor_BulkWrite(dev, MI_buf + 9, 9); | 326 | bulk_w(gspca_dev, MI_buf + 9, 9); |
315 | MISensor_BulkWrite(dev, MI_buf + 0x0b, 0x0b); | 327 | bulk_w(gspca_dev, MI_buf + 0x0b, 0x0b); |
316 | MISensor_BulkWrite(dev, MI_buf + 0x0c, 0x0c); | 328 | bulk_w(gspca_dev, MI_buf + 0x0c, 0x0c); |
317 | MISensor_BulkWrite(dev, MI_buf + 0x0d, 0x0d); | 329 | bulk_w(gspca_dev, MI_buf + 0x0d, 0x0d); |
318 | MISensor_BulkWrite(dev, MI_buf + 0x1e, 0x1e); | 330 | bulk_w(gspca_dev, MI_buf + 0x1e, 0x1e); |
319 | MISensor_BulkWrite(dev, MI_buf + 0x20, 0x20); | 331 | bulk_w(gspca_dev, MI_buf + 0x20, 0x20); |
320 | MISensor_BulkWrite(dev, MI_buf + 0x2b, 0x2b); | 332 | bulk_w(gspca_dev, MI_buf + 0x2b, 0x2b); |
321 | MISensor_BulkWrite(dev, MI_buf + 0x2c, 0x2c); | 333 | bulk_w(gspca_dev, MI_buf + 0x2c, 0x2c); |
322 | MISensor_BulkWrite(dev, MI_buf + 0x2d, 0x2d); | 334 | bulk_w(gspca_dev, MI_buf + 0x2d, 0x2d); |
323 | MISensor_BulkWrite(dev, MI_buf + 0x2e, 0x2e); | 335 | bulk_w(gspca_dev, MI_buf + 0x2e, 0x2e); |
324 | MISensor_BulkWrite(dev, MI_buf + 0x35, 0x35); | 336 | bulk_w(gspca_dev, MI_buf + 0x35, 0x35); |
325 | MISensor_BulkWrite(dev, MI_buf + 0x5f, 0x5f); | 337 | bulk_w(gspca_dev, MI_buf + 0x5f, 0x5f); |
326 | MISensor_BulkWrite(dev, MI_buf + 0x60, 0x60); | 338 | bulk_w(gspca_dev, MI_buf + 0x60, 0x60); |
327 | MISensor_BulkWrite(dev, MI_buf + 0x61, 0x61); | 339 | bulk_w(gspca_dev, MI_buf + 0x61, 0x61); |
328 | MISensor_BulkWrite(dev, MI_buf + 0x62, 0x62); | 340 | bulk_w(gspca_dev, MI_buf + 0x62, 0x62); |
329 | MISensor_BulkWrite(dev, MI_buf + 0x63, 0x63); | 341 | bulk_w(gspca_dev, MI_buf + 0x63, 0x63); |
330 | MISensor_BulkWrite(dev, MI_buf + 0x64, 0x64); | 342 | bulk_w(gspca_dev, MI_buf + 0x64, 0x64); |
331 | MISensor_BulkWrite(dev, MI_buf + 0xf1, 0xf1); | 343 | bulk_w(gspca_dev, MI_buf + 0xf1, 0xf1); |
332 | 344 | kfree(MI_buf); | |
333 | intpipe = usb_sndintpipe(dev, 0); | 345 | |
334 | err_code = usb_clear_halt(dev, intpipe); | 346 | intpipe = usb_sndintpipe(gspca_dev->dev, 0); |
347 | err_code = usb_clear_halt(gspca_dev->dev, intpipe); | ||
335 | 348 | ||
336 | data[0] = 0x00; | 349 | data[0] = 0x00; |
337 | data[1] = 0x4d; /* ISOC transfering enable... */ | 350 | data[1] = 0x4d; /* ISOC transfering enable... */ |
338 | pcam_reg_write(dev, data[0], data, 2); | 351 | reg_w(gspca_dev, data[0], 2); |
339 | } | 352 | } |
340 | 353 | ||
341 | static void sd_stopN(struct gspca_dev *gspca_dev) | 354 | static void sd_stopN(struct gspca_dev *gspca_dev) |
342 | { | 355 | { |
343 | int result; | 356 | int result; |
344 | __u8 data[2]; | ||
345 | 357 | ||
346 | data[0] = 1; | 358 | gspca_dev->usb_buf[0] = 1; |
347 | data[1] = 0; | 359 | gspca_dev->usb_buf[1] = 0; |
348 | result = pcam_reg_write(gspca_dev->dev, data[0], data, 2); | 360 | result = reg_w(gspca_dev, gspca_dev->usb_buf[0], 2); |
349 | if (result < 0) | 361 | if (result < 0) |
350 | PDEBUG(D_ERR, "Camera Stop failed"); | 362 | PDEBUG(D_ERR, "Camera Stop failed"); |
351 | } | 363 | } |