2008-09-29 13:59:36 +04:00
/*
* Fujifilm Finepix subdriver
*
* Copyright ( C ) 2008 Frank Zago
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2011-08-22 02:56:53 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2008-09-29 13:59:36 +04:00
# define MODULE_NAME "finepix"
# include "gspca.h"
MODULE_AUTHOR ( " Frank Zago <frank@zago.net> " ) ;
MODULE_DESCRIPTION ( " Fujifilm FinePix USB V4L2 driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
/* Default timeout, in ms */
2009-03-26 11:06:50 +03:00
# define FPIX_TIMEOUT 250
2008-09-29 13:59:36 +04:00
/* Maximum transfer size to use. The windows driver reads by chunks of
* 0x2000 bytes , so do the same . Note : reading more seems to work
* too . */
# define FPIX_MAX_TRANSFER 0x2000
/* Structure to hold all of our device specific stuff */
struct usb_fpix {
struct gspca_dev gspca_dev ; /* !! must be the first item */
2009-03-26 11:06:50 +03:00
struct work_struct work_struct ;
struct workqueue_struct * work_thread ;
2008-09-29 13:59:36 +04:00
} ;
/* Delay after which claim the next frame. If the delay is too small,
* the camera will return old frames . On the 4800 Z , 20 ms is bad , 25 ms
2009-03-26 11:06:50 +03:00
* will fail every 4 or 5 frames , but 30 ms is perfect . On the A210 ,
* 30 ms is bad while 35 ms is perfect . */
# define NEXT_FRAME_DELAY 35
2008-09-29 13:59:36 +04:00
/* These cameras only support 320x200. */
2008-12-29 13:49:41 +03:00
static const struct v4l2_pix_format fpix_mode [ 1 ] = {
2008-09-29 13:59:36 +04:00
{ 320 , 240 , V4L2_PIX_FMT_JPEG , V4L2_FIELD_NONE ,
. bytesperline = 320 ,
. sizeimage = 320 * 240 * 3 / 8 + 590 ,
. colorspace = V4L2_COLORSPACE_SRGB ,
. priv = 0 }
} ;
2009-03-26 11:06:50 +03:00
/* send a command to the webcam */
static int command ( struct gspca_dev * gspca_dev ,
int order ) /* 0: reset, 1: frame request */
2008-09-29 13:59:36 +04:00
{
2009-03-26 11:06:50 +03:00
static u8 order_values [ 2 ] [ 12 ] = {
{ 0xc6 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x20 , 0 , 0 , 0 } , /* reset */
{ 0xd3 , 0 , 0 , 0 , 0 , 0 , 0 , 0x01 , 0 , 0 , 0 , 0 } , /* fr req */
} ;
2008-09-29 13:59:36 +04:00
2009-03-26 11:06:50 +03:00
memcpy ( gspca_dev - > usb_buf , order_values [ order ] , 12 ) ;
return usb_control_msg ( gspca_dev - > dev ,
usb_sndctrlpipe ( gspca_dev - > dev , 0 ) ,
USB_REQ_GET_STATUS ,
USB_DIR_OUT | USB_TYPE_CLASS |
USB_RECIP_INTERFACE , 0 , 0 , gspca_dev - > usb_buf ,
12 , FPIX_TIMEOUT ) ;
2008-09-29 13:59:36 +04:00
}
2012-09-09 14:30:02 +04:00
/*
* This function is called as a workqueue function and runs whenever the camera
* is streaming data . Because it is a workqueue function it is allowed to sleep
* so we can use synchronous USB calls . To avoid possible collisions with other
* threads attempting to use gspca_dev - > usb_buf we take the usb_lock when
* performing USB operations using it . In practice we don ' t really need this
* as the camera doesn ' t provide any controls .
*/
2009-03-26 11:06:50 +03:00
static void dostream ( struct work_struct * work )
2008-09-29 13:59:36 +04:00
{
2009-03-26 11:06:50 +03:00
struct usb_fpix * dev = container_of ( work , struct usb_fpix , work_struct ) ;
struct gspca_dev * gspca_dev = & dev - > gspca_dev ;
struct urb * urb = gspca_dev - > urb [ 0 ] ;
u8 * data = urb - > transfer_buffer ;
int ret = 0 ;
int len ;
PDEBUG ( D_STREAM , " dostream started " ) ;
/* loop reading a frame */
again :
[media] gspca: Don't set gspca_dev->dev to NULL before stop0
In commit a3d6e8cc0e6ddc8b3cfdeb3c979f07ed1aa528b3 gspca_dev->dev is set
to NULL on disconnect, before calling stop0. The plan was to get rid of
gspca_dev->present and instead simply check for gspca_dev->dev everywhere
where we were checking for present. This should be race free since all users
of gspca_dev->dev hold the usb_lock, or so I thought.
But I was wrong, drivers which use a work-queue + synchronous bulk transfers
to get the video data don't hold the usb_lock while doing so, their stop0
callbacks stop the workqueue, so they won't be using gspca_dev->dev anymore
after the stop0 call, but they might be dereferincing it before, so we should
not set gspca_dev->dev to NULL on disconnect before calling stop0.
This also means that the workqueue functions in these drivers cannot
use gspca_dev->dev to check if they need to stop because of disconnection,
so we will need to keep gspca_dev->present around, and set that to 0 on
disconnect, before calling stop0. Unfortunately as part of the plan to remove
gspca_dev->present, these workqueues where already moved over to checking
for gspca_dev->dev instead of gspca_dev->present as part of commit
254902b01d2acc6aced99ec17caa4c6cd890cdea, so this patch also reverts those
parts of that commit.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2012-09-09 13:30:02 +04:00
while ( gspca_dev - > present & & gspca_dev - > streaming ) {
2012-05-18 15:40:42 +04:00
# ifdef CONFIG_PM
if ( gspca_dev - > frozen )
break ;
# endif
2009-03-26 11:06:50 +03:00
/* request a frame */
mutex_lock ( & gspca_dev - > usb_lock ) ;
ret = command ( gspca_dev , 1 ) ;
mutex_unlock ( & gspca_dev - > usb_lock ) ;
if ( ret < 0 )
break ;
2012-05-18 15:40:42 +04:00
# ifdef CONFIG_PM
if ( gspca_dev - > frozen )
break ;
# endif
[media] gspca: Don't set gspca_dev->dev to NULL before stop0
In commit a3d6e8cc0e6ddc8b3cfdeb3c979f07ed1aa528b3 gspca_dev->dev is set
to NULL on disconnect, before calling stop0. The plan was to get rid of
gspca_dev->present and instead simply check for gspca_dev->dev everywhere
where we were checking for present. This should be race free since all users
of gspca_dev->dev hold the usb_lock, or so I thought.
But I was wrong, drivers which use a work-queue + synchronous bulk transfers
to get the video data don't hold the usb_lock while doing so, their stop0
callbacks stop the workqueue, so they won't be using gspca_dev->dev anymore
after the stop0 call, but they might be dereferincing it before, so we should
not set gspca_dev->dev to NULL on disconnect before calling stop0.
This also means that the workqueue functions in these drivers cannot
use gspca_dev->dev to check if they need to stop because of disconnection,
so we will need to keep gspca_dev->present around, and set that to 0 on
disconnect, before calling stop0. Unfortunately as part of the plan to remove
gspca_dev->present, these workqueues where already moved over to checking
for gspca_dev->dev instead of gspca_dev->present as part of commit
254902b01d2acc6aced99ec17caa4c6cd890cdea, so this patch also reverts those
parts of that commit.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2012-09-09 13:30:02 +04:00
if ( ! gspca_dev - > present | | ! gspca_dev - > streaming )
2009-03-26 11:06:50 +03:00
break ;
/* the frame comes in parts */
for ( ; ; ) {
ret = usb_bulk_msg ( gspca_dev - > dev ,
urb - > pipe ,
data ,
FPIX_MAX_TRANSFER ,
& len , FPIX_TIMEOUT ) ;
if ( ret < 0 ) {
/* Most of the time we get a timeout
* error . Just restart . */
goto again ;
}
2012-05-18 15:40:42 +04:00
# ifdef CONFIG_PM
if ( gspca_dev - > frozen )
goto out ;
# endif
[media] gspca: Don't set gspca_dev->dev to NULL before stop0
In commit a3d6e8cc0e6ddc8b3cfdeb3c979f07ed1aa528b3 gspca_dev->dev is set
to NULL on disconnect, before calling stop0. The plan was to get rid of
gspca_dev->present and instead simply check for gspca_dev->dev everywhere
where we were checking for present. This should be race free since all users
of gspca_dev->dev hold the usb_lock, or so I thought.
But I was wrong, drivers which use a work-queue + synchronous bulk transfers
to get the video data don't hold the usb_lock while doing so, their stop0
callbacks stop the workqueue, so they won't be using gspca_dev->dev anymore
after the stop0 call, but they might be dereferincing it before, so we should
not set gspca_dev->dev to NULL on disconnect before calling stop0.
This also means that the workqueue functions in these drivers cannot
use gspca_dev->dev to check if they need to stop because of disconnection,
so we will need to keep gspca_dev->present around, and set that to 0 on
disconnect, before calling stop0. Unfortunately as part of the plan to remove
gspca_dev->present, these workqueues where already moved over to checking
for gspca_dev->dev instead of gspca_dev->present as part of commit
254902b01d2acc6aced99ec17caa4c6cd890cdea, so this patch also reverts those
parts of that commit.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2012-09-09 13:30:02 +04:00
if ( ! gspca_dev - > present | | ! gspca_dev - > streaming )
2009-03-26 11:06:50 +03:00
goto out ;
if ( len < FPIX_MAX_TRANSFER | |
( data [ len - 2 ] = = 0xff & &
data [ len - 1 ] = = 0xd9 ) ) {
/* If the result is less than what was asked
* for , then it ' s the end of the
* frame . Sometimes the jpeg is not complete ,
* but there ' s nothing we can do . We also end
* here if the the jpeg ends right at the end
* of the frame . */
2009-11-13 15:21:03 +03:00
gspca_frame_add ( gspca_dev , LAST_PACKET ,
data , len ) ;
2009-03-26 11:06:50 +03:00
break ;
}
2008-09-29 13:59:36 +04:00
/* got a partial image */
2009-11-13 15:21:03 +03:00
gspca_frame_add ( gspca_dev ,
gspca_dev - > last_packet_type
= = LAST_PACKET
? FIRST_PACKET : INTER_PACKET ,
data , len ) ;
2008-09-29 13:59:36 +04:00
}
2009-03-26 11:06:50 +03:00
/* We must wait before trying reading the next
* frame . If we don ' t , or if the delay is too short ,
* the camera will disconnect . */
msleep ( NEXT_FRAME_DELAY ) ;
2008-09-29 13:59:36 +04:00
}
2009-03-26 11:06:50 +03:00
out :
PDEBUG ( D_STREAM , " dostream stopped " ) ;
2008-09-29 13:59:36 +04:00
}
/* this function is called at probe time */
static int sd_config ( struct gspca_dev * gspca_dev ,
const struct usb_device_id * id )
{
2009-03-26 11:06:50 +03:00
struct usb_fpix * dev = ( struct usb_fpix * ) gspca_dev ;
2008-09-29 13:59:36 +04:00
struct cam * cam = & gspca_dev - > cam ;
cam - > cam_mode = fpix_mode ;
cam - > nmodes = 1 ;
2009-04-21 20:45:56 +04:00
cam - > bulk = 1 ;
2008-09-29 13:59:36 +04:00
cam - > bulk_size = FPIX_MAX_TRANSFER ;
2009-03-26 11:06:50 +03:00
INIT_WORK ( & dev - > work_struct , dostream ) ;
2008-09-29 13:59:36 +04:00
2009-03-26 11:06:50 +03:00
return 0 ;
2008-09-29 13:59:36 +04:00
}
/* this function is called at probe and resume time */
static int sd_init ( struct gspca_dev * gspca_dev )
{
return 0 ;
}
2009-03-26 11:06:50 +03:00
/* start the camera */
2008-09-29 13:59:36 +04:00
static int sd_start ( struct gspca_dev * gspca_dev )
{
struct usb_fpix * dev = ( struct usb_fpix * ) gspca_dev ;
2009-03-26 11:06:50 +03:00
int ret , len ;
2008-09-29 13:59:36 +04:00
/* Init the device */
2009-03-26 11:06:50 +03:00
ret = command ( gspca_dev , 0 ) ;
if ( ret < 0 ) {
2011-08-22 02:56:53 +04:00
pr_err ( " init failed %d \n " , ret ) ;
2009-03-26 11:06:50 +03:00
return ret ;
2008-09-29 13:59:36 +04:00
}
/* Read the result of the command. Ignore the result, for it
* varies with the device . */
ret = usb_bulk_msg ( gspca_dev - > dev ,
2008-12-31 14:13:46 +03:00
gspca_dev - > urb [ 0 ] - > pipe ,
2009-03-26 11:06:50 +03:00
gspca_dev - > urb [ 0 ] - > transfer_buffer ,
FPIX_MAX_TRANSFER , & len ,
2008-09-29 13:59:36 +04:00
FPIX_TIMEOUT ) ;
2009-03-26 11:06:50 +03:00
if ( ret < 0 ) {
2011-08-22 02:56:53 +04:00
pr_err ( " usb_bulk_msg failed %d \n " , ret ) ;
2009-03-26 11:06:50 +03:00
return ret ;
2008-09-29 13:59:36 +04:00
}
/* Request a frame, but don't read it */
2009-03-26 11:06:50 +03:00
ret = command ( gspca_dev , 1 ) ;
if ( ret < 0 ) {
2011-08-22 02:56:53 +04:00
pr_err ( " frame request failed %d \n " , ret ) ;
2009-03-26 11:06:50 +03:00
return ret ;
2008-09-29 13:59:36 +04:00
}
/* Again, reset bulk in endpoint */
2008-12-31 14:13:46 +03:00
usb_clear_halt ( gspca_dev - > dev , gspca_dev - > urb [ 0 ] - > pipe ) ;
2008-09-29 13:59:36 +04:00
2009-03-26 11:06:50 +03:00
/* Start the workqueue function to do the streaming */
dev - > work_thread = create_singlethread_workqueue ( MODULE_NAME ) ;
queue_work ( dev - > work_thread , & dev - > work_struct ) ;
2008-09-29 13:59:36 +04:00
return 0 ;
2009-03-26 11:06:50 +03:00
}
/* called on streamoff with alt==0 and on disconnect */
/* the usb_lock is held at entry - restore on exit */
static void sd_stop0 ( struct gspca_dev * gspca_dev )
{
struct usb_fpix * dev = ( struct usb_fpix * ) gspca_dev ;
2008-09-29 13:59:36 +04:00
2009-03-26 11:06:50 +03:00
/* wait for the work queue to terminate */
mutex_unlock ( & gspca_dev - > usb_lock ) ;
destroy_workqueue ( dev - > work_thread ) ;
mutex_lock ( & gspca_dev - > usb_lock ) ;
dev - > work_thread = NULL ;
2008-09-29 13:59:36 +04:00
}
/* Table of supported USB devices */
2011-01-13 11:20:29 +03:00
static const struct usb_device_id device_table [ ] = {
2008-09-29 13:59:36 +04:00
{ USB_DEVICE ( 0x04cb , 0x0104 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0109 ) } ,
{ USB_DEVICE ( 0x04cb , 0x010b ) } ,
{ USB_DEVICE ( 0x04cb , 0x010f ) } ,
{ USB_DEVICE ( 0x04cb , 0x0111 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0113 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0115 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0117 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0119 ) } ,
{ USB_DEVICE ( 0x04cb , 0x011b ) } ,
{ USB_DEVICE ( 0x04cb , 0x011d ) } ,
{ USB_DEVICE ( 0x04cb , 0x0121 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0123 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0125 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0127 ) } ,
{ USB_DEVICE ( 0x04cb , 0x0129 ) } ,
{ USB_DEVICE ( 0x04cb , 0x012b ) } ,
{ USB_DEVICE ( 0x04cb , 0x012d ) } ,
{ USB_DEVICE ( 0x04cb , 0x012f ) } ,
{ USB_DEVICE ( 0x04cb , 0x0131 ) } ,
{ USB_DEVICE ( 0x04cb , 0x013b ) } ,
{ USB_DEVICE ( 0x04cb , 0x013d ) } ,
{ USB_DEVICE ( 0x04cb , 0x013f ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( usb , device_table ) ;
/* sub-driver description */
static const struct sd_desc sd_desc = {
2009-03-26 11:06:50 +03:00
. name = MODULE_NAME ,
2008-09-29 13:59:36 +04:00
. config = sd_config ,
2009-03-26 11:06:50 +03:00
. init = sd_init ,
. start = sd_start ,
. stop0 = sd_stop0 ,
2008-09-29 13:59:36 +04:00
} ;
/* -- device connect -- */
static int sd_probe ( struct usb_interface * intf ,
const struct usb_device_id * id )
{
return gspca_dev_probe ( intf , id ,
& sd_desc ,
sizeof ( struct usb_fpix ) ,
THIS_MODULE ) ;
}
static struct usb_driver sd_driver = {
2009-03-26 11:06:50 +03:00
. name = MODULE_NAME ,
. id_table = device_table ,
. probe = sd_probe ,
2008-09-29 13:59:36 +04:00
. disconnect = gspca_disconnect ,
# ifdef CONFIG_PM
. suspend = gspca_suspend ,
2009-03-26 11:06:50 +03:00
. resume = gspca_resume ,
2012-06-30 13:44:47 +04:00
. reset_resume = gspca_resume ,
2008-09-29 13:59:36 +04:00
# endif
} ;
2011-11-18 21:46:12 +04:00
module_usb_driver ( sd_driver ) ;