/* sane - Scanner Access Now Easy.

   Copyright (C) 2006-2007 Gerard Klaver (gerard at gkall dot hobby dot nl)
   For the usb command and add_text parts of the sq930x 
   sane backend, pencam program are used.

   This file is part of the SANE package.

   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 (at your option) 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.

   */

/* 
	$Id: sq930x.h,v 1.7 2007/06/02 12:16:02 gerard Exp $
        update 14-04-2005*/

/* Commands supported by the vidcam. */

/*--------------------------------------------------------------------------*/

static inline int
getbitfield (unsigned char *pageaddr, int mask, int shift)
{
  return ((*pageaddr >> shift) & mask);
}

/*--------------------------------------------------------------------------*/

#include <stdio.h>

#define LIBUSB_TIMEOUT					1000	/* ms */

typedef unsigned char byte;

/*--------------------------------------------------------------------------*/

/* Black magic for color adjustment. */
struct dpi_color_adjust
{
  int resolution_x;		/* x-resolution  */
  int resolution_y;		/* y-resolution  */

  int z1_color_0;		/* 0, 1 or 2 */
  int z1_color_1;		/* idem */
  int z1_color_2;		/* idem */
};

/*--------------------------------------------------------------------------*/

enum Sq930x_Option
{
  /* Must come first */
  OPT_NUM_OPTS = 0,

  OPT_MODE_GROUP,
  OPT_MODE,			/* vidcam modes */
  OPT_RESOLUTION,		/* X and Y resolution */
  OPT_BRIGHTNESS,		/* brightness   */

  OPT_ENHANCEMENT_GROUP,
  OPT_TEXT,			/*text line */
  OPT_DECOMP,                   /*decompression mode */
  OPT_READ_FORMAT,		/*read format webcam image */
  OPT_WHITE_LEVEL_R,		/*white level red correction */
  OPT_WHITE_LEVEL_G,		/*white level green correction */
  OPT_WHITE_LEVEL_B,		/*white level blue correction */

  /* must come last: */
  OPT_NUM_OPTIONS
};

/*--------------------------------------------------------------------------*/

/* 
 * Video Camera supported by this backend. 
 */
struct vidcam_hardware
{
  /* USB stuff */
  SANE_Word vendor;
  SANE_Word product;
  SANE_Word class;
  enum
  {
  Sq930x_trust_3500t,
  Sq930x_MI360,
  Sq930x_creative_ultra_notebook,
  Sq930x_creative_live_motion,
  Sq930x_sweex_motion_tracking
  }
  sq930_sensor_ref;

  /* Readable names */
  const char *vendor_name;	/* brand on the box */
  const char *product_name;	/* name on the box */

  /* Resolutions supported in color mode. */
  const struct dpi_color_adjust *color_adjust;
};

#define COLOR_RAW_STR			SANE_I18N("Color RAW")
#define COLOR_RGB_STR			SANE_I18N("Color RGB")
/*--------------------------------------------------------------------------*/

/* Define a vidcam occurence. */
typedef struct Sq930x_Vidcam
{
  struct Sq930x_Vidcam *next;
  SANE_Device sane;

  char *devicename;
  SANE_Int fd;			/* device handle */

  /* USB handling */
  size_t buffer_size;		/* size of the buffer */
  SANE_Byte *buffer;		/* for USB transfer. */

  /* Bayer handling */
  size_t output_size;		/* size of the output */
  SANE_Byte *output;		/* for bayer conversion */
  
  size_t image_size;		/* allocated size of image */
  size_t image_begin;		/* first significant byte in image */
  size_t image_end;		/* first free byte in image */
  SANE_Byte *image;		/* keep the raw image here */

  /* USB control messages handling */
  size_t windoww_size;		/* size of window write */
  size_t windowr_size;		/* size of window read  */
  SANE_Byte *windoww;		/* for window write     */
  SANE_Byte *windowr;		/* for window read      */

  /* Scanner infos. */
  const struct vidcam_hardware *hw;	/* default options for that vidcam */

  SANE_Word *resolutions_list;
  SANE_Word *color_sequence_list;

  /* Scanning handling. */
  SANE_Bool scanning;		/* TRUE if a scan is running. */
  SANE_Bool deliver_eof;
  int x_resolution;		/* X resolution */
  int y_resolution;		/* Y resolution */
  int depth;			/* depth per color */
  unsigned int colour;
  int red_s;
  int green_s;
  int blue_s;
 
  SANE_Parameters s_params;
  enum
  {
    SQ930X_COLOR_RGB,
    SQ930X_COLOR,
    SQ930X_COLOR_RAW
  }
  scan_mode;

  size_t bytes_left;		/* number of bytes left to give to the backend */
  size_t real_bytes_left;	/* number of bytes left the vidcam will return. */
  int bytes_pixel;
  int text_line;
  int decomp_alg;
  int read_format;
  
  const struct dpi_color_adjust *color_adjust;

  SANE_Parameters params;

  /* Options */
  SANE_Option_Descriptor opt[OPT_NUM_OPTIONS];
  Option_Value val[OPT_NUM_OPTIONS];

  unsigned int video_mode;	/* 0x0100 = VGA, 0x0000 = CIF,
				 * 0x0300 = QVGA, 0x0200 = QCIF*/
  int SupportedModes;
  int HardwareConfig;
  int cwidth;			/* camera width */
  int cheight;

  int framecount;
  char picmsg_ps[50];

}
Sq930x_Vidcam;

/*--------------------------------------------------------------------------*/

/* Debug levels. 
 * Should be common to all backends. */

#define DBG_error0  0
#define DBG_error   1
#define DBG_sense   2
#define DBG_warning 3
#define DBG_inquiry 4
#define DBG_info    5
#define DBG_info2   6
#define DBG_proc    7
#define DBG_read    8
#define DBG_sane_init   10
#define DBG_sane_proc   11
#define DBG_sane_info   12
#define DBG_sane_option 13

/*--------------------------------------------------------*/

static SANE_Byte urb_init_4[0x08] = {
            0x03, 0x00, 0x12, 0x93, 0x0b, 0xf6, 0xc9, 0x00
};

/* ur8 same as urb129 ?*/
static SANE_Byte urb_init_8[0x15] = {
            0xfa, 0x03, 0x00, 0x00, 0xf8, 0x02, 0x01, 0xf8,
	    0xbe, 0x02, 0xf8, 0xc6, 0x04, 0xf8, 0x00, 0x08,
	    0xf8, 0x00, 0x09, 0xf8, 0x06
};

/* read urb 14 - 120*/
static SANE_Byte urb_init_116[0x08] = {
            0x03, 0x00, 0x12, 0x93, 0x0b, 0xf6, 0xc9, 0x00
};

/* urb 129 22 */
static SANE_Byte urb_init_129[0x15] = {
            0xfa, 0x03, 0x00, 0x00, 0xf8, 0x02, 0x01, 0xf8,
	    0xbe, 0x02, 0xf8, 0xc6, 0x04, 0xf8, 0x00, 0x08,
	    0xf8, 0x00, 0x09, 0xf8, 0x06
};

/* urb 130 23 */
static SANE_Byte urb_init_130[0x15] = {
            0x0b, 0xf8, 0xfe, 0x07, 0xf8, 0x84, 0x0c, 0xf8,
	    0x02, 0x0d, 0xf8, 0xf7, 0x0e, 0xf8, 0x03, 0x0f,
	    0xf8, 0x0b, 0x1c, 0xf8, 0x00
};

/* urb 131 24*/
static SANE_Byte urb_init_131[0x15] = {
            0x1e, 0xf8, 0x03, 0x1f, 0xf8, 0x0b, 0x3a, 0xf8,
	    0x00, 0x3b, 0xf8, 0x01, 0x3c, 0xf8, 0x00, 0x3d,
	    0xf8, 0x6b, 0x10, 0xf8, 0x03
};

/* urb 132 25*/
static SANE_Byte urb_init_132[0x15] = {
            0x12, 0xf8, 0x02, 0x13, 0xf8, 0x6f, 0x03, 0xf8,
	    0x00, 0x14, 0xf8, 0x00, 0x15, 0xf8, 0x44, 0x16,
	    0xf8, 0x00, 0x17, 0xf8, 0x48
};

/* urb 133 26*/
static SANE_Byte urb_init_133[0x15] = {
            0x19, 0xf8, 0x25, 0x1a, 0xf8, 0x00, 0x1b, 0xf8,
	    0x3c, 0x2f, 0xf8, 0x03, 0x20, 0xf8, 0xff, 0x21,
	    0xf8, 0x0d, 0x22, 0xf8, 0xff
};

/* urb 134 27*/
static SANE_Byte urb_init_134[0x15] = {
            0x24, 0xf8, 0xfd, 0x25, 0xf8, 0x07, 0x26, 0xf8,
	    0xf0, 0x27, 0xf8, 0x0c, 0x28, 0xf8, 0xff, 0x29,
	    0xf8, 0x03, 0x2a, 0xf8, 0xff
};

/* urb 135 28 */
static SANE_Byte urb_init_135[0x15] = {
            0x2c, 0xf8, 0xfc, 0x2d, 0xf8, 0x01, 0x2e, 0xf8,
	    0x00, 0x30, 0xf8, 0x00, 0x31, 0xf8, 0x47, 0x32,
	    0xf8, 0x00, 0x33, 0xf8, 0x00
};

/* urb 136 29*/
static SANE_Byte urb_init_136[0x15] = {
            0x51, 0xf8, 0x00, 0x52, 0xf8, 0x00, 0x53, 0xf8,
	    0x24, 0x54, 0xf8, 0x00, 0x55, 0xf8, 0x0c, 0x56,
	    0xf8, 0x00, 0x57, 0xf8, 0x30
};

/* urb 137 30*/
static SANE_Byte urb_init_137[0x15] = {
            0x59, 0xf8, 0x18, 0x5a, 0xf8, 0x00, 0x5b, 0xf8,
	    0x3c, 0x5c, 0xf8, 0x00, 0x5d, 0xf8, 0x18, 0x5e,
	    0xf8, 0x00, 0x5f, 0xf8, 0x3c
};

/* urb 138 31*/
static SANE_Byte urb_init_138[0x15] = {
            0x61, 0xf8, 0x37, 0x62, 0xf8, 0xff, 0x63, 0xf8,
	    0x1d, 0x64, 0xf8, 0xff, 0x65, 0xf8, 0x98, 0x66,
	    0xf8, 0xff, 0x67, 0xf8, 0xc0
};

/* urb 139 32*/
static SANE_Byte urb_init_139[0x15] = {
            0x69, 0xf8, 0x37, 0x6c, 0xf8, 0x02, 0x6d, 0xf8,
	    0x1d, 0x6a, 0xf8, 0x00, 0x6b, 0xf8, 0x37, 0x6e,
	    0xf8, 0x02, 0x6f, 0xf8, 0x1d
};

/* urb 140 33*/
static SANE_Byte urb_init_140[0x15] = {
            0x71, 0xf8, 0xc6, 0x72, 0xf8, 0x02, 0x73, 0xf8,
	    0x04, 0x74, 0xf8, 0x01, 0x75, 0xf8, 0xc6, 0x76,
	    0xf8, 0x02, 0x77, 0xf8, 0x04
};

/* urb 141 34*/
static SANE_Byte urb_init_141[0x0c] = {
            0x79, 0xf8, 0x0f, 0x7a, 0xf8, 0xff, 0x7b, 0xf8,
	    0xff, 0x00, 0xf8, 0x03
};

/* urb 142, 143 data  35 36 */
static SANE_Byte urb_init_142[0x0c] = {
            0xf1, 0xf5, 0xff, 0xf2, 0xf5, 0x80, 0xf3, 0xf5,
	    0x80, 0xf4, 0xf5, 0xb3
};
static SANE_Byte urb_init_142a[0x0c] = {
            0xf1, 0xf5, 0x99, 0xf2, 0xf5, 0x80, 0xf3, 0xf5,
	    0x80, 0xf4, 0xf5, 0xa6
};
static SANE_Byte urb_init_142b[0x0c] = {
            0xf1, 0xf5, 0xff, 0xf2, 0xf5, 0x88, 0xf3, 0xf5,
	    0x88, 0xf4, 0xf5, 0xc0
};

/* urb 144 37 */
static SANE_Byte urb_init_144[0x0c] = {
            0xf6, 0xf5, 0x00, 0xf7, 0xf5, 0x00, 0xf8, 0xf5,
	    0x00, 0xf9, 0xf5, 0x00
};

/* urb 145 38 */
static SANE_Byte urb_init_145[0x0f] = {
            0x07, 0xf8, 0xff, 0x05, 0xf8, 0x80, 0x06, 0xf8,
	    0x00, 0x07, 0xf8, 0x7f, 0x00, 0xf8, 0x03
};

/* urb 146 39 */
static SANE_Byte urb_init_146[0x0f] = {
            0x07, 0xf8, 0xff, 0x05, 0xf8, 0x4e, 0x06, 0xf8,
	    0x00, 0x07, 0xf8, 0x7f, 0x00, 0xf8, 0x03
};

/* urb 147 40 */
static SANE_Byte urb_init_147[0x0f] = {
            0x07, 0xf8, 0xff, 0x05, 0xf8, 0xc0, 0x06, 0xf8,
	    0x48, 0x07, 0xf8, 0x7f, 0x00, 0xf8, 0x03
};

/* urb 148 41 */
static SANE_Byte urb_init_148[0x0f] = {
            0x07, 0xf8, 0xff, 0x05, 0xf8, 0x00, 0x06, 0xf8,
	    0x00, 0x07, 0xf8, 0x7f, 0x00, 0xf8, 0x03
};
/* urb 43 lun 
 * 43	out down	n/a	35.591	VENDOR_DEVICE	01 22 20 0e 00 a2 02 f0	
*/

static SANE_Byte urb_init_15043[0x20] = {
           0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xf0,
	   0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 
           0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f,
	   0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01 
	   };
	   /* 150-46*/
static SANE_Byte urb_init_150[0x20] = {
	    0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee, 
	    0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
    	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static SANE_Byte urb_init_150a[0x20] = {
	    0x01, 0x23, 0x20, 0x0e, 0x00, 0xa3, 0x02, 0xee, 
	    0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
    	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/*-----------------------------trust 3500*/
static SANE_Byte urb_init_22[0x12] = {
            0xfa, 0x03, 0x00, 0x32, 0xf3, 0xcc, 0x33, 0xf3,
	    0xcc, 0x34, 0xf3, 0xcc, 0x35, 0xf3, 0xcc, 0x3f,
	    0xf3, 0x00
	    };

static SANE_Byte urb_init_23[0x0e] = {
	    0x80, 0x40, 0x31, 0x00, 0x80, 0x00, 0x34, 0x01, 
	    0x80, 0x00, 0x3d, 0x06, 0x80, 0x8f
};

static SANE_Byte urb_init_24[0x06] = {
	    0x80, 0xe5, 0x04, 0x02, 0x80, 0x85
};

static SANE_Byte urb_init_25[0x12] = {
	    0x80, 0x20, 0x2b, 0x00, 0x80, 0x20, 0x2c, 0x00, 
	    0x80, 0x2a, 0x2d, 0x00, 0x80, 0x28, 0x2e, 0x00,
    	    0x80, 0x20
};

static SANE_Byte urb_init_34[0x20] = {
	    0x01, 0x02, 0x20, 0x03, 0x20, 0x82, 0x02, 0xe3, 
	    0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
    	    0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f,
	    0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00
};
