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/spca561.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/spca561.c')
-rw-r--r-- | drivers/media/video/gspca/spca561.c | 115 |
1 files changed, 61 insertions, 54 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index f0770ee595d8..b659bd0f788d 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -24,8 +24,8 @@ | |||
24 | 24 | ||
25 | #include "gspca.h" | 25 | #include "gspca.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/SPCA561 USB Camera Driver"); | 31 | MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver"); |
@@ -177,27 +177,28 @@ static void write_vector(struct gspca_dev *gspca_dev, | |||
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
180 | static void reg_r(struct usb_device *dev, | 180 | /* read 'len' bytes to gspca_dev->usb_buf */ |
181 | __u16 index, __u8 *buffer, __u16 length) | 181 | static void reg_r(struct gspca_dev *gspca_dev, |
182 | __u16 index, __u16 length) | ||
182 | { | 183 | { |
183 | usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 184 | usb_control_msg(gspca_dev->dev, |
185 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
184 | 0, /* request */ | 186 | 0, /* request */ |
185 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 187 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
186 | 0, /* value */ | 188 | 0, /* value */ |
187 | index, buffer, length, 500); | 189 | index, gspca_dev->usb_buf, length, 500); |
188 | } | 190 | } |
189 | 191 | ||
190 | static void reg_w_buf(struct usb_device *dev, | 192 | static void reg_w_buf(struct gspca_dev *gspca_dev, |
191 | __u16 index, const __u8 *buffer, __u16 len) | 193 | __u16 index, const __u8 *buffer, __u16 len) |
192 | { | 194 | { |
193 | __u8 tmpbuf[8]; | 195 | memcpy(gspca_dev->usb_buf, buffer, len); |
194 | 196 | usb_control_msg(gspca_dev->dev, | |
195 | memcpy(tmpbuf, buffer, len); | 197 | usb_sndctrlpipe(gspca_dev->dev, 0), |
196 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
197 | 0, /* request */ | 198 | 0, /* request */ |
198 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 199 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
199 | 0, /* value */ | 200 | 0, /* value */ |
200 | index, tmpbuf, len, 500); | 201 | index, gspca_dev->usb_buf, len, 500); |
201 | } | 202 | } |
202 | 203 | ||
203 | static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode) | 204 | static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode) |
@@ -211,7 +212,6 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg) | |||
211 | int retry = 60; | 212 | int retry = 60; |
212 | __u8 DataLow; | 213 | __u8 DataLow; |
213 | __u8 DataHight; | 214 | __u8 DataHight; |
214 | __u8 Data; | ||
215 | 215 | ||
216 | DataLow = valeur; | 216 | DataLow = valeur; |
217 | DataHight = valeur >> 8; | 217 | DataHight = valeur >> 8; |
@@ -219,8 +219,8 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg) | |||
219 | reg_w_val(gspca_dev->dev, DataLow, 0x8805); | 219 | reg_w_val(gspca_dev->dev, DataLow, 0x8805); |
220 | reg_w_val(gspca_dev->dev, DataHight, 0x8800); | 220 | reg_w_val(gspca_dev->dev, DataHight, 0x8800); |
221 | while (retry--) { | 221 | while (retry--) { |
222 | reg_r(gspca_dev->dev, 0x8803, &Data, 1); | 222 | reg_r(gspca_dev, 0x8803, 1); |
223 | if (!Data) | 223 | if (!gspca_dev->usb_buf[0]) |
224 | break; | 224 | break; |
225 | } | 225 | } |
226 | } | 226 | } |
@@ -230,20 +230,21 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode) | |||
230 | int retry = 60; | 230 | int retry = 60; |
231 | __u8 value; | 231 | __u8 value; |
232 | __u8 vallsb; | 232 | __u8 vallsb; |
233 | __u8 Data; | ||
234 | 233 | ||
235 | reg_w_val(gspca_dev->dev, 0x92, 0x8804); | 234 | reg_w_val(gspca_dev->dev, 0x92, 0x8804); |
236 | reg_w_val(gspca_dev->dev, reg, 0x8801); | 235 | reg_w_val(gspca_dev->dev, reg, 0x8801); |
237 | reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802); | 236 | reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802); |
238 | while (retry--) { | 237 | while (retry--) { |
239 | reg_r(gspca_dev->dev, 0x8803, &Data, 1); | 238 | reg_r(gspca_dev, 0x8803, 1); |
240 | if (!Data) | 239 | if (!gspca_dev->usb_buf) |
241 | break; | 240 | break; |
242 | } | 241 | } |
243 | if (retry == 0) | 242 | if (retry == 0) |
244 | return -1; | 243 | return -1; |
245 | reg_r(gspca_dev->dev, 0x8800, &value, 1); | 244 | reg_r(gspca_dev, 0x8800, 1); |
246 | reg_r(gspca_dev->dev, 0x8805, &vallsb, 1); | 245 | value = gspca_dev->usb_buf[0]; |
246 | reg_r(gspca_dev, 0x8805, 1); | ||
247 | vallsb = gspca_dev->usb_buf[0]; | ||
247 | return ((int) value << 8) | vallsb; | 248 | return ((int) value << 8) | vallsb; |
248 | } | 249 | } |
249 | 250 | ||
@@ -541,7 +542,7 @@ static void sensor_mapwrite(struct gspca_dev *gspca_dev, | |||
541 | while (sensormap[i][0]) { | 542 | while (sensormap[i][0]) { |
542 | usbval[0] = sensormap[i][1]; | 543 | usbval[0] = sensormap[i][1]; |
543 | usbval[1] = sensormap[i][1] >> 8; | 544 | usbval[1] = sensormap[i][1] >> 8; |
544 | reg_w_buf(gspca_dev->dev, sensormap[i][0], usbval, 2); | 545 | reg_w_buf(gspca_dev, sensormap[i][0], usbval, 2); |
545 | i++; | 546 | i++; |
546 | } | 547 | } |
547 | } | 548 | } |
@@ -559,7 +560,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
559 | const struct usb_device_id *id) | 560 | const struct usb_device_id *id) |
560 | { | 561 | { |
561 | struct sd *sd = (struct sd *) gspca_dev; | 562 | struct sd *sd = (struct sd *) gspca_dev; |
562 | struct usb_device *dev = gspca_dev->dev; | ||
563 | struct cam *cam; | 563 | struct cam *cam; |
564 | __u16 vendor, product; | 564 | __u16 vendor, product; |
565 | __u8 data1, data2; | 565 | __u8 data1, data2; |
@@ -568,11 +568,15 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
568 | * prove that we can communicate with the device. This works, which | 568 | * prove that we can communicate with the device. This works, which |
569 | * confirms at we are communicating properly and that the device | 569 | * confirms at we are communicating properly and that the device |
570 | * is a 561. */ | 570 | * is a 561. */ |
571 | reg_r(dev, 0x8104, &data1, 1); | 571 | reg_r(gspca_dev, 0x8104, 1); |
572 | reg_r(dev, 0x8105, &data2, 1); | 572 | data1 = gspca_dev->usb_buf[0]; |
573 | reg_r(gspca_dev, 0x8105, 1); | ||
574 | data2 = gspca_dev->usb_buf[0]; | ||
573 | vendor = (data2 << 8) | data1; | 575 | vendor = (data2 << 8) | data1; |
574 | reg_r(dev, 0x8106, &data1, 1); | 576 | reg_r(gspca_dev, 0x8106, 1); |
575 | reg_r(dev, 0x8107, &data2, 1); | 577 | data1 = gspca_dev->usb_buf[0]; |
578 | reg_r(gspca_dev, 0x8107, 1); | ||
579 | data2 = gspca_dev->usb_buf[0]; | ||
576 | product = (data2 << 8) | data1; | 580 | product = (data2 << 8) | data1; |
577 | if (vendor != id->idVendor || product != id->idProduct) { | 581 | if (vendor != id->idVendor || product != id->idProduct) { |
578 | PDEBUG(D_PROBE, "Bad vendor / product from device"); | 582 | PDEBUG(D_PROBE, "Bad vendor / product from device"); |
@@ -656,8 +660,8 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
656 | Reg8391[0] = expotimes & 0xff; /* exposure */ | 660 | Reg8391[0] = expotimes & 0xff; /* exposure */ |
657 | Reg8391[1] = 0x18 | (expotimes >> 8); | 661 | Reg8391[1] = 0x18 | (expotimes >> 8); |
658 | Reg8391[2] = sd->brightness; /* gain */ | 662 | Reg8391[2] = sd->brightness; /* gain */ |
659 | reg_w_buf(dev, 0x8391, Reg8391, 8); | 663 | reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); |
660 | reg_w_buf(dev, 0x8390, Reg8391, 8); | 664 | reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); |
661 | break; | 665 | break; |
662 | } | 666 | } |
663 | } | 667 | } |
@@ -714,10 +718,11 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
714 | * is sufficient to push raw frames at ~20fps */ | 718 | * is sufficient to push raw frames at ~20fps */ |
715 | reg_w_val(dev, 0x8500, mode); | 719 | reg_w_val(dev, 0x8500, mode); |
716 | } /* -- qq@kuku.eu.org */ | 720 | } /* -- qq@kuku.eu.org */ |
717 | reg_w_buf(dev, 0x8307, Reg8307, 2); | 721 | reg_w_buf(gspca_dev, 0x8307, Reg8307, 2); |
718 | reg_w_val(dev, 0x8700, Clck); /* 0x8f 0x85 0x27 clock */ | 722 | reg_w_val(gspca_dev->dev, 0x8700, Clck); |
719 | reg_w_val(dev, 0x8112, 0x1e | 0x20); | 723 | /* 0x8f 0x85 0x27 clock */ |
720 | reg_w_val(dev, 0x850b, 0x03); | 724 | reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); |
725 | reg_w_val(gspca_dev->dev, 0x850b, 0x03); | ||
721 | setcontrast(gspca_dev); | 726 | setcontrast(gspca_dev); |
722 | break; | 727 | break; |
723 | } | 728 | } |
@@ -752,10 +757,14 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
752 | 757 | ||
753 | switch (sd->chip_revision) { | 758 | switch (sd->chip_revision) { |
754 | case Rev072A: | 759 | case Rev072A: |
755 | reg_r(gspca_dev->dev, 0x8621, &Gr, 1); | 760 | reg_r(gspca_dev, 0x8621, 1); |
756 | reg_r(gspca_dev->dev, 0x8622, &R, 1); | 761 | Gr = gspca_dev->usb_buf[0]; |
757 | reg_r(gspca_dev->dev, 0x8623, &B, 1); | 762 | reg_r(gspca_dev, 0x8622, 1); |
758 | reg_r(gspca_dev->dev, 0x8624, &Gb, 1); | 763 | R = gspca_dev->usb_buf[0]; |
764 | reg_r(gspca_dev, 0x8623, 1); | ||
765 | B = gspca_dev->usb_buf[0]; | ||
766 | reg_r(gspca_dev, 0x8624, 1); | ||
767 | Gb = gspca_dev->usb_buf[0]; | ||
759 | y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8; | 768 | y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8; |
760 | /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */ | 769 | /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */ |
761 | /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */ | 770 | /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */ |
@@ -867,20 +876,19 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
867 | static void getbrightness(struct gspca_dev *gspca_dev) | 876 | static void getbrightness(struct gspca_dev *gspca_dev) |
868 | { | 877 | { |
869 | struct sd *sd = (struct sd *) gspca_dev; | 878 | struct sd *sd = (struct sd *) gspca_dev; |
870 | __u8 value; | ||
871 | __u16 tot; | 879 | __u16 tot; |
872 | 880 | ||
873 | switch (sd->chip_revision) { | 881 | switch (sd->chip_revision) { |
874 | case Rev072A: | 882 | case Rev072A: |
875 | tot = 0; | 883 | tot = 0; |
876 | reg_r(gspca_dev->dev, 0x8611, &value, 1); | 884 | reg_r(gspca_dev, 0x8611, 1); |
877 | tot += value; | 885 | tot += gspca_dev->usb_buf[0]; |
878 | reg_r(gspca_dev->dev, 0x8612, &value, 1); | 886 | reg_r(gspca_dev, 0x8612, 1); |
879 | tot += value; | 887 | tot += gspca_dev->usb_buf[0]; |
880 | reg_r(gspca_dev->dev, 0x8613, &value, 1); | 888 | reg_r(gspca_dev, 0x8613, 1); |
881 | tot += value; | 889 | tot += gspca_dev->usb_buf[0]; |
882 | reg_r(gspca_dev->dev, 0x8614, &value, 1); | 890 | reg_r(gspca_dev, 0x8614, 1); |
883 | tot += value; | 891 | tot += gspca_dev->usb_buf[0]; |
884 | sd->brightness = tot >> 2; | 892 | sd->brightness = tot >> 2; |
885 | break; | 893 | break; |
886 | default: | 894 | default: |
@@ -893,20 +901,19 @@ static void getbrightness(struct gspca_dev *gspca_dev) | |||
893 | static void getcontrast(struct gspca_dev *gspca_dev) | 901 | static void getcontrast(struct gspca_dev *gspca_dev) |
894 | { | 902 | { |
895 | struct sd *sd = (struct sd *) gspca_dev; | 903 | struct sd *sd = (struct sd *) gspca_dev; |
896 | __u8 value; | ||
897 | __u16 tot; | 904 | __u16 tot; |
898 | 905 | ||
899 | switch (sd->chip_revision) { | 906 | switch (sd->chip_revision) { |
900 | case Rev072A: | 907 | case Rev072A: |
901 | tot = 0; | 908 | tot = 0; |
902 | reg_r(gspca_dev->dev, 0x8651, &value, 1); | 909 | reg_r(gspca_dev, 0x8651, 1); |
903 | tot += value; | 910 | tot += gspca_dev->usb_buf[0]; |
904 | reg_r(gspca_dev->dev, 0x8652, &value, 1); | 911 | reg_r(gspca_dev, 0x8652, 1); |
905 | tot += value; | 912 | tot += gspca_dev->usb_buf[0]; |
906 | reg_r(gspca_dev->dev, 0x8653, &value, 1); | 913 | reg_r(gspca_dev, 0x8653, 1); |
907 | tot += value; | 914 | tot += gspca_dev->usb_buf[0]; |
908 | reg_r(gspca_dev->dev, 0x8654, &value, 1); | 915 | reg_r(gspca_dev, 0x8654, 1); |
909 | tot += value; | 916 | tot += gspca_dev->usb_buf[0]; |
910 | sd->contrast = tot << 6; | 917 | sd->contrast = tot << 6; |
911 | break; | 918 | break; |
912 | default: | 919 | default: |