aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sq905.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/sq905.c')
-rw-r--r--drivers/media/video/gspca/sq905.c56
1 files changed, 26 insertions, 30 deletions
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
index 715a68f0156e..547d1fd5191d 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)
168 * request and read a block of data - see warning on sq905_command. 168 * request and read a block of data - see warning on sq905_command.
169 */ 169 */
170static int 170static int
171sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size) 171sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
172{ 172{
173 int ret; 173 int ret;
174 int act_len; 174 int act_len;
175 175
176 gspca_dev->usb_buf[0] = '\0'; 176 gspca_dev->usb_buf[0] = '\0';
177 if (need_lock)
178 mutex_lock(&gspca_dev->usb_lock);
177 ret = usb_control_msg(gspca_dev->dev, 179 ret = usb_control_msg(gspca_dev->dev,
178 usb_sndctrlpipe(gspca_dev->dev, 0), 180 usb_sndctrlpipe(gspca_dev->dev, 0),
179 USB_REQ_SYNCH_FRAME, /* request */ 181 USB_REQ_SYNCH_FRAME, /* request */
180 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 182 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
181 SQ905_BULK_READ, size, gspca_dev->usb_buf, 183 SQ905_BULK_READ, size, gspca_dev->usb_buf,
182 1, SQ905_CMD_TIMEOUT); 184 1, SQ905_CMD_TIMEOUT);
185 if (need_lock)
186 mutex_unlock(&gspca_dev->usb_lock);
183 if (ret < 0) { 187 if (ret < 0) {
184 PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); 188 PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret);
185 return ret; 189 return ret;
@@ -214,7 +218,6 @@ static void sq905_dostream(struct work_struct *work)
214 int bytes_left; /* bytes remaining in current frame. */ 218 int bytes_left; /* bytes remaining in current frame. */
215 int data_len; /* size to use for the next read. */ 219 int data_len; /* size to use for the next read. */
216 int header_read; /* true if we have already read the frame header. */ 220 int header_read; /* true if we have already read the frame header. */
217 int discarding; /* true if we failed to get space for frame. */
218 int packet_type; 221 int packet_type;
219 int frame_sz; 222 int frame_sz;
220 int ret; 223 int ret;
@@ -222,7 +225,6 @@ static void sq905_dostream(struct work_struct *work)
222 u8 *buffer; 225 u8 *buffer;
223 226
224 buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); 227 buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
225 mutex_lock(&gspca_dev->usb_lock);
226 if (!buffer) { 228 if (!buffer) {
227 PDEBUG(D_ERR, "Couldn't allocate USB buffer"); 229 PDEBUG(D_ERR, "Couldn't allocate USB buffer");
228 goto quit_stream; 230 goto quit_stream;
@@ -232,28 +234,22 @@ static void sq905_dostream(struct work_struct *work)
232 + FRAME_HEADER_LEN; 234 + FRAME_HEADER_LEN;
233 235
234 while (gspca_dev->present && gspca_dev->streaming) { 236 while (gspca_dev->present && gspca_dev->streaming) {
235 /* Need a short delay to ensure streaming flag was set by
236 * gspca and to make sure gspca can grab the mutex. */
237 mutex_unlock(&gspca_dev->usb_lock);
238 msleep(1);
239
240 /* request some data and then read it until we have 237 /* request some data and then read it until we have
241 * a complete frame. */ 238 * a complete frame. */
242 bytes_left = frame_sz; 239 bytes_left = frame_sz;
243 header_read = 0; 240 header_read = 0;
244 discarding = 0;
245 241
246 while (bytes_left > 0) { 242 /* Note we do not check for gspca_dev->streaming here, as
243 we must finish reading an entire frame, otherwise the
244 next time we stream we start reading in the middle of a
245 frame. */
246 while (bytes_left > 0 && gspca_dev->present) {
247 data_len = bytes_left > SQ905_MAX_TRANSFER ? 247 data_len = bytes_left > SQ905_MAX_TRANSFER ?
248 SQ905_MAX_TRANSFER : bytes_left; 248 SQ905_MAX_TRANSFER : bytes_left;
249 mutex_lock(&gspca_dev->usb_lock); 249 ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
250 if (!gspca_dev->present)
251 goto quit_stream;
252 ret = sq905_read_data(gspca_dev, buffer, data_len);
253 if (ret < 0) 250 if (ret < 0)
254 goto quit_stream; 251 goto quit_stream;
255 mutex_unlock(&gspca_dev->usb_lock); 252 PDEBUG(D_PACK,
256 PDEBUG(D_STREAM,
257 "Got %d bytes out of %d for frame", 253 "Got %d bytes out of %d for frame",
258 data_len, bytes_left); 254 data_len, bytes_left);
259 bytes_left -= data_len; 255 bytes_left -= data_len;
@@ -271,7 +267,7 @@ static void sq905_dostream(struct work_struct *work)
271 packet_type = INTER_PACKET; 267 packet_type = INTER_PACKET;
272 } 268 }
273 frame = gspca_get_i_frame(gspca_dev); 269 frame = gspca_get_i_frame(gspca_dev);
274 if (frame && !discarding) { 270 if (frame) {
275 frame = gspca_frame_add(gspca_dev, packet_type, 271 frame = gspca_frame_add(gspca_dev, packet_type,
276 frame, data, data_len); 272 frame, data, data_len);
277 /* If entire frame fits in one packet we still 273 /* If entire frame fits in one packet we still
@@ -281,23 +277,23 @@ static void sq905_dostream(struct work_struct *work)
281 frame = gspca_frame_add(gspca_dev, 277 frame = gspca_frame_add(gspca_dev,
282 LAST_PACKET, 278 LAST_PACKET,
283 frame, data, 0); 279 frame, data, 0);
284 } else {
285 discarding = 1;
286 } 280 }
287 } 281 }
288 /* acknowledge the frame */ 282 if (gspca_dev->present) {
289 mutex_lock(&gspca_dev->usb_lock); 283 /* acknowledge the frame */
290 if (!gspca_dev->present) 284 mutex_lock(&gspca_dev->usb_lock);
291 goto quit_stream; 285 ret = sq905_ack_frame(gspca_dev);
292 ret = sq905_ack_frame(gspca_dev); 286 mutex_unlock(&gspca_dev->usb_lock);
293 if (ret < 0) 287 if (ret < 0)
294 goto quit_stream; 288 goto quit_stream;
289 }
295 } 290 }
296quit_stream: 291quit_stream:
297 /* the usb_lock is already acquired */ 292 if (gspca_dev->present) {
298 if (gspca_dev->present) 293 mutex_lock(&gspca_dev->usb_lock);
299 sq905_command(gspca_dev, SQ905_CLEAR); 294 sq905_command(gspca_dev, SQ905_CLEAR);
300 mutex_unlock(&gspca_dev->usb_lock); 295 mutex_unlock(&gspca_dev->usb_lock);
296 }
301 kfree(buffer); 297 kfree(buffer);
302} 298}
303 299
@@ -346,7 +342,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
346 ret = sq905_command(gspca_dev, SQ905_ID); 342 ret = sq905_command(gspca_dev, SQ905_ID);
347 if (ret < 0) 343 if (ret < 0)
348 return ret; 344 return ret;
349 ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4); 345 ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0);
350 if (ret < 0) 346 if (ret < 0)
351 return ret; 347 return ret;
352 /* usb_buf is allocated with kmalloc so is aligned. 348 /* usb_buf is allocated with kmalloc so is aligned.