aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-11-10 20:21:01 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:06 -0500
commita3a048cea301baba5d451991074a85dc20a8f228 (patch)
tree4dc2f79f974c1e73b6809adaebc5d849686a91d0 /drivers
parent2c94a674e059e89252d58da655efa4e798be4d48 (diff)
V4L/DVB (6582): Fix em28xx to allow multiple open
Allows shared access support for em28xx. Just one userspace application is allowed to get stream. The other(s) application(s) can change V4L2 controls, set video standards, etc. This patch were splited from Markus Rechberger's tree and backported to 2.6.17 by Pádraig Brady. The original patch were ported to the latest em28xx version and had CodingStyle corrected to solve the issues pointed by scripts/checkpatch.pl. Thanks to Pádraig Brady <P@draigBrady.com> for pointing this. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c124
-rw-r--r--drivers/media/video/em28xx/em28xx.h6
2 files changed, 79 insertions, 51 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index b43edc3fa23..5b17ca9cad1 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -234,6 +234,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
234 int minor = iminor(inode); 234 int minor = iminor(inode);
235 int errCode = 0; 235 int errCode = 0;
236 struct em28xx *h,*dev = NULL; 236 struct em28xx *h,*dev = NULL;
237 struct em28xx_fh *fh;
237 238
238 list_for_each_entry(h, &em28xx_devlist, devlist) { 239 list_for_each_entry(h, &em28xx_devlist, devlist) {
239 if (h->vdev->minor == minor) { 240 if (h->vdev->minor == minor) {
@@ -251,19 +252,17 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
251 em28xx_videodbg("open minor=%d type=%s users=%d\n", 252 em28xx_videodbg("open minor=%d type=%s users=%d\n",
252 minor,v4l2_type_names[dev->type],dev->users); 253 minor,v4l2_type_names[dev->type],dev->users);
253 254
254 mutex_lock(&dev->lock); 255 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
255 256
256 if (dev->users) { 257 if (!fh) {
257 em28xx_warn("this driver can be opened only once\n"); 258 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
258 mutex_unlock(&dev->lock); 259 return -ENOMEM;
259 return -EBUSY;
260 } 260 }
261 mutex_lock(&dev->lock);
262 fh->dev = dev;
263 filp->private_data = fh;
261 264
262 spin_lock_init(&dev->queue_lock); 265 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
263 init_waitqueue_head(&dev->wait_frame);
264 init_waitqueue_head(&dev->wait_stream);
265
266 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
267 em28xx_set_alternate(dev); 266 em28xx_set_alternate(dev);
268 267
269 dev->width = norm_maxw(dev); 268 dev->width = norm_maxw(dev);
@@ -277,26 +276,16 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
277 em28xx_capture_start(dev, 1); 276 em28xx_capture_start(dev, 1);
278 em28xx_resolution_set(dev); 277 em28xx_resolution_set(dev);
279 278
280 /* device needs to be initialized before isoc transfer */
281 video_mux(dev, 0);
282 279
283 /* start the transfer */ 280 /* start the transfer */
284 errCode = em28xx_init_isoc(dev); 281 errCode = em28xx_init_isoc(dev);
285 if (errCode) 282 if (errCode)
286 goto err; 283 goto err;
287 284
285 em28xx_empty_framequeues(dev);
288 } 286 }
289 287
290 dev->users++; 288 dev->users++;
291 filp->private_data = dev;
292 dev->io = IO_NONE;
293 dev->stream = STREAM_OFF;
294 dev->num_frames = 0;
295
296 /* prepare queues */
297 em28xx_empty_framequeues(dev);
298
299 dev->state |= DEV_INITIALIZED;
300 289
301err: 290err:
302 mutex_unlock(&dev->lock); 291 mutex_unlock(&dev->lock);
@@ -333,34 +322,41 @@ static void em28xx_release_resources(struct em28xx *dev)
333 */ 322 */
334static int em28xx_v4l2_close(struct inode *inode, struct file *filp) 323static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
335{ 324{
336 int errCode; 325 struct em28xx_fh *fh = filp->private_data;
337 struct em28xx *dev=filp->private_data; 326 struct em28xx *dev = fh->dev;
327 int errCode;
338 328
339 em28xx_videodbg("users=%d\n", dev->users); 329 em28xx_videodbg("users=%d\n", dev->users);
340 330
341 mutex_lock(&dev->lock); 331 mutex_lock(&dev->lock);
332 if (fh->reader == 1)
333 fh->reader = 0;
342 334
343 em28xx_uninit_isoc(dev); 335 if (dev->users == 1) {
336 dev->reader = 0;
344 337
345 em28xx_release_buffers(dev); 338 em28xx_uninit_isoc(dev);
339 em28xx_release_buffers(dev);
346 340
347 /* the device is already disconnect, free the remaining resources */ 341 /* the device is already disconnect,
348 if (dev->state & DEV_DISCONNECTED) { 342 free the remaining resources */
349 em28xx_release_resources(dev); 343 if (dev->state & DEV_DISCONNECTED) {
350 mutex_unlock(&dev->lock); 344 em28xx_release_resources(dev);
351 kfree(dev); 345 mutex_unlock(&dev->lock);
352 return 0; 346 kfree(dev);
353 } 347 return 0;
348 }
354 349
355 /* set alternate 0 */ 350 /* set alternate 0 */
356 dev->alt = 0; 351 dev->alt = 0;
357 em28xx_videodbg("setting alternate 0\n"); 352 em28xx_videodbg("setting alternate 0\n");
358 errCode = usb_set_interface(dev->udev, 0, 0); 353 errCode = usb_set_interface(dev->udev, 0, 0);
359 if (errCode < 0) { 354 if (errCode < 0) {
360 em28xx_errdev ("cannot change alternate number to 0 (error=%i)\n", 355 em28xx_errdev("cannot change alternate number to "
361 errCode); 356 "0 (error=%i)\n", errCode);
357 }
362 } 358 }
363 359 kfree(fh);
364 dev->users--; 360 dev->users--;
365 wake_up_interruptible_nr(&dev->open, 1); 361 wake_up_interruptible_nr(&dev->open, 1);
366 mutex_unlock(&dev->lock); 362 mutex_unlock(&dev->lock);
@@ -378,13 +374,19 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
378 struct em28xx_frame_t *f, *i; 374 struct em28xx_frame_t *f, *i;
379 unsigned long lock_flags; 375 unsigned long lock_flags;
380 int ret = 0; 376 int ret = 0;
381 struct em28xx *dev = filp->private_data; 377 struct em28xx_fh *fh = filp->private_data;
378 struct em28xx *dev = fh->dev;
382 379
383 mutex_lock(&dev->lock); 380 mutex_lock(&dev->lock);
384 381
385 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 382 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
386 em28xx_videodbg("V4l2_Buf_type_videocapture is set\n"); 383 em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
384
385 if (dev->reader > 0 && fh->reader == 0) {
386 mutex_unlock(&dev->lock);
387 return -EBUSY;
387 } 388 }
389
388 if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 390 if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
389 em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); 391 em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
390 em28xx_videodbg("not supported yet! ...\n"); 392 em28xx_videodbg("not supported yet! ...\n");
@@ -423,6 +425,9 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
423 " the device again to choose the read method\n"); 425 " the device again to choose the read method\n");
424 mutex_unlock(&dev->lock); 426 mutex_unlock(&dev->lock);
425 return -EINVAL; 427 return -EINVAL;
428 } else {
429 dev->reader = 1;
430 fh->reader = 1;
426 } 431 }
427 432
428 if (dev->io == IO_NONE) { 433 if (dev->io == IO_NONE) {
@@ -491,7 +496,8 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
491static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) 496static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
492{ 497{
493 unsigned int mask = 0; 498 unsigned int mask = 0;
494 struct em28xx *dev = filp->private_data; 499 struct em28xx_fh *fh = filp->private_data;
500 struct em28xx *dev = fh->dev;
495 501
496 mutex_lock(&dev->lock); 502 mutex_lock(&dev->lock);
497 503
@@ -559,15 +565,23 @@ static struct vm_operations_struct em28xx_vm_ops = {
559 */ 565 */
560static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) 566static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
561{ 567{
562 unsigned long size = vma->vm_end - vma->vm_start, 568 struct em28xx_fh *fh = filp->private_data;
563 start = vma->vm_start; 569 struct em28xx *dev = fh->dev;
564 void *pos; 570 unsigned long size = vma->vm_end - vma->vm_start;
565 u32 i; 571 unsigned long start = vma->vm_start;
566 572 void *pos;
567 struct em28xx *dev = filp->private_data; 573 u32 i;
568 574
569 mutex_lock(&dev->lock); 575 mutex_lock(&dev->lock);
570 576
577 if (dev->reader > 0 && fh->reader == 0) {
578 mutex_unlock(&dev->lock);
579 return -EBUSY;
580 } else {
581 dev->reader = 1;
582 fh->reader = 1;
583 }
584
571 if (dev->state & DEV_DISCONNECTED) { 585 if (dev->state & DEV_DISCONNECTED) {
572 em28xx_videodbg("mmap: device not present\n"); 586 em28xx_videodbg("mmap: device not present\n");
573 mutex_unlock(&dev->lock); 587 mutex_unlock(&dev->lock);
@@ -918,6 +932,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
918 struct em28xx *dev, unsigned int cmd, void *arg, 932 struct em28xx *dev, unsigned int cmd, void *arg,
919 v4l2_kioctl driver_ioctl) 933 v4l2_kioctl driver_ioctl)
920{ 934{
935 struct em28xx_fh *fh = filp->private_data;
921 int ret; 936 int ret;
922 937
923 switch (cmd) { 938 switch (cmd) {
@@ -1227,6 +1242,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1227 return ret; 1242 return ret;
1228 } 1243 }
1229 } 1244 }
1245
1246 fh->reader = 0;
1230 em28xx_empty_framequeues(dev); 1247 em28xx_empty_framequeues(dev);
1231 mutex_unlock(&dev->lock); 1248 mutex_unlock(&dev->lock);
1232 1249
@@ -1248,7 +1265,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1248static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, 1265static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,
1249 unsigned int cmd, void *arg) 1266 unsigned int cmd, void *arg)
1250{ 1267{
1251 struct em28xx *dev = filp->private_data; 1268 struct em28xx_fh *fh = filp->private_data;
1269 struct em28xx *dev = fh->dev;
1252 1270
1253 if (!dev) 1271 if (!dev)
1254 return -ENODEV; 1272 return -ENODEV;
@@ -1456,7 +1474,8 @@ static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp,
1456 unsigned int cmd, unsigned long arg) 1474 unsigned int cmd, unsigned long arg)
1457{ 1475{
1458 int ret = 0; 1476 int ret = 0;
1459 struct em28xx *dev = filp->private_data; 1477 struct em28xx_fh *fh = filp->private_data;
1478 struct em28xx *dev = fh->dev;
1460 1479
1461 if (dev->state & DEV_DISCONNECTED) { 1480 if (dev->state & DEV_DISCONNECTED) {
1462 em28xx_errdev("v4l2 ioctl: device not present\n"); 1481 em28xx_errdev("v4l2 ioctl: device not present\n");
@@ -1503,7 +1522,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1503 1522
1504 dev->udev = udev; 1523 dev->udev = udev;
1505 mutex_init(&dev->lock); 1524 mutex_init(&dev->lock);
1525 spin_lock_init(&dev->queue_lock);
1506 init_waitqueue_head(&dev->open); 1526 init_waitqueue_head(&dev->open);
1527 init_waitqueue_head(&dev->wait_frame);
1528 init_waitqueue_head(&dev->wait_stream);
1507 1529
1508 dev->em28xx_write_regs = em28xx_write_regs; 1530 dev->em28xx_write_regs = em28xx_write_regs;
1509 dev->em28xx_read_reg = em28xx_read_reg; 1531 dev->em28xx_read_reg = em28xx_read_reg;
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index c2531da2e61..f8ad0f4ae6d 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -258,6 +258,7 @@ struct em28xx {
258 int vscale; /* vertical scale factor (see datasheet) */ 258 int vscale; /* vertical scale factor (see datasheet) */
259 int interlaced; /* 1=interlace fileds, 0=just top fileds */ 259 int interlaced; /* 1=interlace fileds, 0=just top fileds */
260 int type; 260 int type;
261 unsigned int reader:1;
261 262
262 unsigned long hash; /* eeprom hash - for boards with generic ID */ 263 unsigned long hash; /* eeprom hash - for boards with generic ID */
263 unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */ 264 unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */
@@ -294,6 +295,11 @@ struct em28xx {
294 int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg); 295 int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg);
295}; 296};
296 297
298struct em28xx_fh {
299 struct em28xx *dev;
300 unsigned int reader:1;
301};
302
297/* Provided by em28xx-i2c.c */ 303/* Provided by em28xx-i2c.c */
298 304
299void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg); 305void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg);