aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2008-02-21 12:25:51 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-21 12:25:51 -0800
commit61837aa7b275148a00752dea585c940b0326d101 (patch)
treeb490fcbad586bfca8dce3a0ddaf1f67c88284eab /usb
parent441cac6a419fe351440200bed8b7f7f8805096d2 (diff)
downloadpatches-61837aa7b275148a00752dea585c940b0326d101.tar.gz
usb sensoray driver update
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-add-sensoray-2255-v4l-driver.patch2203
1 files changed, 1054 insertions, 1149 deletions
diff --git a/usb/usb-add-sensoray-2255-v4l-driver.patch b/usb/usb-add-sensoray-2255-v4l-driver.patch
index 8fdc8fe06a392c..a63ac132ad8f44 100644
--- a/usb/usb-add-sensoray-2255-v4l-driver.patch
+++ b/usb/usb-add-sensoray-2255-v4l-driver.patch
@@ -15,36 +15,13 @@ Cc: Dean Anderson <dean@sensoray.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
+
+---
drivers/usb/image/Kconfig | 9
drivers/usb/image/Makefile | 1
drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/Kconfig | 9
- drivers/usb/image/Makefile | 1
- drivers/usb/image/f2255usb.h |40334 +++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/image/s2255drv.c | 2638 ++
- drivers/usb/image/s2255drv.h | 235
- 5 files changed, 43217 insertions(+)
+ drivers/usb/image/s2255drv.c | 2804 ++
+ 4 files changed, 43148 insertions(+)
--- a/drivers/usb/image/Kconfig
+++ b/drivers/usb/image/Kconfig
@@ -40407,7 +40384,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+};
--- /dev/null
+++ b/drivers/usb/image/s2255drv.c
-@@ -0,0 +1,2638 @@
+@@ -0,0 +1,2804 @@
+/*
+ * Sensoray 2255 USB Video for Linux driver
+ *
@@ -40453,11 +40430,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <linux/dma-mapping.h>
-+#ifdef CONFIG_VIDEO_V4L1_COMPAT
-+/* Include V4L1 specific functions. Should be removed soon */
-+#include <linux/videodev.h>
-+#endif
-+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-common.h>
@@ -40466,11 +40438,235 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+#include <linux/freezer.h>
+#include <linux/vmalloc.h>
+#include <linux/usb.h>
-+#include "s2255drv.h"
++
++#ifdef CONFIG_VIDEO_V4L1_COMPAT
++/* Include V4L1 specific functions. Should be removed soon */
++#include <linux/videodev.h>
++#endif
++
+#include "f2255usb.h" /* firmware in header file */
+
++
++#define DIR_IN 0
++#define DIR_OUT 1
++
++/* firmware query */
++#define VX_FW 0x30
++
++#define MAX_CHANNELS 4
++#define FRAME_MARKER 0x2255DA4AL
++#define MAX_PIPE_USBBLOCK (40*1024)
++#define DEFAULT_PIPE_USBBLOCK (16*1024)
++#define MAX_CHANNELS 4
++#define MAX_PIPE_BUFFERS 1
++#define SYS_FRAMES 4
++/* maximum size is PAL full size plus room for the marker header(s) */
++#define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096)
++#define DEF_USB_BLOCK (4096)
++#define LINE_SZ_4CIFS_NTSC 640
++#define LINE_SZ_2CIFS_NTSC 640
++#define LINE_SZ_1CIFS_NTSC 320
++#define LINE_SZ_4CIFS_PAL 704
++#define LINE_SZ_2CIFS_PAL 704
++#define LINE_SZ_1CIFS_PAL 352
++#define NUM_LINES_4CIFS_NTSC 240
++#define NUM_LINES_2CIFS_NTSC 240
++#define NUM_LINES_1CIFS_NTSC 240
++#define NUM_LINES_4CIFS_PAL 288
++#define NUM_LINES_2CIFS_PAL 288
++#define NUM_LINES_1CIFS_PAL 288
++#define LINE_SZ_DEF 640
++#define NUM_LINES_DEF 240
++
++
++/* predefined settings */
++#define FORMAT_NTSC 1
++#define FORMAT_PAL 2
++
++#define SCALE_4CIFS 1 /* 640x480(NTSC) or 704x576(PAL) */
++#define SCALE_2CIFS 2 /* 640x240(NTSC) or 704x288(PAL) */
++#define SCALE_1CIFS 3 /* 320x240(NTSC) or 352x288(PAL) */
++
++#define COLOR_YUVPL 1 /* YUV planar */
++#define COLOR_YUVPK 2 /* YUV packed */
++#define COLOR_RGB 3 /* RGB */
++#define COLOR_Y8 4 /* monochrome */
++
++/* frame decimation. Not implemented by V4L yet(experimental in V4L) */
++#define FDEC_1 1 /* capture every frame. default */
++#define FDEC_2 2 /* capture every 2nd frame */
++#define FDEC_3 3 /* capture every 3rd frame */
++#define FDEC_5 5 /* capture every 5th frame */
++
++/*-------------------------------------------------------
++ * Default mode parameters.
++ *-------------------------------------------------------*/
++#define DEF_SCALE SCALE_4CIFS
++#define DEF_COLOR COLOR_YUVPL
++#define DEF_FDEC FDEC_1
++#define DEF_BRIGHT 0
++#define DEF_CONTRAST 0x5c
++#define DEF_SATURATION 0x80
++#define DEF_HUE 0
++
++/* usb config commands */
++#define IN_DATA_TOKEN 0x2255c0de
++#define CMD_2255 0xc2255000
++#define CMD_SET_MODE (CMD_2255 | 0x10)
++#define CMD_START (CMD_2255 | 0x20)
++#define CMD_STOP (CMD_2255 | 0x30)
++#define CMD_STATUS (CMD_2255 | 0x40)
++
++struct mode2255i {
++ u32 format; /* input video format (NTSC, PAL) */
++ u32 scale; /* output video scale */
++ u32 color; /* output video color format */
++ u32 fdec; /* frame decimation */
++ u32 bright; /* brightness */
++ u32 contrast; /* contrast */
++ u32 saturation; /* saturation */
++ u32 hue; /* hue (NTSC only)*/
++ u32 single; /* capture 1 frame at a time (!=0), continuously (==0)*/
++ u32 usb_block; /* block size. should be 4096 of DEF_USB_BLOCK */
++ u32 restart; /* if DSP requires restart */
++};
++
++/* frame structure */
++#define FRAME_STATE_UNUSED 0
++#define FRAME_STATE_FILLING 1
++#define FRAME_STATE_FULL 2
++
++
++struct framei {
++ unsigned long size;
++
++ unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */
++ void *lpvbits; /* image data */
++ unsigned long cur_size; /* current data copied to it */
++};
++
++/* image buffer structure */
++struct bufferi {
++ unsigned long dwFrames; /* number of frames in buffer */
++ struct framei frame[SYS_FRAMES]; /* array of FRAME structures */
++};
++
++#define DEF_MODEI_NTSC_CONT FORMAT_NTSC, DEF_SCALE, DEF_COLOR, \
++ DEF_FDEC, DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, \
++ DEF_HUE, 0, DEF_USB_BLOCK, 0
++
++#define DEF_MODEI_PAL_CONT FORMAT_PAL, DEF_SCALE, DEF_COLOR, DEF_FDEC,\
++ DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, DEF_HUE, 0, \
++ DEF_USB_BLOCK, 0
++
++#define DEF_MODEI_NTSC_SING FORMAT_NTSC, DEF_SCALE, DEF_COLOR, DEF_FDEC,\
++ DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, DEF_HUE, 1,\
++ DEF_USB_BLOCK, 0
++
++#define DEF_MODEI_PAL_SING FORMAT_PAL, DEF_SCALE, DEF_COLOR, DEF_FDEC, \
++ DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, DEF_HUE, 1,\
++ DEF_USB_BLOCK, 0
++
++struct s2255_dmaqueue {
++ struct list_head active;
++ struct list_head queued;
++ struct timer_list timeout;
++ /* thread for acquisition */
++ struct task_struct *kthread;
++ wait_queue_head_t wq;
++ int frame;
++ struct s2255_dev *dev;
++ int channel;
++};
++
++/* for firmware loading */
++#define FWSTATE_NOTLOADED 0
++#define FWSTATE_SUCCESS 1
++#define FWSTATE_FAILED 2
++
++struct complete_data {
++ int fw_loaded;
++ int fw_size;
++ struct urb *fw_urb;
++ int fw_state;
++ void *pfw_data;
++};
++
++struct s2255_pipeinfo {
++ u32 max_transfer_size;
++ u32 cur_transfer_size;
++ u8 *transfer_buffer;
++ u32 transfer_flags;;
++ u32 state;
++ u32 prev_state;
++ u32 urb_size;
++ void *stream_urb;
++ void *dev; /* back pointer to s2255_dev struct*/
++ u32 err_count;
++ u32 buf_index;
++ u32 idx;
++ u32 priority_set;
++};
++
++struct s2255_dev {
++ int frames;
++ int users[MAX_CHANNELS];
++ struct mutex lock;
++ int resources[MAX_CHANNELS];
++ struct usb_device *udev;
++ struct usb_interface *interface;
++ u8 read_endpoint;
++ struct semaphore sem_frms[MAX_CHANNELS]; /* frames ready */
++ struct s2255_dmaqueue vidq[MAX_CHANNELS];
++ struct video_device *vdev[MAX_CHANNELS];
++ struct list_head s2255_devlist;
++ struct timer_list timer;
++ struct complete_data *fw_data;
++ int board_num;
++ int is_open;
++ struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS];
++ struct bufferi buffer[MAX_CHANNELS];
++ struct mode2255i mode[MAX_CHANNELS];
++ int cur_frame[MAX_CHANNELS];
++ int last_frame[MAX_CHANNELS];
++ u32 cc; /* current channel */
++ int b_acquire[MAX_CHANNELS];
++ unsigned long req_image_size[MAX_CHANNELS];
++ int bad_payload[MAX_CHANNELS];
++ unsigned long frame_count[MAX_CHANNELS];
++ int frame_ready;
++ struct kref kref;
++};
++#define to_s2255_dev(d) container_of(d, struct s2255_dev, kref)
++
++struct s2255_fmt {
++ char *name;
++ u32 fourcc;
++ int depth;
++};
++
++/* buffer for one video frame */
++struct s2255_buffer {
++ /* common v4l buffer stuff -- must be first */
++ struct videobuf_buffer vb;
++ const struct s2255_fmt *fmt;
++ /* future use */
++ int reserved[32];
++};
++
++struct s2255_fh {
++ struct s2255_dev *dev;
++ unsigned int resources;
++ const struct s2255_fmt *fmt;
++ unsigned int width;
++ unsigned int height;
++ struct videobuf_queue vb_vidq;
++ enum v4l2_buf_type type;
++ int channel;
++};
++
++
+#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */
-+static char MODULE_REVISION[] = "Ver.1.0.1";
+#define S2255_MAJOR_VERSION 1
+#define S2255_MINOR_VERSION 1
+#define S2255_RELEASE 0
@@ -40491,46 +40687,25 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+static LIST_HEAD(s2255_devlist);
+
-+static int s2255_probe_v4l(struct s2255_dev *dev);
-+static void s2255_exit_v4l(struct s2255_dev *dev);
-+static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pPipeInfo);
-+
-+static int s2255_wait_frame_block(struct s2255_dev *dev, int chn);
-+static int s2255_wait_frame_noblock(struct s2255_dev *dev, int chn);
++static int debug;
++static int *s2255_debug = &debug;
+
-+static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
-+ int size);
+static int s2255_start_readpipe(struct s2255_dev *dev);
+static void s2255_stop_readpipe(struct s2255_dev *dev);
-+static int s2255_create_sys_buffers(struct s2255_dev *dev, unsigned long chn);
-+static int s2255_release_sys_buffers(struct s2255_dev *dev, unsigned long chn);
-+static int s2255_board_init(struct s2255_dev *dev);
-+static int s2255_board_shutdown(struct s2255_dev *dev);
-+
-+static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
-+ u16 index,
-+ u16 val, void *buffer, s32 buf_len, int bOut);
-+static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
-+ struct mode2255i *mode);
-+
+static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn);
+static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn);
-+static int restart_video_queue(struct s2255_dmaqueue *dma_q);
-+static void s2255_sleep(int ms);
-+static void planar422p_to_yuy2(const unsigned char *in, unsigned char *out,
-+ int width, int height);
+
-+static void planar422p_to_rgb32(const unsigned char *in, unsigned char *out,
-+ int width, int height, int rev_order);
-+static void planar422p_to_rgb24(const unsigned char *in, unsigned char *out,
-+ int width, int height, int rev_order);
-+static void planar422p_to_rgb565(unsigned char const *in, unsigned char *out,
-+ int width, int height, int rev_order);
-+static u32 get_transfer_size(struct mode2255i *mode);
-+static int s2255_get_fx2fw(struct s2255_dev *dev);
++#define dprintk(level, fmt, arg...) \
++ do { \
++ if (*s2255_debug >= (level)) { \
++ printk(KERN_DEBUG "s2255: " fmt, ##arg); \
++ } \
++ } while (0)
++
++
++static DEFINE_MUTEX(usb_s2255_open_mutex);
++static struct usb_driver s2255_driver;
+
-+static int debug;
-+static int *s2255_debug = &debug;
+/* Declare static vars that will be used as parameters */
+static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
+
@@ -40544,13 +40719,119 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+module_param(video_nr, int, 0);
+MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)");
+
-+/* device table */
++/* USB device table */
+static struct usb_device_id s2255_table[] = {
+ {USB_DEVICE(USB_S2255_VENDOR_ID, USB_S2255_PRODUCT_ID)},
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, s2255_table);
+
++/* buffer timeout. Do not make this smaller than
++ 300ms. The long timeout is required because the hardware
++ internally restartswhen a new video source is plugged in.
++ */
++#define BUFFER_TIMEOUT msecs_to_jiffies(300)
++/* initial startup timeout*/
++#define BUFFER_TIMEOUT_INIT msecs_to_jiffies(900)
++
++/* supported controls */
++static struct v4l2_queryctrl s2255_qctrl[] = {
++ {
++ .id = V4L2_CID_BRIGHTNESS,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Brightness",
++ .minimum = -127,
++ .maximum = 128,
++ .step = 1,
++ .default_value = 0,
++ .flags = 0,
++ },
++ {
++ .id = V4L2_CID_CONTRAST,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Contrast",
++ .minimum = 0,
++ .maximum = 255,
++ .step = 0x1,
++ .default_value = DEF_CONTRAST,
++ .flags = 0,
++ },
++ {
++ .id = V4L2_CID_SATURATION,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Saturation",
++ .minimum = 0,
++ .maximum = 255,
++ .step = 0x1,
++ .default_value = DEF_SATURATION,
++ .flags = 0,
++ },
++ {
++ .id = V4L2_CID_HUE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Hue",
++ .minimum = 0,
++ .maximum = 255,
++ .step = 0x1,
++ .default_value = DEF_HUE,
++ .flags = 0,
++ }
++};
++
++static int qctl_regs[ARRAY_SIZE(s2255_qctrl)];
++
++/* image formats. Note RGB formats are software converted.
++ * because the 2255 transfers in YUV for maximum USB efficiency
++ * in order to allow 2 full size color channels at full frame rate
++ */
++static const struct s2255_fmt formats[] = {
++ {
++ .name = "4:2:2, planar, YUV422P",
++ .fourcc = V4L2_PIX_FMT_YUV422P,
++ .depth = 16
++ },
++ {
++ .name = "4:2:2, packed, YUYV",
++ .fourcc = V4L2_PIX_FMT_YUYV,
++ .depth = 16
++ },
++ {
++ .name = "BGR24",
++ .fourcc = V4L2_PIX_FMT_BGR24,
++ .depth = 24
++ },
++ {
++ .name = "RGB24",
++ .fourcc = V4L2_PIX_FMT_RGB24,
++ .depth = 24
++ },
++ {
++ .name = "BGR32",
++ .fourcc = V4L2_PIX_FMT_BGR32,
++ .depth = 32
++ },
++ {
++ .name = "RGB24",
++ .fourcc = V4L2_PIX_FMT_RGB32,
++ .depth = 32
++ },
++ {
++ .name = "RGB565",
++ .fourcc = V4L2_PIX_FMT_RGB565,
++ .depth = 16
++ },
++ {
++ .name = "RGB565 big endian",
++ .fourcc = V4L2_PIX_FMT_RGB565X,
++ .depth = 16
++ },
++ {
++ .name = "8bpp GREY",
++ .fourcc = V4L2_PIX_FMT_GREY,
++ .depth = 8
++ },
++};
++
+static int norm_maxw(struct video_device *vdev)
+{
+ return (vdev->current_norm != V4L2_STD_PAL_B) ?
@@ -40575,17 +40856,185 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ (NUM_LINES_1CIFS_NTSC) : (NUM_LINES_1CIFS_PAL);
+}
+
-+#define dprintk(level, fmt, arg...) \
-+ do { \
-+ if (*s2255_debug >= (level)) { \
-+ printk(KERN_DEBUG "s2255: " fmt, ##arg); \
-+ } \
-+ } while (0)
++/*
++ * convert from YUV(YCrCb) to RGB
++ * 65536 R = 76533(Y-16) + 104936 * (Cr-128)
++ * 65536 G = 76533(Y-16) - 53451(Cr-128) - 25703(Cb -128)
++ * 65536 B = 76533(Y-16) + 132677(Cb-128)
++ */
++static void YCrCb2RGB(int Y, int Cr, int Cb, unsigned char *pR,
++ unsigned char *pG, unsigned char *pB)
++{
++ int R, G, B;
+
-+#define to_s2255_dev(d) container_of(d, struct s2255_dev, kref)
++ Y = Y - 16;
++ Cr = Cr - 128;
++ Cb = Cb - 128;
+
-+static DEFINE_MUTEX(usb_s2255_open_mutex);
-+static struct usb_driver s2255_driver;
++ R = (76533 * Y + 104936 * Cr) >> 16;
++ G = ((76533 * Y) - (53451 * Cr) - (25703 * Cb)) >> 16;
++ B = ((76533 * Y) + (132677 * Cb)) >> 16;
++ /* even with proper conversion, some values still need clipping. */
++ if (R > 255)
++ R = 255;
++ if (G > 255)
++ G = 255;
++ if (B > 255)
++ B = 255;
++ if (R < 0)
++ R = 0;
++ if (G < 0)
++ G = 0;
++ if (B < 0)
++ B = 0;
++ *pR = R;
++ *pG = G;
++ *pB = B;
++ return;
++}
++
++/* converts 2255 planar format to yuyv */
++static void planar422p_to_yuy2(const unsigned char *in, unsigned char *out,
++ int width, int height)
++{
++ unsigned char *pY;
++ unsigned char *pCb;
++ unsigned char *pCr;
++ unsigned long size = height * width;
++ unsigned int i;
++ pY = (unsigned char *)in;
++ pCr = (unsigned char *)in + height * width;
++ pCb = (unsigned char *)in + height * width + (height * width / 2);
++ for (i = 0; i < size * 2; i += 4) {
++ out[i] = *pY++;
++ out[i + 1] = *pCr++;
++ out[i + 2] = *pY++;
++ out[i + 3] = *pCb++;
++ }
++ return;
++}
++
++/*
++ * basic 422 planar to RGB24 or BGR24 software conversion.
++ * This is best done with MMX. Update to kernel function
++ * when image conversion functions added to kernel.
++ */
++static void planar422p_to_rgb24(const unsigned char *in,
++ unsigned char *out, int width,
++ int height, int rev_order)
++{
++ unsigned char *pY;
++ unsigned char *pYEND;
++ unsigned char *pCb;
++ unsigned char *pCr;
++ unsigned char Cr, Cb, Y, r, g, b;
++ unsigned long k = 0;
++ pY = (unsigned char *)in;
++ pCb = (unsigned char *)in + (height * width);
++ pCr = (unsigned char *)in + (height * width) + (height * width / 2);
++ pYEND = pCb;
++ while (pY < pYEND) {
++ Y = *pY++;
++ Cr = *pCr;
++ Cb = *pCb;
++ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
++ out[k++] = !rev_order ? b : r;
++ out[k++] = g;
++ out[k++] = !rev_order ? r : b;
++ if (pY >= pYEND)
++ break;
++ Y = *pY++;
++ Cr = *pCr++;
++ Cb = *pCb++;
++ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
++ out[k++] = !rev_order ? b : r;
++ out[k++] = g;
++ out[k++] = !rev_order ? r : b;
++ }
++ return;
++}
++
++static void planar422p_to_rgb32(const unsigned char *in, unsigned char *out,
++ int width, int height, int rev_order)
++{
++ unsigned char *pY;
++ unsigned char *pYEND;
++ unsigned char *pCb;
++ unsigned char *pCr;
++ unsigned char Cr, Cb, Y, r, g, b;
++ unsigned long k = 0;
++ pY = (unsigned char *)in;
++ pCb = (unsigned char *)in + (height * width);
++ pCr = (unsigned char *)in + (height * width) + (height * width / 2);
++ pYEND = pCb;
++ while (pY < pYEND) {
++ Y = *pY++;
++ Cr = *pCr;
++ Cb = *pCb;
++ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
++ out[k++] = rev_order ? b : r;
++ out[k++] = g;
++ out[k++] = rev_order ? r : b;
++ out[k++] = 0;
++ if (pY >= pYEND)
++ break;
++ Y = *pY++;
++ Cr = *pCr++;
++ Cb = *pCb++;
++ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
++ out[k++] = rev_order ? b : r;
++ out[k++] = g;
++ out[k++] = rev_order ? r : b;
++ out[k++] = 0;
++ }
++
++ return;
++}
++
++static void planar422p_to_rgb565(unsigned char const *in, unsigned char *out,
++ int width, int height, int rev_order)
++{
++ unsigned char *pY;
++ unsigned char *pYEND;
++ unsigned char *pCb;
++ unsigned char *pCr;
++ unsigned char Cr, Cb, Y, r, g, b;
++ unsigned long k = 0;
++ unsigned short rgbbytes;
++ pY = (unsigned char *)in;
++ pCb = (unsigned char *)in + (height * width);
++ pCr = (unsigned char *)in + (height * width) + (height * width / 2);
++ pYEND = pCb;
++ while (pY < pYEND) {
++ Y = *pY++;
++ Cr = *pCr;
++ Cb = *pCb;
++ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
++ r = r >> 3;
++ g = g >> 2;
++ b = b >> 3;
++ if (rev_order)
++ rgbbytes = b + (g << 5) + (r << (5 + 6));
++ else
++ rgbbytes = r + (g << 5) + (b << (5 + 6));
++ out[k++] = rgbbytes & 0xff;
++ out[k++] = (rgbbytes >> 8) & 0xff;
++ Y = *pY++;
++ Cr = *pCr++;
++ Cb = *pCb++;
++ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
++ r = r >> 3;
++ g = g >> 2;
++ b = b >> 3;
++ if (rev_order)
++ rgbbytes = b + (g << 5) + (r << (5 + 6));
++ else
++ rgbbytes = r + (g << 5) + (b << (5 + 6));
++ out[k++] = rgbbytes & 0xff;
++ out[k++] = (rgbbytes >> 8) & 0xff;
++ }
++ return;
++}
+
+/* kickstarts the firmware loading. from probe
+ */
@@ -40612,11 +41061,11 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ int len;
+ dprintk(100, "udev %p urb %p", udev, urb);
+ if (urb->status) {
-+ printk("URB failed with status %d", urb->status);
++ dev_err(&udev->dev, "URB failed with status %d", urb->status);
+ return;
+ }
+ if (data->fw_urb == NULL) {
-+ printk("early disconncect\n");
++ dev_err(&udev->dev, "early disconncect\n");
+ return;
+ }
+#define CHUNK_SIZE 512
@@ -40636,14 +41085,14 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ s2255_fwchunk_complete, data);
+
+ if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
-+ printk("failed submit URB\n");
++ dev_err(&udev->dev, "failed submit URB\n");
+ data->fw_state = FWSTATE_FAILED;
+ return;
+ }
+ data->fw_loaded += len;
+ } else {
+ data->fw_state = FWSTATE_SUCCESS;
-+ printk(KERN_INFO "2255 firmware loaded successfully\n");
++ dev_info(&udev->dev, "firmware loaded successfully\n");
+ }
+
+ dprintk(100, "2255 complete done\n");
@@ -40651,194 +41100,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+}
+
-+/* standard usb probe function */
-+static int s2255_probe
-+ (struct usb_interface *interface, const struct usb_device_id *id) {
-+ struct s2255_dev *dev = NULL;
-+ struct usb_host_interface *iface_desc;
-+ struct usb_endpoint_descriptor *endpoint;
-+ int i;
-+ int retval = -ENOMEM;
-+ printk(KERN_INFO "s2255: probe\n");
-+ /* allocate memory for our device state and initialize it to zero */
-+ dev = (struct s2255_dev *)kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
-+
-+ if (dev == NULL) {
-+ err("s2255: out of memory");
-+ goto error;
-+ }
-+
-+ /* grab usb_device and save it */
-+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
-+ if (dev->udev == NULL) {
-+ printk("null usb device\n");
-+ goto error;
-+ }
-+
-+ kref_init(&dev->kref);
-+ dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref,
-+ dev->udev, interface);
-+ dev->interface = interface;
-+ /* set up the endpoint information */
-+ iface_desc = interface->cur_altsetting;
-+ printk("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
-+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-+ endpoint = &iface_desc->endpoint[i].desc;
-+ if (!dev->read_endpoint &&
-+ ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-+ == USB_DIR_IN) &&
-+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-+ == USB_ENDPOINT_XFER_BULK)) {
-+ /* we found the bulk in endpoint */
-+ dev->read_endpoint = endpoint->bEndpointAddress;
-+ }
-+ }
-+
-+ if (!dev->read_endpoint) {
-+ err("Could not find both bulk-in endpoint");
-+ goto error;
-+ }
-+
-+ /* set intfdata */
-+ usb_set_intfdata(interface, dev);
-+
-+ dprintk(100, "after intfdata %p\n", dev);
-+
-+ /* initialize COUNTING semaphores */
-+ for (i = 0; i < MAX_CHANNELS; i++) {
-+ sema_init(&dev->sem_frms[i], 0);
-+ }
-+
-+ /* initialize device mutex */
-+ mutex_init(&dev->lock);
-+
-+ init_timer(&dev->timer);
-+ dev->timer.function = s2255_timer;
-+ dev->fw_data = kzalloc(sizeof(struct complete_data), GFP_KERNEL);
-+ if (!dev->fw_data) {
-+ goto error;
-+ }
-+
-+ dev->timer.data = (unsigned long)dev->fw_data;
-+
-+ dev->fw_data->fw_size = sizeof(G_f2255usb) / sizeof(unsigned char);
-+ dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
-+
-+ if (!dev->fw_data->fw_urb) {
-+ printk("out of memory!\n");
-+ goto error;
-+ }
-+ dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL);
-+ if (!dev->fw_data->pfw_data) {
-+ printk("out of mem\n");
-+ goto error;
-+ }
-+
-+ /* load the first chunk */
-+ memcpy(dev->fw_data->pfw_data, G_f2255usb, CHUNK_SIZE);
-+ dev->fw_data->fw_loaded = CHUNK_SIZE;
-+ usb_fill_bulk_urb(dev->fw_data->fw_urb, dev->udev,
-+ usb_sndbulkpipe(dev->udev, 2), dev->fw_data->pfw_data,
-+ CHUNK_SIZE, s2255_fwchunk_complete, dev->fw_data);
-+ /* loads v4l specific */
-+ s2255_probe_v4l(dev);
-+ /* load 2255 board specific */
-+ s2255_board_init(dev);
-+
-+ printk("Sensoray 2255 successfully loaded\n");
-+ dprintk(4, "before probe done %p\n", dev);
-+
-+ mod_timer(&dev->timer, jiffies + HZ);
-+
-+ kref_get(&dev->kref);
-+ return 0;
-+error:
-+ return retval;
-+}
-+
-+static void s2255_destroy(struct kref *kref)
-+{
-+ struct s2255_dev *dev = to_s2255_dev(kref);
-+
-+ usb_put_dev(dev->udev);
-+ dprintk(1, "s2255_destroy\n");
-+ kfree(dev);
-+}
-+
-+/* disconnect routine. when board is removed physically or with rmmod */
-+static void s2255_disconnect(struct usb_interface *interface)
-+{
-+ struct s2255_dev *dev = NULL;
-+
-+ /* lock to prevent s2255_open() from racing s2255_disconnect() */
-+ mutex_lock(&usb_s2255_open_mutex);
-+ printk(KERN_INFO "s2255: disconnect interface %p\n", interface);
-+ dev = usb_get_intfdata(interface);
-+ s2255_board_shutdown(dev);
-+ if (dev->fw_data->fw_urb) {
-+ dprintk(2, "kill URB\n");
-+ usb_kill_urb(dev->fw_data->fw_urb);
-+ usb_free_urb(dev->fw_data->fw_urb);
-+
-+ }
-+ s2255_exit_v4l(dev);
-+ if (dev->fw_data) {
-+ if (dev->fw_data->pfw_data)
-+ kfree(dev->fw_data->pfw_data);
-+ kfree(dev->fw_data);
-+ }
-+ usb_set_intfdata(interface, NULL);
-+ kref_put(&dev->kref, s2255_destroy);
-+ mutex_unlock(&usb_s2255_open_mutex);
-+ info("s2255usb now disconnected\n");
-+}
-+
-+/* Generate proc info.
-+ */
-+static int s2255_read_procmem(char *buf, char **start, off_t offset, int count,
-+ int *eof, void *data)
-+{
-+ int len = 0;
-+ /* Generate report heading. */
-+ len += sprintf(buf + len, "Sensoray 2255 drvr, version %s\n",
-+ MODULE_REVISION);
-+
-+ len += sprintf(buf + len, "\n");
-+
-+ *eof = 1;
-+ return len;
-+}
-+
-+static struct usb_driver s2255_driver = {
-+ .name = "s2255",
-+ .probe = s2255_probe,
-+ .disconnect = s2255_disconnect,
-+ .id_table = s2255_table,
-+};
-+
-+static int __init usb_s2255_init(void)
-+{
-+ int result;
-+
-+ /* Make public the function that supplies "proc" info to the system.
-+ */
-+ create_proc_read_entry("s2255", 0, NULL, s2255_read_procmem, NULL);
-+
-+ /* register this driver with the USB subsystem */
-+ result = usb_register(&s2255_driver);
-+
-+ if (result)
-+ err("usb_register failed. Error number %d", result);
-+
-+ dprintk(2, "s2255_init: done\n");
-+ return result;
-+}
-+
-+static void __exit usb_s2255_exit(void)
-+{
-+ usb_deregister(&s2255_driver);
-+}
-+
+static int s2255_got_frame(struct s2255_dev *dev, int chn)
+{
+ dprintk(2, "wakeup: %p channel: %d\n", &dev->sem_frms[chn], chn);
@@ -40848,13 +41109,13 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+static int s2255_wait_frame_noblock(struct s2255_dev *dev, int chn)
+{
-+ if (dev == NULL) {
-+ return -1;
-+ }
++ if (dev == NULL)
++ return -EINVAL;
++
+ dprintk(2, "wait frame: %p channel: %d\n", &dev->sem_frms[chn], chn);
+ if (down_trylock(&dev->sem_frms[chn])) {
+ dprintk(4, "wait_event: would block\n");
-+ return -1;
++ return -EINVAL;
+ }
+
+ return 0;
@@ -40863,109 +41124,16 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+static int s2255_wait_frame_block(struct s2255_dev *dev, int chn)
+{
+ int res;
-+ if (dev == NULL) {
-+ return -1;
-+ }
++
++ if (dev == NULL)
++ return -EINVAL;
++
+ dprintk(2, "wait frame: %p channel: %d\n", &dev->sem_frms[chn], chn);
+ res = down_interruptible(&dev->sem_frms[chn]);
+
+ return res;
+}
+
-+/* buffer timeout. Do not make this smaller than
-+ 300ms. The long timeout is required because the hardware
-+ internally restartswhen a new video source is plugged in.
-+ */
-+#define BUFFER_TIMEOUT msecs_to_jiffies(300)
-+/* initial startup timeout*/
-+#define BUFFER_TIMEOUT_INIT msecs_to_jiffies(900)
-+
-+/* supported controls */
-+static struct v4l2_queryctrl s2255_qctrl[] = {
-+ {
-+ .id = V4L2_CID_BRIGHTNESS,
-+ .type = V4L2_CTRL_TYPE_INTEGER,
-+ .name = "Brightness",
-+ .minimum = -127,
-+ .maximum = 128,
-+ .step = 1,
-+ .default_value = 0,
-+ .flags = 0,
-+ }, {
-+ .id = V4L2_CID_CONTRAST,
-+ .type = V4L2_CTRL_TYPE_INTEGER,
-+ .name = "Contrast",
-+ .minimum = 0,
-+ .maximum = 255,
-+ .step = 0x1,
-+ .default_value = DEF_CONTRAST,
-+ .flags = 0,
-+ }, {
-+ .id = V4L2_CID_SATURATION,
-+ .type = V4L2_CTRL_TYPE_INTEGER,
-+ .name = "Saturation",
-+ .minimum = 0,
-+ .maximum = 255,
-+ .step = 0x1,
-+ .default_value = DEF_SATURATION,
-+ .flags = 0,
-+ }, {
-+ .id = V4L2_CID_HUE,
-+ .type = V4L2_CTRL_TYPE_INTEGER,
-+ .name = "Hue",
-+ .minimum = 0,
-+ .maximum = 255,
-+ .step = 0x1,
-+ .default_value = DEF_HUE,
-+ .flags = 0,
-+ }
-+};
-+
-+static int qctl_regs[ARRAY_SIZE(s2255_qctrl)];
-+
-+/* image formats. Note RGB formats are software converted.
-+ * because the 2255 transfers in YUV for maximum USB efficiency
-+ * in order to allow 2 full size color channels at full frame rate
-+ */
-+static const struct s2255_fmt formats[] = {
-+ {
-+ .name = "4:2:2, planar, YUV422P",
-+ .fourcc = V4L2_PIX_FMT_YUV422P,
-+ .depth = 16},
-+ {
-+ .name = "4:2:2, packed, YUYV",
-+ .fourcc = V4L2_PIX_FMT_YUYV,
-+ .depth = 16},
-+ {
-+ .name = "BGR24",
-+ .fourcc = V4L2_PIX_FMT_BGR24,
-+ .depth = 24},
-+ {
-+ .name = "RGB24",
-+ .fourcc = V4L2_PIX_FMT_RGB24,
-+ .depth = 24},
-+ {
-+ .name = "BGR32",
-+ .fourcc = V4L2_PIX_FMT_BGR32,
-+ .depth = 32},
-+ {
-+ .name = "RGB24",
-+ .fourcc = V4L2_PIX_FMT_RGB32,
-+ .depth = 32},
-+ {
-+ .name = "RGB565",
-+ .fourcc = V4L2_PIX_FMT_RGB565,
-+ .depth = 16},
-+ {
-+ .name = "RGB565 big endian",
-+ .fourcc = V4L2_PIX_FMT_RGB565X,
-+ .depth = 16},
-+ {
-+ .name = "8bpp GREY",
-+ .fourcc = V4L2_PIX_FMT_GREY,
-+ .depth = 8},
-+};
-+
+static const struct s2255_fmt *format_by_fourcc(int fourcc)
+{
+ unsigned int i;
@@ -41064,9 +41232,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ when acquisition restarted.
+ */
+ tmp = s2255_wait_frame_noblock(dev, chn);
-+ while (tmp == 0) {
++ while (tmp == 0)
+ tmp = s2255_wait_frame_noblock(dev, chn);
-+ }
+
+ /* initialize the states */
+ dev->b_acquire[chn] = 1;
@@ -41096,18 +41263,16 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ if (!waitqueue_active(&buf->vb.done)) {
+ /* no one active */
+ mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT);
-+ if (kthread_should_stop()) {
++ if (kthread_should_stop())
+ break;
-+ }
+ continue;
+ }
+ do_gettimeofday(&buf->vb.ts);
+ dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i);
+ s2255_fillbuff(dev, buf, dma_q->channel);
+ mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT);
-+ if (kthread_should_stop()) {
++ if (kthread_should_stop())
+ break;
-+ }
+ dprintk(3, "thread tick \n");
+ }
+ dprintk(1, "thread: exit %d\n", dma_q->channel);
@@ -41120,7 +41285,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+static int s2255_start_thread(struct s2255_dmaqueue *dma_q)
+{
+ dma_q->frame = 0;
-+ dprintk(1, "%s[%d]\n", __FUNCTION__, dma_q->channel);
++ dprintk(1, "%s[%d]\n", __func__, dma_q->channel);
+ dma_q->kthread = kthread_run(s2255_thread, dma_q, "s2255");
+ if (IS_ERR(dma_q->kthread)) {
+ printk(KERN_ERR "s2255: kernel_thread() failed\n");
@@ -41129,13 +41294,13 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ /* Wakes thread */
+ wake_up_interruptible(&dma_q->wq);
+
-+ dprintk(1, "returning from %s\n", __FUNCTION__);
++ dprintk(1, "returning from %s\n", __func__);
+ return 0;
+}
+
+static void s2255_stop_thread(struct s2255_dmaqueue *dma_q)
+{
-+ dprintk(1, "%s[%d]\n", __FUNCTION__, dma_q->channel);
++ dprintk(1, "%s[%d]\n", __func__, dma_q->channel);
+ /* unblock the kthread */
+ dprintk(1, "stop thread channel %d\n", dma_q->channel);
+ /* wakeup the thread in case it's waiting */
@@ -41146,7 +41311,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ dma_q->kthread = NULL;
+ }
+
-+ dprintk(1, "%s exiting\n", __FUNCTION__);
++ dprintk(1, "%s exiting\n", __func__);
+ return;
+}
+
@@ -41155,7 +41320,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ struct s2255_buffer *buf, *prev;
+ struct list_head *item;
+
-+ dprintk(1, "%s dma_q=0x%08lx chan %d\n", __FUNCTION__,
++ dprintk(1, "%s dma_q=0x%08lx chan %d\n", __func__,
+ (unsigned long)dma_q, dma_q->channel);
+
+ if (!list_empty(&dma_q->active)) {
@@ -41242,16 +41407,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+/* ------------------------------------------------------------------
+ Videobuf operations
+ ------------------------------------------------------------------*/
-+static int
-+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
++static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
++ unsigned int *size)
+{
+ struct s2255_fh *fh = vq->priv_data;
+
+ *size = fh->width * fh->height * (fh->fmt->depth >> 3);
+
-+ if (0 == *count) {
++ if (0 == *count)
+ *count = 32;
-+ }
+
+ while (*size * *count > vid_limit * 1024 * 1024)
+ (*count)--;
@@ -41261,7 +41425,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+static void free_buffer(struct videobuf_queue *vq, struct s2255_buffer *buf)
+{
-+ dprintk(4, "%s\n", __FUNCTION__);
++ dprintk(4, "%s\n", __func__);
+
+ if (vq == NULL) {
+ dprintk(4, "null vq\n");
@@ -41281,17 +41445,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
-+static int
-+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-+ enum v4l2_field field)
++static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
++ enum v4l2_field field)
+{
+ struct s2255_fh *fh = vq->priv_data;
+ struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+ int rc, init_buffer = 0;
-+ dprintk(4, "%s, field=%d\n", __FUNCTION__, field);
-+ if (fh->fmt == NULL) {
++ dprintk(4, "%s, field=%d\n", __func__, field);
++ if (fh->fmt == NULL)
+ return -EINVAL;
-+ }
+ if ((fh->width < norm_minw(fh->dev->vdev[fh->channel])) ||
+ (fh->width > norm_maxw(fh->dev->vdev[fh->channel])) ||
+ (fh->height < norm_minh(fh->dev->vdev[fh->channel])) ||
@@ -41318,13 +41480,14 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ }
+
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-+ if (0 != (rc = videobuf_iolock(vq, &buf->vb, NULL)))
++ rc = videobuf_iolock(vq, &buf->vb, NULL);
++ if (rc)
+ goto fail;
+ }
+
+ buf->vb.state = VIDEOBUF_PREPARED;
+ return 0;
-+ fail:
++fail:
+ free_buffer(vq, buf);
+ return rc;
+}
@@ -41381,7 +41544,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ struct s2255_dev *dev = (struct s2255_dev *)fh->dev;
+ struct s2255_dmaqueue *vidq = &dev->vidq[fh->channel];
+
-+ dprintk(1, "%s\n", __FUNCTION__);
++ dprintk(1, "%s\n", __func__);
+ s2255_stop_thread(vidq);
+ free_buffer(vq, buf);
+}
@@ -41442,13 +41605,11 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ struct v4l2_fmtdesc *f)
+{
+ int index = 0;
-+ if (f) {
++ if (f)
+ index = f->index;
-+ }
+
-+ if (index >= ARRAY_SIZE(formats)) {
++ if (index >= ARRAY_SIZE(formats))
+ return -EINVAL;
-+ }
+
+ dprintk(4, "name %s\n", formats[index].name);
+ strlcpy(f->description, formats[index].name, sizeof(f->description));
@@ -41484,9 +41645,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ (dev->vdev[fh->channel]->current_norm != V4L2_STD_PAL_B) ? 1 : 0;
+
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-+ if (fmt == NULL) {
++ if (fmt == NULL)
+ return -EINVAL;
-+ }
+
+ field = f->fmt.pix.field;
+
@@ -41551,21 +41711,22 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ return 0;
+}
+
-+/*FIXME: This seems to be generic enough to be at videodev2 */
++/* FIXME: This seems to be generic enough to be at videodev2 */
+static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct s2255_fh *fh = priv;
+ const struct s2255_fmt *fmt;
-+ int ret = vidioc_try_fmt_cap(file, fh, f);
++ int ret;
+ int norm;
-+ if (ret < 0) {
++
++ ret = vidioc_try_fmt_cap(file, fh, f);
++ if (ret < 0)
+ return (ret);
-+ }
++
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-+ if (fmt == NULL) {
++ if (fmt == NULL)
+ return -EINVAL;
-+ }
+
+ fh->fmt = fmt;
+ fh->width = f->fmt.pix.width;
@@ -41574,15 +41735,13 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ fh->type = f->type;
+
+ norm = norm_minw(fh->dev->vdev[fh->channel]);
-+ if (fh->width > norm_minw(fh->dev->vdev[fh->channel])) {
-+ if (fh->height > norm_minh(fh->dev->vdev[fh->channel])) {
++ if (fh->width > norm_minw(fh->dev->vdev[fh->channel]))
++ if (fh->height > norm_minh(fh->dev->vdev[fh->channel]))
+ fh->dev->mode[fh->channel].scale = SCALE_4CIFS;
-+ } else {
++ else
+ fh->dev->mode[fh->channel].scale = SCALE_2CIFS;
-+ }
-+ } else {
++ else
+ fh->dev->mode[fh->channel].scale = SCALE_1CIFS;
-+ }
+
+ /* color mode */
+ if (fh->fmt->fourcc == V4L2_PIX_FMT_GREY) {
@@ -41663,6 +41822,166 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+}
+#endif
+
++static void s2255_sleep(int ms)
++{
++ wait_queue_head_t sleep_q;
++ DEFINE_WAIT(wait);
++ if (ms == 0) {
++ schedule();
++ return;
++ }
++ init_waitqueue_head(&sleep_q);
++ prepare_to_wait(&sleep_q, &wait, TASK_INTERRUPTIBLE);
++ schedule_timeout((ms * HZ) / 1000);
++ finish_wait(&sleep_q, &wait);
++}
++
++#define EP_NUM_CONFIG 2
++/* write to the configuration pipe, synchronously */
++static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
++ int size)
++{
++ int pipe;
++ int done;
++ long retval = -1;
++ if (udev) {
++ pipe = usb_sndbulkpipe(udev, EP_NUM_CONFIG);
++ retval = usb_bulk_msg(udev, pipe, pbuf, size, &done, 500);
++ }
++ return retval;
++}
++
++static u32 get_transfer_size(struct mode2255i *mode)
++{
++ int linesPerFrame = LINE_SZ_DEF;
++ int pixelsPerLine = NUM_LINES_DEF;
++ u32 outImageSize;
++ u32 usbInSize;
++ unsigned int mask_mult;
++
++ if (mode == NULL)
++ return 0;
++
++ if (mode->format == FORMAT_NTSC) {
++ switch (mode->scale) {
++ case SCALE_4CIFS:
++ linesPerFrame = NUM_LINES_4CIFS_NTSC * 2;
++ pixelsPerLine = LINE_SZ_4CIFS_NTSC;
++ break;
++ case SCALE_2CIFS:
++ linesPerFrame = NUM_LINES_2CIFS_NTSC;
++ pixelsPerLine = LINE_SZ_2CIFS_NTSC;
++ break;
++ case SCALE_1CIFS:
++ linesPerFrame = NUM_LINES_1CIFS_NTSC;
++ pixelsPerLine = LINE_SZ_1CIFS_NTSC;
++ break;
++ default:
++ break;
++ }
++ } else if (mode->format == FORMAT_PAL) {
++ switch (mode->scale) {
++ case SCALE_4CIFS:
++ linesPerFrame = NUM_LINES_4CIFS_PAL * 2;
++ pixelsPerLine = LINE_SZ_4CIFS_PAL;
++ break;
++ case SCALE_2CIFS:
++ linesPerFrame = NUM_LINES_2CIFS_PAL;
++ pixelsPerLine = LINE_SZ_2CIFS_PAL;
++ break;
++ case SCALE_1CIFS:
++ linesPerFrame = NUM_LINES_1CIFS_PAL;
++ pixelsPerLine = LINE_SZ_1CIFS_PAL;
++ break;
++ default:
++ break;
++ }
++ }
++ outImageSize = linesPerFrame * pixelsPerLine;
++ if (mode->color != COLOR_Y8) {
++ /* 2 bytes/pixel if not monochrome */
++ outImageSize *= 2;
++ }
++
++ /* total bytes to send including prefix and 4K padding;
++ must be a multiple of USB_READ_SIZE */
++ usbInSize = outImageSize + PREFIX_SIZE; /* always send prefix */
++ mask_mult = 0xffffffffUL - DEF_USB_BLOCK + 1;
++ /* if size not a multiple of USB_READ_SIZE */
++ if (usbInSize & ~mask_mult)
++ usbInSize = (usbInSize & mask_mult) + (DEF_USB_BLOCK);
++ return usbInSize;
++}
++
++static void dump_verify_mode(struct s2255_dev *sdev, struct mode2255i *mode)
++{
++ struct device *dev = &sdev->udev->dev;
++ dev_info(dev, "------------------------------------------------\n");
++ dev_info(dev, "verify mode\n");
++ dev_info(dev, "format: %d\n", mode->format);
++ dev_info(dev, "scale: %d\n", mode->scale);
++ dev_info(dev, "fdec: %d\n", mode->fdec);
++ dev_info(dev, "color: %d\n", mode->color);
++ dev_info(dev, "bright: 0x%x\n", mode->bright);
++ dev_info(dev, "restart: 0x%x\n", mode->restart);
++ dev_info(dev, "usb_block: 0x%x\n", mode->usb_block);
++ dev_info(dev, "single: 0x%x\n", mode->single);
++ dev_info(dev, "------------------------------------------------\n");
++}
++
++/*
++ * set mode is the function which controls the DSP.
++ * the restart parameter in struct mode2255i should be set whenever
++ * the image size could change via color format, video system or image
++ * size.
++ * When the restart parameter is set, we sleep for ONE frame to allow the
++ * DSP time to get the new frame
++ */
++static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
++ struct mode2255i *mode)
++{
++ int res;
++ u32 *buffer;
++ unsigned long chn_rev;
++
++ chn_rev = G_chnmap[chn];
++ dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale);
++ dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn],
++ dev->mode[chn].scale);
++ dprintk(2, "mode contrast %x\n", mode->contrast);
++
++ /* save the mode */
++ dev->mode[chn] = *mode;
++ dev->req_image_size[chn] = get_transfer_size(mode);
++ dprintk(1, "transfer size %ld\n", dev->req_image_size[chn]);
++
++ buffer = kzalloc(512, GFP_KERNEL);
++ if (buffer == NULL) {
++ dev_err(&dev->udev->dev, "out of mem\n");
++ return -ENOMEM;
++ }
++
++ /* set the mode */
++ buffer[0] = IN_DATA_TOKEN;
++ buffer[1] = (u32) chn_rev;
++ buffer[2] = CMD_SET_MODE;
++ memcpy(&buffer[3], &dev->mode[chn], sizeof(struct mode2255i));
++ res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
++ if (debug)
++ dump_verify_mode(dev, mode);
++ kfree(buffer);
++ dprintk(1, "set mode done chn %lu, %d\n", chn, res);
++
++ /* wait at least one frame before continuing */
++
++ s2255_sleep(40);
++
++ /* clear the restart flag */
++ dev->mode[chn].restart = 0;
++
++ return res;
++}
++
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ int res;
@@ -41671,17 +41990,17 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ struct mode2255i *mode;
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-+ printk("invalid fh type0\n");
++ dev_err(&dev->udev->dev, "invalid fh type0\n");
+ return -EINVAL;
+ }
+
+ if (i != fh->type) {
-+ printk("invalid fh type1\n");
++ dev_err(&dev->udev->dev, "invalid fh type1\n");
+ return -EINVAL;
+ }
+
+ if (!res_get(dev, fh)) {
-+ printk("res get busy\n");
++ dev_err(&dev->udev->dev, "res get busy\n");
+ return -EBUSY;
+ }
+ /* send a set mode command everytime with restart.
@@ -41701,15 +42020,16 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ int res;
+ struct s2255_fh *fh = priv;
+ struct s2255_dev *dev = fh->dev;
++
+ dprintk(1, "[%d]videobuf stream off\n", fh->channel);
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-+ printk("invalid fh type0\n");
++ dev_err(&dev->udev->dev, "invalid fh type0\n");
+ return -EINVAL;
+ }
+
+ if (i != fh->type) {
-+ printk("invalid fh type1\n");
++ dev_err(&dev->udev->dev, "invalid fh type1\n");
+ return -EINVAL;
+ }
+
@@ -41880,7 +42200,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ if (dev->users[cur_channel] > 1) {
+ dev->users[cur_channel]--;
-+ printk("one user at a time\n");
++ dev_err(&dev->udev->dev, "one user at a time\n");
+ mutex_unlock(&usb_s2255_open_mutex);
+ return -EAGAIN;
+ }
@@ -41950,7 +42270,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ struct s2255_fh *fh = file->private_data;
+ struct s2255_buffer *buf;
+
-+ dprintk(100, "%s\n", __FUNCTION__);
++ dprintk(100, "%s\n", __func__);
+
+ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+ return POLLERR;
@@ -41975,6 +42295,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ return 0;
+}
+
++static void s2255_destroy(struct kref *kref)
++{
++ struct s2255_dev *dev = to_s2255_dev(kref);
++
++ usb_put_dev(dev->udev);
++ dprintk(1, "s2255_destroy\n");
++ kfree(dev);
++}
++
+static int s2255_release_v4l(struct inode *inode, struct file *file)
+{
+ struct s2255_fh *fh = file->private_data;
@@ -42086,7 +42415,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ dev->vdev[i]->priv = dev;
+
+ if (ret != 0) {
-+ printk("failed register video device!\n");
++ dev_err(&dev->udev->dev,
++ "failed to register video device!\n");
+ return ret;
+ }
+ }
@@ -42110,21 +42440,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ }
+}
+
-+#define EP_NUM_CONFIG 2
-+/* write to the configuration pipe, synchronously */
-+static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
-+ int size)
-+{
-+ int pipe;
-+ int done;
-+ long retval = -1;
-+ if (udev) {
-+ pipe = usb_sndbulkpipe(udev, EP_NUM_CONFIG);
-+ retval = usb_bulk_msg(udev, pipe, pbuf, size, &done, 500);
-+ }
-+ return retval;
-+}
-+
+/* this function moves the usb stream read pipe data
+ * into the system buffers.
+ * returns 0 on success, EAGAIN if more data to process( call this
@@ -42136,7 +42451,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ * bytes 8-11: payload size: size of the frame
+ * bytes 12-payloadsize+12: frame data
+ */
-+static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pPipeInfo)
++static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
+{
+ static int dbgsync; /* = 0; */
+ char *pdest;
@@ -42171,7 +42486,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ }
+
+ if (bsearch) {
-+ if (*(s32 *) pPipeInfo->pTransferBuffer != FRAME_MARKER) {
++ if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) {
+ u32 jj;
+ if (dbgsync == 0) {
+ dprintk(3, "not synched, discarding all packets"
@@ -42179,8 +42494,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ dbgsync++;
+ }
-+ pdata = (unsigned char *)pPipeInfo->pTransferBuffer;
-+ for (jj = 0; jj < (pPipeInfo->cur_transfer_size - 12);
++ pdata = (unsigned char *)pipe_info->transfer_buffer;
++ for (jj = 0; jj < (pipe_info->cur_transfer_size - 12);
+ jj++) {
+ if (*(s32 *) pdata == FRAME_MARKER) {
+ int cc;
@@ -42210,7 +42525,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ int cc;
+ dbgsync = 0;
+ bsync = 1;
-+ pword = (u32 *) pPipeInfo->pTransferBuffer;
++ pword = (u32 *) pipe_info->transfer_buffer;
+ cc = pword[1];
+
+ if (cc >= MAX_CHANNELS) {
@@ -42252,9 +42567,9 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ if (bsync) {
+ /* skip the marker 512 bytes (and offset if out of sync) */
-+ psrc = (u8 *)pPipeInfo->pTransferBuffer + offset + PREFIX_SIZE;
++ psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE;
+ } else {
-+ psrc = (u8 *)pPipeInfo->pTransferBuffer;
++ psrc = (u8 *)pipe_info->transfer_buffer;
+ }
+
+ if (frm->lpvbits == NULL) {
@@ -42267,13 +42582,13 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ if (bsync) {
+ copy_size =
-+ (pPipeInfo->cur_transfer_size - offset) - PREFIX_SIZE;
-+ if (copy_size > pPipeInfo->cur_transfer_size) {
++ (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE;
++ if (copy_size > pipe_info->cur_transfer_size) {
+ printk("invalid copy size, overflow!\n");
+ return -ENOMEM;
+ }
+ } else {
-+ copy_size = pPipeInfo->cur_transfer_size;
++ copy_size = pipe_info->cur_transfer_size;
+ }
+
+ cur_size = frm->cur_size;
@@ -42297,10 +42612,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ dev->last_frame[cc] = dev->cur_frame[cc];
+ dev->cur_frame[cc]++;
+ /* end of system frame ring buffer, start at zero */
-+ if ((dev->cur_frame[cc] == SYS_FRAMES)
-+ || (dev->cur_frame[cc] == dev->buffer[cc].dwFrames)) {
++ if ((dev->cur_frame[cc] == SYS_FRAMES) ||
++ (dev->cur_frame[cc] == dev->buffer[cc].dwFrames))
+ dev->cur_frame[cc] = 0;
-+ }
++
+ /* signal the semaphore for this channel */
+ s2255_got_frame(dev, cc);
+ dev->frame_count[cc]++;
@@ -42315,7 +42630,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+}
+
+static void s2255_read_video_callback(struct s2255_dev *dev,
-+ struct s2255_pipeinfo *pPipeInfo)
++ struct s2255_pipeinfo *pipe_info)
+{
+ int res;
+ int b_acq = 0;
@@ -42324,7 +42639,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ if (dev->cc >= MAX_CHANNELS) {
+ dev->cc = 0;
-+ printk("invalid channel\n");
++ dev_err(&dev->udev->dev, "invalid channel\n");
+ return;
+ }
+
@@ -42340,70 +42655,51 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ return;
+
+ /* otherwise copy to the system buffers */
-+ res = save_frame(dev, pPipeInfo);
++ res = save_frame(dev, pipe_info);
+ if (res == EAGAIN)
-+ save_frame(dev, pPipeInfo);
++ save_frame(dev, pipe_info);
+
+ dprintk(50, "callback read video done\n");
+ return;
+}
+
-+static int s2255_board_init(struct s2255_dev *dev)
++static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
++ u16 Index, u16 Value, void *TransferBuffer,
++ s32 TransferBufferLength, int bOut)
+{
-+ int j;
-+ struct mode2255i mode_def = { DEF_MODEI_NTSC_CONT };
-+ int fw_ver;
-+ dprintk(4, "board init: %p", dev);
-+
-+ for (j = 0; j < MAX_CHANNELS; j++) {
-+ dev->b_acquire[j] = 0;
-+ dev->mode[j] = mode_def;
-+ dev->req_image_size[j] = get_transfer_size(&mode_def);
-+ }
-+
-+ for (j = 0; j < MAX_PIPE_BUFFERS; j++) {
-+ struct s2255_pipeinfo *pPipeInfo = &dev->UsbPipes[j];
-+ memset(pPipeInfo, sizeof(struct s2255_pipeinfo), 0);
-+ pPipeInfo->state = 0;
-+ pPipeInfo->prev_state = 0;
-+ pPipeInfo->dev = dev;
-+ pPipeInfo->cur_transfer_size = DEFAULT_PIPE_USBBLOCK;
-+ pPipeInfo->max_transfer_size = MAX_PIPE_USBBLOCK;
-+
-+ if (pPipeInfo->cur_transfer_size > pPipeInfo->max_transfer_size) {
-+ pPipeInfo->cur_transfer_size =
-+ pPipeInfo->max_transfer_size;
-+ }
-+ pPipeInfo->pTransferBuffer =
-+ (unsigned char *)kzalloc(pPipeInfo->max_transfer_size,
-+ GFP_KERNEL);
-+ if (pPipeInfo->pTransferBuffer == NULL) {
-+ dprintk(1, "out of memory!\n");
-+ return -ENOMEM;
-+ }
-+
-+ }
-+
-+ /* query the firmware */
-+ fw_ver = s2255_get_fx2fw(dev);
-+
-+ printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver);
-+ if (fw_ver < CUR_USB_FWVER)
-+ err("usb firmware not up to date %d\n", fw_ver);
-+
-+ for (j = 0; j < MAX_CHANNELS; j++) {
-+ dev->b_acquire[j] = 0;
-+ dev->mode[j] = mode_def;
-+ dev->req_image_size[j] = get_transfer_size(&mode_def);
-+ dev->frame_count[j] = 0;
-+ /* create the system buffers */
-+ s2255_create_sys_buffers(dev, j);
++ int r;
++ if (!bOut) {
++ r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
++ Request,
++ USB_TYPE_VENDOR | USB_RECIP_DEVICE |
++ USB_DIR_IN,
++ Value, Index, TransferBuffer,
++ TransferBufferLength, HZ * 5);
++ } else {
++ r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
++ Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++ Value, Index, TransferBuffer,
++ TransferBufferLength, HZ * 5);
+ }
-+ /* start read pipe */
-+ s2255_start_readpipe(dev);
++ return r;
++}
+
-+ dprintk(1, "S2255: board initialized\n");
-+ return 0;
++/*
++ * retrieve FX2 firmware version. future use.
++ * @param dev pointer to device extension
++ * @return -1 for fail, else returns firmware version as an int(16 bits)
++ */
++static int s2255_get_fx2fw(struct s2255_dev *dev)
++{
++ int fw;
++ int ret;
++ unsigned char transBuffer[64];
++ ret = s2255_vendor_req(dev, VX_FW, 0, 0, transBuffer, 2, DIR_IN);
++ if (ret < 0)
++ dprintk(2, "get fw error: %x\n", ret);
++ fw = transBuffer[0] + (transBuffer[1] << 8);
++ dprintk(2, "Get FW %x %x\n", transBuffer[0], transBuffer[1]);
++ return fw;
+}
+
+/*
@@ -42468,6 +42764,62 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ return 0;
+}
+
++static int s2255_board_init(struct s2255_dev *dev)
++{
++ int j;
++ struct mode2255i mode_def = { DEF_MODEI_NTSC_CONT };
++ int fw_ver;
++ dprintk(4, "board init: %p", dev);
++
++ for (j = 0; j < MAX_CHANNELS; j++) {
++ dev->b_acquire[j] = 0;
++ dev->mode[j] = mode_def;
++ dev->req_image_size[j] = get_transfer_size(&mode_def);
++ }
++
++ for (j = 0; j < MAX_PIPE_BUFFERS; j++) {
++ struct s2255_pipeinfo *pipe = &dev->pipes[j];
++
++ memset(pipe, sizeof(struct s2255_pipeinfo), 0);
++ pipe->state = 0;
++ pipe->prev_state = 0;
++ pipe->dev = dev;
++ pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK;
++ pipe->max_transfer_size = MAX_PIPE_USBBLOCK;
++
++ if (pipe->cur_transfer_size > pipe->max_transfer_size)
++ pipe->cur_transfer_size = pipe->max_transfer_size;
++ pipe->transfer_buffer = kzalloc(pipe->max_transfer_size,
++ GFP_KERNEL);
++ if (pipe->transfer_buffer == NULL) {
++ dprintk(1, "out of memory!\n");
++ return -ENOMEM;
++ }
++
++ }
++
++ /* query the firmware */
++ fw_ver = s2255_get_fx2fw(dev);
++
++ printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver);
++ if (fw_ver < CUR_USB_FWVER)
++ err("usb firmware not up to date %d\n", fw_ver);
++
++ for (j = 0; j < MAX_CHANNELS; j++) {
++ dev->b_acquire[j] = 0;
++ dev->mode[j] = mode_def;
++ dev->req_image_size[j] = get_transfer_size(&mode_def);
++ dev->frame_count[j] = 0;
++ /* create the system buffers */
++ s2255_create_sys_buffers(dev, j);
++ }
++ /* start read pipe */
++ s2255_start_readpipe(dev);
++
++ dprintk(1, "S2255: board initialized\n");
++ return 0;
++}
++
+static int s2255_board_shutdown(struct s2255_dev *dev)
+{
+ u32 i;
@@ -42483,33 +42835,30 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+ /* release transfer buffers */
+ for (i = 0; i < MAX_PIPE_BUFFERS; i++) {
-+ struct s2255_pipeinfo *pPipeInfo = &dev->UsbPipes[i];
-+ if (pPipeInfo->pTransferBuffer) {
-+ kfree(pPipeInfo->pTransferBuffer);
-+ }
++ struct s2255_pipeinfo *pipe = &dev->pipes[i];
++ kfree(pipe->transfer_buffer);
+ }
+ return 0;
+}
+
+static void read_pipe_completion(struct urb *purb)
+{
-+ struct s2255_pipeinfo *pPipeInfo;
++ struct s2255_pipeinfo *pipe_info;
+ struct s2255_dev *dev;
+ int status;
+ int pipe;
+
-+ pPipeInfo = (struct s2255_pipeinfo *)purb->context;
++ pipe_info = purb->context;
+ dprintk(100, "read pipe completion %p, status %d\n", purb,
+ purb->status);
-+ if (pPipeInfo == NULL) {
-+ printk("no context !\n");
++ if (pipe_info == NULL) {
++ err("no context !");
+ return;
+ }
+
-+ dev = (struct s2255_dev *)pPipeInfo->dev;
-+
++ dev = pipe_info->dev;
+ if (dev == NULL) {
-+ printk("no context !\n");
++ err("no context !");
+ return;
+ }
+ status = purb->status;
@@ -42518,26 +42867,26 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ return;
+ }
+
-+ if (pPipeInfo->state == 0) {
++ if (pipe_info->state == 0) {
+ dprintk(2, "exiting USB pipe");
+ return;
+ }
+
-+ s2255_read_video_callback(dev, pPipeInfo);
++ s2255_read_video_callback(dev, pipe_info);
+
-+ pPipeInfo->err_count = 0;
++ pipe_info->err_count = 0;
+ pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
+ /* reuse urb */
-+ usb_fill_bulk_urb(pPipeInfo->pStreamUrb, dev->udev,
++ usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
+ pipe,
-+ pPipeInfo->pTransferBuffer,
-+ pPipeInfo->cur_transfer_size,
-+ read_pipe_completion, pPipeInfo);
-+
-+ if (pPipeInfo->state != 0) {
-+ if (usb_submit_urb(pPipeInfo->pStreamUrb, GFP_KERNEL)) {
-+ printk("error submitting urb\n");
-+ usb_free_urb(pPipeInfo->pStreamUrb);
++ pipe_info->transfer_buffer,
++ pipe_info->cur_transfer_size,
++ read_pipe_completion, pipe_info);
++
++ if (pipe_info->state != 0) {
++ if (usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL)) {
++ dev_err(&dev->udev->dev, "error submitting urb\n");
++ usb_free_urb(pipe_info->stream_urb);
+ }
+ }
+ return;
@@ -42548,29 +42897,30 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ int pipe;
+ int retval;
+ int i;
-+ struct s2255_pipeinfo *pPipeInfo = dev->UsbPipes;
++ struct s2255_pipeinfo *pipe_info = dev->pipes;
+ pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
+ dprintk(2, "start pipe IN %d\n", dev->read_endpoint);
+
+ for (i = 0; i < MAX_PIPE_BUFFERS; i++) {
-+ pPipeInfo->state = 1;
-+ pPipeInfo->buf_index = (u32) i;
-+ pPipeInfo->priority_set = 0;
-+ pPipeInfo->pStreamUrb = usb_alloc_urb(0, GFP_KERNEL);
-+ if (!pPipeInfo->pStreamUrb) {
-+ printk("ReadStream : Unable to alloc URB");
++ pipe_info->state = 1;
++ pipe_info->buf_index = (u32) i;
++ pipe_info->priority_set = 0;
++ pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
++ if (!pipe_info->stream_urb) {
++ dev_err(&dev->udev->dev,
++ "ReadStream: Unable to alloc URB");
+ return -ENOMEM;
+ }
+ /* transfer buffer allocated in board_init */
-+ usb_fill_bulk_urb(pPipeInfo->pStreamUrb, dev->udev,
++ usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
+ pipe,
-+ pPipeInfo->pTransferBuffer,
-+ pPipeInfo->cur_transfer_size,
-+ read_pipe_completion, pPipeInfo);
++ pipe_info->transfer_buffer,
++ pipe_info->cur_transfer_size,
++ read_pipe_completion, pipe_info);
+
-+ pPipeInfo->urb_size = sizeof(pPipeInfo->pStreamUrb);
-+ dprintk(4, "submitting URB %p\n", pPipeInfo->pStreamUrb);
-+ retval = usb_submit_urb(pPipeInfo->pStreamUrb, GFP_KERNEL);
++ pipe_info->urb_size = sizeof(pipe_info->stream_urb);
++ dprintk(4, "submitting URB %p\n", pipe_info->stream_urb);
++ retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
+ if (retval) {
+ printk(KERN_ERR "s2255: start read pipe failed\n");
+ return retval;
@@ -42580,92 +42930,10 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ return 0;
+}
+
-+static void s2255_sleep(int ms)
-+{
-+ wait_queue_head_t sleep_q;
-+ DEFINE_WAIT(wait);
-+ if (ms == 0) {
-+ schedule();
-+ return;
-+ }
-+ init_waitqueue_head(&sleep_q);
-+ prepare_to_wait(&sleep_q, &wait, TASK_INTERRUPTIBLE);
-+ schedule_timeout((ms * HZ) / 1000);
-+ finish_wait(&sleep_q, &wait);
-+}
-+
-+static void dump_verify_mode(struct mode2255i *mode)
-+{
-+ printk("-------------------------------------------------------\n");
-+ printk("verify mode\n");
-+ printk("format: %d\n", mode->format);
-+ printk("scale: %d\n", mode->scale);
-+ printk("fdec: %d\n", mode->fdec);
-+ printk("color: %d\n", mode->color);
-+ printk("bright: 0x%x\n", mode->bright);
-+ printk("restart: 0x%x\n", mode->restart);
-+ printk("Usbblock: 0x%x\n", mode->usb_block);
-+ printk("single: 0x%x\n", mode->single);
-+ printk("-------------------------------------------------------\n");
-+}
-+
-+/*
-+ * set mode is the function which controls the DSP.
-+ * the restart parameter in struct mode2255i should be set whenever
-+ * the image size could change via color format, video system or image
-+ * size.
-+ * When the restart parameter is set, we sleep for ONE frame to allow the
-+ * DSP time to get the new frame
-+ */
-+static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
-+ struct mode2255i *mode)
-+{
-+ int res;
-+ u32 *pBuf;
-+ unsigned long chn_rev;
-+
-+ chn_rev = G_chnmap[chn];
-+ dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale);
-+ dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn],
-+ dev->mode[chn].scale);
-+ dprintk(2, "mode contrast %x\n", mode->contrast);
-+
-+ /* save the mode */
-+ dev->mode[chn] = *mode;
-+ dev->req_image_size[chn] = get_transfer_size(mode);
-+ dprintk(1, "transfer size %ld\n", dev->req_image_size[chn]);
-+
-+ pBuf = (u32 *) kzalloc(512, GFP_KERNEL);
-+ if (pBuf == NULL) {
-+ printk("out of mem\n");
-+ return -1;
-+ }
-+
-+ /* set the mode */
-+ pBuf[0] = IN_DATA_TOKEN;
-+ pBuf[1] = (u32) chn_rev;
-+ pBuf[2] = CMD_SET_MODE;
-+ memcpy(&pBuf[3], &dev->mode[chn], sizeof(struct mode2255i));
-+ res = s2255_write_config(dev->udev, (unsigned char *)pBuf, 512);
-+ if (debug)
-+ dump_verify_mode(mode);
-+ kfree(pBuf);
-+ dprintk(1, "set mode done chn %lu, %d\n", chn, res);
-+
-+ /* wait at least one frame before continuing */
-+
-+ s2255_sleep(40);
-+
-+ /* clear the restart flag */
-+ dev->mode[chn].restart = 0;
-+
-+ return res;
-+}
-+
+/* starts acquisition process */
+static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn)
+{
-+ unsigned char *pBuf;
++ unsigned char *buffer;
+ int res;
+ unsigned long chn_rev;
+
@@ -42676,27 +42944,27 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ chn_rev = G_chnmap[chn];
+ dprintk(1, "S2255: start acquire %lu \n", chn);
+
-+ pBuf = (unsigned char *)kzalloc(512, GFP_KERNEL);
-+ if (pBuf == NULL) {
-+ printk("out of mem\n");
-+ return -1;
++ buffer = kzalloc(512, GFP_KERNEL);
++ if (buffer == NULL) {
++ dev_err(&dev->udev->dev, "out of mem\n");
++ return -ENOMEM;
+ }
+ /* send the start command */
-+ *(u32 *) pBuf = IN_DATA_TOKEN;
-+ *((u32 *) pBuf + 1) = (u32) chn_rev;
-+ *((u32 *) pBuf + 2) = (u32) CMD_START;
-+ res = s2255_write_config(dev->udev, (unsigned char *)pBuf, 512);
++ *(u32 *) buffer = IN_DATA_TOKEN;
++ *((u32 *) buffer + 1) = (u32) chn_rev;
++ *((u32 *) buffer + 2) = (u32) CMD_START;
++ res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
+ if (res != 0)
-+ printk("S2255: CMD_START error\n");
++ dev_err(&dev->udev->dev, "CMD_START error\n");
+
+ dprintk(2, "start acquire exit[%lu] %d \n", chn, res);
-+ kfree(pBuf);
++ kfree(buffer);
+ return 0;
+}
+
+static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn)
+{
-+ unsigned char *pBuf;
++ unsigned char *buffer;
+ int res;
+ unsigned long chn_rev;
+
@@ -42706,25 +42974,25 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ }
+ chn_rev = G_chnmap[chn];
+
-+ pBuf = (unsigned char *)kzalloc(512, GFP_KERNEL);
-+ if (pBuf == NULL) {
-+ printk("out of mem\n");
-+ return -1;
++ buffer = kzalloc(512, GFP_KERNEL);
++ if (buffer == NULL) {
++ dev_err(&dev->udev->dev, "out of mem\n");
++ return -ENOMEM;
+ }
+
+ /* send the stop command */
+ dprintk(1, "stop acquire %lu\n", chn);
-+ *(u32 *) pBuf = IN_DATA_TOKEN;
-+ *((u32 *) pBuf + 1) = (u32) chn_rev;
-+ *((u32 *) pBuf + 2) = CMD_STOP;
-+ res = s2255_write_config(dev->udev, (unsigned char *)pBuf, 512);
++ *(u32 *) buffer = IN_DATA_TOKEN;
++ *((u32 *) buffer + 1) = (u32) chn_rev;
++ *((u32 *) buffer + 2) = CMD_STOP;
++ res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
+
+ if (res != 0)
-+ printk("CMD_STOP error\n");
++ dev_err(&dev->udev->dev, "CMD_STOP error\n");
+
+ dprintk(4, "stop acquire: releasing states \n");
+
-+ kfree(pBuf);
++ kfree(buffer);
+
+ return 0;
+}
@@ -42732,555 +43000,192 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+static void s2255_stop_readpipe(struct s2255_dev *dev)
+{
+ int j;
++
+ if (dev == NULL) {
-+ printk("s2255: invalid device\n");
++ err("s2255: invalid device");
+ return;
+ }
+ dprintk(4, "stop read pipe\n");
+ for (j = 0; j < MAX_PIPE_BUFFERS; j++) {
-+ struct s2255_pipeinfo *pPipeInfo = &dev->UsbPipes[j];
-+ if (pPipeInfo) {
-+ if (pPipeInfo->state == 0)
++ struct s2255_pipeinfo *pipe_info = &dev->pipes[j];
++ if (pipe_info) {
++ if (pipe_info->state == 0)
+ continue;
-+ pPipeInfo->state = 0;
-+ pPipeInfo->prev_state = 1;
++ pipe_info->state = 0;
++ pipe_info->prev_state = 1;
+
+ }
+ }
+
+ for (j = 0; j < MAX_PIPE_BUFFERS; j++) {
-+ struct s2255_pipeinfo *pPipeInfo = &dev->UsbPipes[j];
-+ if (pPipeInfo->pStreamUrb) {
++ struct s2255_pipeinfo *pipe_info = &dev->pipes[j];
++ if (pipe_info->stream_urb) {
+ /* cancel urb */
-+ usb_kill_urb(pPipeInfo->pStreamUrb);
-+ usb_free_urb(pPipeInfo->pStreamUrb);
-+ pPipeInfo->pStreamUrb = NULL;
++ usb_kill_urb(pipe_info->stream_urb);
++ usb_free_urb(pipe_info->stream_urb);
++ pipe_info->stream_urb = NULL;
+ }
+ }
+ dprintk(2, "s2255 stop read pipe: %d\n", j);
+ return;
+}
+
-+static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
-+ u16 Index, u16 Value, void *TransferBuffer,
-+ s32 TransferBufferLength, int bOut)
-+{
-+ int r;
-+ if (!bOut) {
-+ r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-+ Request,
-+ USB_TYPE_VENDOR | USB_RECIP_DEVICE |
-+ USB_DIR_IN,
-+ Value, Index, TransferBuffer,
-+ TransferBufferLength, HZ * 5);
-+ } else {
-+ r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-+ Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+ Value, Index, TransferBuffer,
-+ TransferBufferLength, HZ * 5);
-+ }
-+ return r;
-+}
-+
-+static u32 get_transfer_size(struct mode2255i *mode)
-+{
-+ int linesPerFrame = LINE_SZ_DEF;
-+ int pixelsPerLine = NUM_LINES_DEF;
-+ u32 outImageSize;
-+ u32 usbInSize;
-+ unsigned int mask_mult;
-+
-+ if (mode == NULL)
-+ return 0;
-+
-+ if (mode->format == FORMAT_NTSC) {
-+ switch (mode->scale) {
-+ case SCALE_4CIFS:
-+ linesPerFrame = NUM_LINES_4CIFS_NTSC * 2;
-+ pixelsPerLine = LINE_SZ_4CIFS_NTSC;
-+ break;
-+ case SCALE_2CIFS:
-+ linesPerFrame = NUM_LINES_2CIFS_NTSC;
-+ pixelsPerLine = LINE_SZ_2CIFS_NTSC;
-+ break;
-+ case SCALE_1CIFS:
-+ linesPerFrame = NUM_LINES_1CIFS_NTSC;
-+ pixelsPerLine = LINE_SZ_1CIFS_NTSC;
-+ break;
-+ default:
-+ break;
-+ }
-+ } else if (mode->format == FORMAT_PAL) {
-+ switch (mode->scale) {
-+ case SCALE_4CIFS:
-+ linesPerFrame = NUM_LINES_4CIFS_PAL * 2;
-+ pixelsPerLine = LINE_SZ_4CIFS_PAL;
-+ break;
-+ case SCALE_2CIFS:
-+ linesPerFrame = NUM_LINES_2CIFS_PAL;
-+ pixelsPerLine = LINE_SZ_2CIFS_PAL;
-+ break;
-+ case SCALE_1CIFS:
-+ linesPerFrame = NUM_LINES_1CIFS_PAL;
-+ pixelsPerLine = LINE_SZ_1CIFS_PAL;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ outImageSize = linesPerFrame * pixelsPerLine;
-+ if (mode->color != COLOR_Y8) {
-+ /* 2 bytes/pixel if not monochrome */
-+ outImageSize *= 2;
-+ }
-+
-+ /* total bytes to send including prefix and 4K padding;
-+ must be a multiple of USB_READ_SIZE */
-+ usbInSize = outImageSize + PREFIX_SIZE; /* always send prefix */
-+ mask_mult = 0xffffffffUL - DEF_USB_BLOCK + 1;
-+ /* if size not a multiple of USB_READ_SIZE */
-+ if (usbInSize & ~mask_mult)
-+ usbInSize = (usbInSize & mask_mult) + (DEF_USB_BLOCK);
-+ return usbInSize;
-+}
-+
-+/*
-+ * convert from YUV(YCrCb) to RGB
-+ * 65536 R = 76533(Y-16) + 104936 * (Cr-128)
-+ * 65536 G = 76533(Y-16) - 53451(Cr-128) - 25703(Cb -128)
-+ * 65536 B = 76533(Y-16) + 132677(Cb-128)
-+ */
-+static void YCrCb2RGB(int Y, int Cr, int Cb, unsigned char *pR,
-+ unsigned char *pG, unsigned char *pB)
++/* standard usb probe function */
++static int s2255_probe(struct usb_interface *interface,
++ const struct usb_device_id *id)
+{
-+ int R, G, B;
-+
-+ Y = Y - 16;
-+ Cr = Cr - 128;
-+ Cb = Cb - 128;
++ struct s2255_dev *dev = NULL;
++ struct usb_host_interface *iface_desc;
++ struct usb_endpoint_descriptor *endpoint;
++ int i;
++ int retval = -ENOMEM;
+
-+ R = (76533 * Y + 104936 * Cr) >> 16;
-+ G = ((76533 * Y) - (53451 * Cr) - (25703 * Cb)) >> 16;
-+ B = ((76533 * Y) + (132677 * Cb)) >> 16;
-+ /* even with proper conversion, some values still need clipping. */
-+ if (R > 255)
-+ R = 255;
-+ if (G > 255)
-+ G = 255;
-+ if (B > 255)
-+ B = 255;
-+ if (R < 0)
-+ R = 0;
-+ if (G < 0)
-+ G = 0;
-+ if (B < 0)
-+ B = 0;
-+ *pR = R;
-+ *pG = G;
-+ *pB = B;
-+ return;
-+}
++ dprintk(100, "s2255: probe\n");
+
-+/* converts 2255 planar format to yuyv */
-+static void planar422p_to_yuy2(const unsigned char *in, unsigned char *out,
-+ int width, int height)
-+{
-+ unsigned char *pY;
-+ unsigned char *pCb;
-+ unsigned char *pCr;
-+ unsigned long size = height * width;
-+ unsigned int i;
-+ pY = (unsigned char *)in;
-+ pCr = (unsigned char *)in + height * width;
-+ pCb = (unsigned char *)in + height * width + (height * width / 2);
-+ for (i = 0; i < size * 2; i += 4) {
-+ out[i] = *pY++;
-+ out[i + 1] = *pCr++;
-+ out[i + 2] = *pY++;
-+ out[i + 3] = *pCb++;
++ /* allocate memory for our device state and initialize it to zero */
++ dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
++ if (dev == NULL) {
++ err("s2255: out of memory");
++ goto error;
+ }
-+ return;
-+}
+
-+/*
-+ * basic 422 planar to RGB24 or BGR24 software conversion.
-+ * This is best done with MMX. Update to kernel function
-+ * when image conversion functions added to kernel.
-+ */
-+static void planar422p_to_rgb24(const unsigned char *in,
-+ unsigned char *out, int width,
-+ int height, int rev_order)
-+{
-+ unsigned char *pY;
-+ unsigned char *pYEND;
-+ unsigned char *pCb;
-+ unsigned char *pCr;
-+ unsigned char Cr, Cb, Y, r, g, b;
-+ unsigned long k = 0;
-+ pY = (unsigned char *)in;
-+ pCb = (unsigned char *)in + (height * width);
-+ pCr = (unsigned char *)in + (height * width) + (height * width / 2);
-+ pYEND = pCb;
-+ while (pY < pYEND) {
-+ Y = *pY++;
-+ Cr = *pCr;
-+ Cb = *pCb;
-+ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
-+ out[k++] = !rev_order ? b : r;
-+ out[k++] = g;
-+ out[k++] = !rev_order ? r : b;
-+ if (pY >= pYEND)
-+ break;
-+ Y = *pY++;
-+ Cr = *pCr++;
-+ Cb = *pCb++;
-+ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
-+ out[k++] = !rev_order ? b : r;
-+ out[k++] = g;
-+ out[k++] = !rev_order ? r : b;
++ /* grab usb_device and save it */
++ dev->udev = usb_get_dev(interface_to_usbdev(interface));
++ if (dev->udev == NULL) {
++ dev_err(&interface->dev, "null usb device\n");
++ goto error;
+ }
-+ return;
-+}
+
-+static void planar422p_to_rgb32(const unsigned char *in, unsigned char *out,
-+ int width, int height, int rev_order)
-+{
-+ unsigned char *pY;
-+ unsigned char *pYEND;
-+ unsigned char *pCb;
-+ unsigned char *pCr;
-+ unsigned char Cr, Cb, Y, r, g, b;
-+ unsigned long k = 0;
-+ pY = (unsigned char *)in;
-+ pCb = (unsigned char *)in + (height * width);
-+ pCr = (unsigned char *)in + (height * width) + (height * width / 2);
-+ pYEND = pCb;
-+ while (pY < pYEND) {
-+ Y = *pY++;
-+ Cr = *pCr;
-+ Cb = *pCb;
-+ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
-+ out[k++] = rev_order ? b : r;
-+ out[k++] = g;
-+ out[k++] = rev_order ? r : b;
-+ out[k++] = 0;
-+ if (pY >= pYEND)
-+ break;
-+ Y = *pY++;
-+ Cr = *pCr++;
-+ Cb = *pCb++;
-+ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
-+ out[k++] = rev_order ? b : r;
-+ out[k++] = g;
-+ out[k++] = rev_order ? r : b;
-+ out[k++] = 0;
++ kref_init(&dev->kref);
++ dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref,
++ dev->udev, interface);
++ dev->interface = interface;
++ /* set up the endpoint information */
++ iface_desc = interface->cur_altsetting;
++ dprintk(1, "num endpoints %d\n", iface_desc->desc.bNumEndpoints);
++ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
++ endpoint = &iface_desc->endpoint[i].desc;
++ if (!dev->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
++ /* we found the bulk in endpoint */
++ dev->read_endpoint = endpoint->bEndpointAddress;
++ }
+ }
+
-+ return;
-+}
-+
-+static void planar422p_to_rgb565(unsigned char const *in, unsigned char *out,
-+ int width, int height, int rev_order)
-+{
-+ unsigned char *pY;
-+ unsigned char *pYEND;
-+ unsigned char *pCb;
-+ unsigned char *pCr;
-+ unsigned char Cr, Cb, Y, r, g, b;
-+ unsigned long k = 0;
-+ unsigned short rgbbytes;
-+ pY = (unsigned char *)in;
-+ pCb = (unsigned char *)in + (height * width);
-+ pCr = (unsigned char *)in + (height * width) + (height * width / 2);
-+ pYEND = pCb;
-+ while (pY < pYEND) {
-+ Y = *pY++;
-+ Cr = *pCr;
-+ Cb = *pCb;
-+ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
-+ r = r >> 3;
-+ g = g >> 2;
-+ b = b >> 3;
-+ if (rev_order)
-+ rgbbytes = b + (g << 5) + (r << (5 + 6));
-+ else
-+ rgbbytes = r + (g << 5) + (b << (5 + 6));
-+ out[k++] = rgbbytes & 0xff;
-+ out[k++] = (rgbbytes >> 8) & 0xff;
-+ Y = *pY++;
-+ Cr = *pCr++;
-+ Cb = *pCb++;
-+ YCrCb2RGB(Y, Cr, Cb, &r, &g, &b);
-+ r = r >> 3;
-+ g = g >> 2;
-+ b = b >> 3;
-+ if (rev_order)
-+ rgbbytes = b + (g << 5) + (r << (5 + 6));
-+ else
-+ rgbbytes = r + (g << 5) + (b << (5 + 6));
-+ out[k++] = rgbbytes & 0xff;
-+ out[k++] = (rgbbytes >> 8) & 0xff;
++ if (!dev->read_endpoint) {
++ dev_err(&interface->dev, "Could not find bulk-in endpoint");
++ goto error;
+ }
-+ return;
-+}
-+
-+/** retrieve FX2 firmware version. future use.
-+ * @param dev pointer to device extension
-+ * @return -1 for fail, else returns firmware version as an int(16 bits)
-+ */
-+static int s2255_get_fx2fw(struct s2255_dev *dev)
-+{
-+ int fw;
-+ int ret;
-+ unsigned char transBuffer[64];
-+ ret = s2255_vendor_req(dev, VX_FW, 0, 0, transBuffer, 2, DIR_IN);
-+ if (ret < 0)
-+ dprintk(2, "get fw error: %x\n", ret);
-+ fw = transBuffer[0] + (transBuffer[1] << 8);
-+ dprintk(2, "Get FW %x %x\n", transBuffer[0], transBuffer[1]);
-+ return fw;
-+}
-+
-+module_init(usb_s2255_init);
-+module_exit(usb_s2255_exit);
-+MODULE_DESCRIPTION("Sensoray 2255 Video for Linux driver");
-+MODULE_AUTHOR("D.A.(Sensoray)");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/usb/image/s2255drv.h
-@@ -0,0 +1,235 @@
-+/*
-+ * Sensoray 2255 USB Linux driver
-+ *
-+ * Copyright (C) 2007-2008 by Sensoray Company Inc.
-+ * Dean Anderson
-+ *
-+ * 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, version 2.
-+ */
-+
-+#ifndef S2255DRIVER_H
-+#define S2255DRIVER_H
-+
-+
-+#define DIR_IN 0
-+#define DIR_OUT 1
-+/* firmware query */
-+#define VX_FW 0x30
-+
-+#define MAX_CHANNELS 4
-+#define FRAME_MARKER 0x2255DA4AL
-+#define MAX_PIPE_USBBLOCK (40*1024)
-+#define DEFAULT_PIPE_USBBLOCK (16*1024)
-+#define MAX_CHANNELS 4
-+#define MAX_PIPE_BUFFERS 1
-+#define SYS_FRAMES 4
-+/* maximum size is PAL full size plus room for the marker header(s) */
-+#define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096)
-+#define DEF_USB_BLOCK (4096)
-+#define LINE_SZ_4CIFS_NTSC 640
-+#define LINE_SZ_2CIFS_NTSC 640
-+#define LINE_SZ_1CIFS_NTSC 320
-+#define LINE_SZ_4CIFS_PAL 704
-+#define LINE_SZ_2CIFS_PAL 704
-+#define LINE_SZ_1CIFS_PAL 352
-+#define NUM_LINES_4CIFS_NTSC 240
-+#define NUM_LINES_2CIFS_NTSC 240
-+#define NUM_LINES_1CIFS_NTSC 240
-+#define NUM_LINES_4CIFS_PAL 288
-+#define NUM_LINES_2CIFS_PAL 288
-+#define NUM_LINES_1CIFS_PAL 288
-+#define LINE_SZ_DEF 640
-+#define NUM_LINES_DEF 240
-+
-+
-+/* predefined settings */
-+#define FORMAT_NTSC 1
-+#define FORMAT_PAL 2
+
-+#define SCALE_4CIFS 1 /* 640x480(NTSC) or 704x576(PAL) */
-+#define SCALE_2CIFS 2 /* 640x240(NTSC) or 704x288(PAL) */
-+#define SCALE_1CIFS 3 /* 320x240(NTSC) or 352x288(PAL) */
++ /* set intfdata */
++ usb_set_intfdata(interface, dev);
+
-+#define COLOR_YUVPL 1 /* YUV planar */
-+#define COLOR_YUVPK 2 /* YUV packed */
-+#define COLOR_RGB 3 /* RGB */
-+#define COLOR_Y8 4 /* monochrome */
++ dprintk(100, "after intfdata %p\n", dev);
+
-+/* frame decimation. Not implemented by V4L yet(experimental in V4L) */
-+#define FDEC_1 1 /* capture every frame. default */
-+#define FDEC_2 2 /* capture every 2nd frame */
-+#define FDEC_3 3 /* capture every 3rd frame */
-+#define FDEC_5 5 /* capture every 5th frame */
++ /* initialize COUNTING semaphores */
++ for (i = 0; i < MAX_CHANNELS; i++)
++ sema_init(&dev->sem_frms[i], 0);
+
-+/*-------------------------------------------------------
-+ * Default mode parameters.
-+ *-------------------------------------------------------*/
-+#define DEF_SCALE SCALE_4CIFS
-+#define DEF_COLOR COLOR_YUVPL
-+#define DEF_FDEC FDEC_1
-+#define DEF_BRIGHT 0
-+#define DEF_CONTRAST 0x5c
-+#define DEF_SATURATION 0x80
-+#define DEF_HUE 0
++ /* initialize device mutex */
++ mutex_init(&dev->lock);
+
-+/* usb config commands */
-+#define IN_DATA_TOKEN 0x2255c0de
-+#define CMD_2255 0xc2255000
-+#define CMD_SET_MODE (CMD_2255 | 0x10)
-+#define CMD_START (CMD_2255 | 0x20)
-+#define CMD_STOP (CMD_2255 | 0x30)
-+#define CMD_STATUS (CMD_2255 | 0x40)
++ init_timer(&dev->timer);
++ dev->timer.function = s2255_timer;
++ dev->fw_data = kzalloc(sizeof(struct complete_data), GFP_KERNEL);
++ if (!dev->fw_data)
++ goto error;
+
-+struct mode2255i {
-+ u32 format; /* input video format (NTSC, PAL) */
-+ u32 scale; /* output video scale */
-+ u32 color; /* output video color format */
-+ u32 fdec; /* frame decimation */
-+ u32 bright; /* brightness */
-+ u32 contrast; /* contrast */
-+ u32 saturation; /* saturation */
-+ u32 hue; /* hue (NTSC only)*/
-+ u32 single; /* capture 1 frame at a time (!=0), continuously (==0)*/
-+ u32 usb_block; /* block size. should be 4096 of DEF_USB_BLOCK */
-+ u32 restart; /* if DSP requires restart */
-+};
++ dev->timer.data = (unsigned long)dev->fw_data;
+
-+/* frame structure */
-+#define FRAME_STATE_UNUSED 0
-+#define FRAME_STATE_FILLING 1
-+#define FRAME_STATE_FULL 2
++ dev->fw_data->fw_size = sizeof(G_f2255usb) / sizeof(unsigned char);
++ dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
+
++ if (!dev->fw_data->fw_urb) {
++ dev_err(&interface->dev, "out of memory!\n");
++ goto error;
++ }
++ dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL);
++ if (!dev->fw_data->pfw_data) {
++ dev_err(&interface->dev, "out of memory!\n");
++ goto error;
++ }
+
-+struct framei {
-+ unsigned long size;
++ /* load the first chunk */
++ memcpy(dev->fw_data->pfw_data, G_f2255usb, CHUNK_SIZE);
++ dev->fw_data->fw_loaded = CHUNK_SIZE;
++ usb_fill_bulk_urb(dev->fw_data->fw_urb, dev->udev,
++ usb_sndbulkpipe(dev->udev, 2), dev->fw_data->pfw_data,
++ CHUNK_SIZE, s2255_fwchunk_complete, dev->fw_data);
++ /* loads v4l specific */
++ s2255_probe_v4l(dev);
++ /* load 2255 board specific */
++ s2255_board_init(dev);
+
-+ unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */
-+ void *lpvbits; /* image data */
-+ unsigned long cur_size; /* current data copied to it */
-+};
++ dev_info(&interface->dev, "Sensoray 2255 successfully loaded\n");
++ dprintk(4, "before probe done %p\n", dev);
+
-+/* image buffer structure */
-+struct bufferi {
-+ unsigned long dwFrames; /* number of frames in buffer */
-+ struct framei frame[SYS_FRAMES]; /* array of FRAME structures */
-+};
++ mod_timer(&dev->timer, jiffies + HZ);
+
-+#define DEF_MODEI_NTSC_CONT FORMAT_NTSC, DEF_SCALE, DEF_COLOR, \
-+ DEF_FDEC, DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, \
-+ DEF_HUE, 0, DEF_USB_BLOCK, 0
++ kref_get(&dev->kref);
++ return 0;
++error:
++ return retval;
++}
+
-+#define DEF_MODEI_PAL_CONT FORMAT_PAL, DEF_SCALE, DEF_COLOR, DEF_FDEC,\
-+ DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, DEF_HUE, 0, \
-+ DEF_USB_BLOCK, 0
++/* disconnect routine. when board is removed physically or with rmmod */
++static void s2255_disconnect(struct usb_interface *interface)
++{
++ struct s2255_dev *dev = NULL;
+
-+#define DEF_MODEI_NTSC_SING FORMAT_NTSC, DEF_SCALE, DEF_COLOR, DEF_FDEC,\
-+ DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, DEF_HUE, 1,\
-+ DEF_USB_BLOCK, 0
++ /* lock to prevent s2255_open() from racing s2255_disconnect() */
++ mutex_lock(&usb_s2255_open_mutex);
++ dprintk(1, "s2255: disconnect interface %p\n", interface);
++ dev = usb_get_intfdata(interface);
++ s2255_board_shutdown(dev);
++ if (dev->fw_data->fw_urb) {
++ dprintk(2, "kill URB\n");
++ usb_kill_urb(dev->fw_data->fw_urb);
++ usb_free_urb(dev->fw_data->fw_urb);
+
-+#define DEF_MODEI_PAL_SING FORMAT_PAL, DEF_SCALE, DEF_COLOR, DEF_FDEC, \
-+ DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, DEF_HUE, 1,\
-+ DEF_USB_BLOCK, 0
++ }
++ s2255_exit_v4l(dev);
++ if (dev->fw_data) {
++ kfree(dev->fw_data->pfw_data);
++ kfree(dev->fw_data);
++ }
++ usb_set_intfdata(interface, NULL);
++ kref_put(&dev->kref, s2255_destroy);
++ mutex_unlock(&usb_s2255_open_mutex);
++ dev_info(&interface->dev, "s2255usb now disconnected\n");
++}
+
-+struct s2255_dmaqueue {
-+ struct list_head active;
-+ struct list_head queued;
-+ struct timer_list timeout;
-+ /* thread for acquisition */
-+ struct task_struct *kthread;
-+ wait_queue_head_t wq;
-+ int frame;
-+ struct s2255_dev *dev;
-+ int channel;
++static struct usb_driver s2255_driver = {
++ .name = "s2255",
++ .probe = s2255_probe,
++ .disconnect = s2255_disconnect,
++ .id_table = s2255_table,
+};
+
-+/* for firmware loading */
-+#define FWSTATE_NOTLOADED 0
-+#define FWSTATE_SUCCESS 1
-+#define FWSTATE_FAILED 2
-+
-+typedef struct complete_data {
-+ int fw_loaded;
-+ int fw_size;
-+ struct urb *fw_urb;
-+ int fw_state;
-+ void *pfw_data;
-+} complete_data_t;
-+
-+struct s2255_pipeinfo;
-+
-+typedef struct s2255_pipeinfo {
-+ u32 max_transfer_size;
-+ u32 cur_transfer_size;
-+ u8 *pTransferBuffer;
-+ u32 transfer_flags;;
-+ u32 state;
-+ u32 prev_state;
-+ u32 urb_size;
-+ void *pStreamUrb;
-+ void *dev; /* back pointer to s2255_dev struct*/
-+ u32 err_count;
-+ u32 buf_index;
-+ u32 idx;
-+ u32 priority_set;
-+} s2255_pipeinfo_t;
-+
-+struct s2255_dev {
-+ int frames;
-+ int users[MAX_CHANNELS];
-+ struct mutex lock;
-+ int resources[MAX_CHANNELS];
-+ struct usb_device *udev;
-+ struct usb_interface *interface;
-+ u8 read_endpoint;
-+ struct semaphore sem_frms[MAX_CHANNELS]; /* frames ready */
-+ struct s2255_dmaqueue vidq[MAX_CHANNELS];
-+ struct video_device *vdev[MAX_CHANNELS];
-+ struct list_head s2255_devlist;
-+ struct timer_list timer;
-+ struct complete_data *fw_data;
-+ int board_num;
-+ int is_open;
-+ struct s2255_pipeinfo UsbPipes[MAX_PIPE_BUFFERS];
-+ struct bufferi buffer[MAX_CHANNELS];
-+ struct mode2255i mode[MAX_CHANNELS];
-+ int cur_frame[MAX_CHANNELS];
-+ int last_frame[MAX_CHANNELS];
-+ u32 cc; /* current channel */
-+ int b_acquire[MAX_CHANNELS];
-+ unsigned long req_image_size[MAX_CHANNELS];
-+ int bad_payload[MAX_CHANNELS];
-+ unsigned long frame_count[MAX_CHANNELS];
-+ int frame_ready;
-+ struct kref kref;
-+};
++static int __init usb_s2255_init(void)
++{
++ int result;
+
-+struct s2255_fmt {
-+ char *name;
-+ u32 fourcc;
-+ int depth;
-+};
++ /* register this driver with the USB subsystem */
++ result = usb_register(&s2255_driver);
+
-+/* buffer for one video frame */
-+struct s2255_buffer {
-+ /* common v4l buffer stuff -- must be first */
-+ struct videobuf_buffer vb;
-+ const struct s2255_fmt *fmt;
-+ /* future use */
-+ int reserved[32];
-+};
++ if (result)
++ err("usb_register failed. Error number %d", result);
+
-+struct s2255_fh {
-+ struct s2255_dev *dev;
-+ unsigned int resources;
-+ const struct s2255_fmt *fmt;
-+ unsigned int width;
-+ unsigned int height;
-+ struct videobuf_queue vb_vidq;
-+ enum v4l2_buf_type type;
-+ int channel;
-+};
++ dprintk(2, "s2255_init: done\n");
++ return result;
++}
+
++static void __exit usb_s2255_exit(void)
++{
++ usb_deregister(&s2255_driver);
++}
+
-+#endif
++module_init(usb_s2255_init);
++module_exit(usb_s2255_exit);
++MODULE_DESCRIPTION("Sensoray 2255 Video for Linux driver");
++MODULE_AUTHOR("D.A.(Sensoray)");
++MODULE_LICENSE("GPL");