aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sq905.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 19:50:49 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 19:50:49 -0800
commit3e7468313758913c5e4d372f35b271b96bad1298 (patch)
treeeb612d252a9e2349a1173451cd779beebd18a33e /drivers/media/video/gspca/sq905.c
parentMerge branch 'next-i2c' of git://git.fluff.org/bjdooks/linux (diff)
parentV4L/DVB (13542): ir-keytable: Allow dynamic table change (diff)
downloadlinux-dev-3e7468313758913c5e4d372f35b271b96bad1298.tar.xz
linux-dev-3e7468313758913c5e4d372f35b271b96bad1298.zip
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (345 commits) V4L/DVB (13542): ir-keytable: Allow dynamic table change V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage V4L/DVB (13540): ir-common: Cleanup get key evdev code V4L/DVB (13539): ir-common: add __func__ for debug messages V4L/DVB (13538): ir-common: Use a dynamic keycode table V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code V4L/DVB (13534): ir-common: Remove some unused fields/structs V4L/DVB (13533): ir: use dynamic tables, instead of static ones V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it V4L/DVB (13458): go7007: subdev conversion V4L/DVB (13457): s2250: subdev conversion V4L/DVB (13456): s2250: Change module structure V4L/DVB (13528): em28xx: add support for em2800 VC211A card em28xx: don't reduce scale to half size for em2800 em28xx: don't load audio modules when AC97 is mis-detected em28xx: em2800 chips support max width of 640 V4L/DVB (13523): dvb-bt8xx: fix compile warning ... Fix up trivial conflicts due to spelling fixes from the trivial tree in Documentation/video4linux/gspca.txt drivers/media/video/cx18/cx18-mailbox.h
Diffstat (limited to 'drivers/media/video/gspca/sq905.c')
-rw-r--r--drivers/media/video/gspca/sq905.c75
1 files changed, 33 insertions, 42 deletions
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
index 715a68f0156e..1fcaca6a87f7 100644
--- a/drivers/media/video/gspca/sq905.c
+++ b/drivers/media/video/gspca/sq905.c
@@ -168,18 +168,22 @@ static int sq905_ack_frame(struct gspca_dev *gspca_dev)
* request and read a block of data - see warning on sq905_command.
*/
static int
-sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size)
+sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
{
int ret;
int act_len;
gspca_dev->usb_buf[0] = '\0';
+ if (need_lock)
+ mutex_lock(&gspca_dev->usb_lock);
ret = usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
USB_REQ_SYNCH_FRAME, /* request */
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
SQ905_BULK_READ, size, gspca_dev->usb_buf,
1, SQ905_CMD_TIMEOUT);
+ if (need_lock)
+ mutex_unlock(&gspca_dev->usb_lock);
if (ret < 0) {
PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret);
return ret;
@@ -210,11 +214,9 @@ static void sq905_dostream(struct work_struct *work)
{
struct sd *dev = container_of(work, struct sd, work_struct);
struct gspca_dev *gspca_dev = &dev->gspca_dev;
- struct gspca_frame *frame;
int bytes_left; /* bytes remaining in current frame. */
int data_len; /* size to use for the next read. */
int header_read; /* true if we have already read the frame header. */
- int discarding; /* true if we failed to get space for frame. */
int packet_type;
int frame_sz;
int ret;
@@ -222,7 +224,6 @@ static void sq905_dostream(struct work_struct *work)
u8 *buffer;
buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
- mutex_lock(&gspca_dev->usb_lock);
if (!buffer) {
PDEBUG(D_ERR, "Couldn't allocate USB buffer");
goto quit_stream;
@@ -232,28 +233,22 @@ static void sq905_dostream(struct work_struct *work)
+ FRAME_HEADER_LEN;
while (gspca_dev->present && gspca_dev->streaming) {
- /* Need a short delay to ensure streaming flag was set by
- * gspca and to make sure gspca can grab the mutex. */
- mutex_unlock(&gspca_dev->usb_lock);
- msleep(1);
-
/* request some data and then read it until we have
* a complete frame. */
bytes_left = frame_sz;
header_read = 0;
- discarding = 0;
- while (bytes_left > 0) {
+ /* Note we do not check for gspca_dev->streaming here, as
+ we must finish reading an entire frame, otherwise the
+ next time we stream we start reading in the middle of a
+ frame. */
+ while (bytes_left > 0 && gspca_dev->present) {
data_len = bytes_left > SQ905_MAX_TRANSFER ?
SQ905_MAX_TRANSFER : bytes_left;
- mutex_lock(&gspca_dev->usb_lock);
- if (!gspca_dev->present)
- goto quit_stream;
- ret = sq905_read_data(gspca_dev, buffer, data_len);
+ ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
if (ret < 0)
goto quit_stream;
- mutex_unlock(&gspca_dev->usb_lock);
- PDEBUG(D_STREAM,
+ PDEBUG(D_PACK,
"Got %d bytes out of %d for frame",
data_len, bytes_left);
bytes_left -= data_len;
@@ -270,34 +265,30 @@ static void sq905_dostream(struct work_struct *work)
} else {
packet_type = INTER_PACKET;
}
- frame = gspca_get_i_frame(gspca_dev);
- if (frame && !discarding) {
- frame = gspca_frame_add(gspca_dev, packet_type,
- frame, data, data_len);
- /* If entire frame fits in one packet we still
- need to add a LAST_PACKET */
- if (packet_type == FIRST_PACKET &&
- bytes_left == 0)
- frame = gspca_frame_add(gspca_dev,
- LAST_PACKET,
- frame, data, 0);
- } else {
- discarding = 1;
- }
+ gspca_frame_add(gspca_dev, packet_type,
+ data, data_len);
+ /* If entire frame fits in one packet we still
+ need to add a LAST_PACKET */
+ if (packet_type == FIRST_PACKET &&
+ bytes_left == 0)
+ gspca_frame_add(gspca_dev, LAST_PACKET,
+ NULL, 0);
+ }
+ if (gspca_dev->present) {
+ /* acknowledge the frame */
+ mutex_lock(&gspca_dev->usb_lock);
+ ret = sq905_ack_frame(gspca_dev);
+ mutex_unlock(&gspca_dev->usb_lock);
+ if (ret < 0)
+ goto quit_stream;
}
- /* acknowledge the frame */
- mutex_lock(&gspca_dev->usb_lock);
- if (!gspca_dev->present)
- goto quit_stream;
- ret = sq905_ack_frame(gspca_dev);
- if (ret < 0)
- goto quit_stream;
}
quit_stream:
- /* the usb_lock is already acquired */
- if (gspca_dev->present)
+ if (gspca_dev->present) {
+ mutex_lock(&gspca_dev->usb_lock);
sq905_command(gspca_dev, SQ905_CLEAR);
- mutex_unlock(&gspca_dev->usb_lock);
+ mutex_unlock(&gspca_dev->usb_lock);
+ }
kfree(buffer);
}
@@ -346,7 +337,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
ret = sq905_command(gspca_dev, SQ905_ID);
if (ret < 0)
return ret;
- ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4);
+ ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0);
if (ret < 0)
return ret;
/* usb_buf is allocated with kmalloc so is aligned.